On 22 August 2011 20:57, Darius Jazayeri <[email protected]> wrote:
> On this week's Design Review Call at 9am Eastern time (our last one of these
> calls before we switch to the new call schedule, actually) we will be
> discussing how to solve HISP India's use case with the reporting module in
> the best/easiest way.
> (Offhand I imagine that would be implementing a SqlIndicator, but I must
> admit I haven't followed every aspect of this conversation.)

Darius thanks for the responsiveness on this.

Offhand it is looking to me that in the short term we might meet our
requirements through a similar module to the rwandareports and
objectgroupindicators.  Then find ourselves in the same corner as
Dave, looking at ways to refactor and harmonize on to firmer ground
:-)

I'm hoping to make the call.

Bob

>
> -Darius
>
> On Mon, Aug 22, 2011 at 9:13 AM, Bob Jolliffe <[email protected]> wrote:
>>
>> Thanks Dave (and Lara) for the explanations.  Some comments below ...
>>
>> On 21 August 2011 21:56, Dave Thomas <[email protected]> wrote:
>> > Sure.  Here's an example (see attached;  sorry for the formatting -- i
>> > recommend setting your texteditor to nowrap).
>> >
>> > There's a bit of an explanation necessary here.  First, note that the
>> > SQL returns exactly 2 items -- object_id (of any openmrs object), and
>> > patient_id.  An ObjectGroup is really a Set<Integer[]>  where the
>> > Integer[] is expected to contain 2 values -- object_id (any object),
>> > and THEN the patient_id (the owner of the object).  A bit of a hack, I
>> > admit, but it allows for intersection with a base Cohort (as discussed
>> > previously), and the whole operation happens without instantiating any
>> > of the objects (Encounter or Patient, in this case), meaning that it
>> > scales really well.  Again, this is all modeled against the core
>> > notion of a Cohort, and then SqlCohortDefinition, CohortIndicator,
>> > CohortIndicatorResult.
>> >
>> > Also, looking at the attached code, i can't remember why the location
>> > parameter was scoped differently than startDate and endDate, which
>> > needed to be explicitly added to the definition for some reason.
>> > Maybe this has changed?
>> >
>> > Finally, reportingobjectgroup has its own persistence mechanisms for
>> > sql definitions, indicator definitions, and report definitions.  I had
>> > to create my own services for these, because at the time, i remember
>> > not being able to register persistence handlers with the regular
>> > reporting xstream stuff from another module.  I also needed to create
>> > my own service for the objectgroup evaluator to use.  These created a
>> > ton of redundancy between reporting and reportingobjectgroup.  These
>> > could be merged by having the reporting module allow external
>> > registration of persistence handlers, and adding some very generic
>> > executeSQL methods to the core reporting service that return values
>> > according to generic interface types.
>> >
>> > Reading through the above, you can see why i'd like to get this on
>> > firmer footing.  Based on reading my own explanation, i may try the
>> > purely SqlDataSetDefinition approach this week, time allowing, just to
>> > see how it goes.
>> >
>> > That being said, we have this working just fine in production.  Our
>> > primary care report (from which the attached code excerpt is from)
>> > has about 30 total indicators, and runs in about 10 seconds against an
>> > Obs table with 5.6 million observations.
>>
>> I have a better idea on what you have done here and I suspect it
>> contains most of the clues of how to get on a "firmer footing".  First
>> it seems to me the Indicator interface and BaseIndicator class both
>> need to be enrichened.  There's quite a bit of stuff in
>> CohortIndicator which can quite easily even now be moved up to
>> BaseIndicator to avoid some of the replication (as well as constrain)
>> what you have had to do.  Things like aggregateor, logic expression,
>> indicator type etc.
>>
>> Getting into more meat, how about methods like setCohortDefinition(..)
>> and setObjectGroupDefinition(..)?  Do you foresee there could be a
>> more general setDefinition(..) method in the generic Indicator
>> interface?
>>
>> Regards
>> Bob
>>
>> >
>> > d
>> >
>> >
>> >
>> >
>> > On Sun, Aug 21, 2011 at 9:08 PM, Bob Jolliffe <[email protected]>
>> > wrote:
>> >> Hi Dave
>> >>
>> >> Is there some way we can take a look at the support module code to get
>> >> a better idea how you use it?  Sorry, I'm sure its obvious to you but
>> >> some of us are slow :-)
>> >>
>> >> Regards
>> >> Bob
>> >>
>> >> On 20 August 2011 12:00, Dave Thomas <[email protected]> wrote:
>> >>> Hi.  No, the indicator types are probably not exposed through the UI.
>> >>> We have another support module that registers our reports using
>> >>> code...
>> >>>
>> >>> d
>> >>>
>> >>> On Sat, Aug 20, 2011 at 12:49 PM, Bob Jolliffe <[email protected]>
>> >>> wrote:
>> >>>> On 20 August 2011 09:40, Dave Thomas <[email protected]> wrote:
>> >>>>> Hi.  For reportingobjectgroup, say you write a query that pulls up a
>> >>>>> group of encounters.  If you intersect this with the Cohort 'all
>> >>>>> patients in a particular program', it will filter out the encounters
>> >>>>> owned by patients not in the program.  Meaning that for any given
>> >>>>> patient in the program, there can still be N encounters in the
>> >>>>> result.
>> >>>>>  This, i think, avoids your problem of having duplicate patients in
>> >>>>> your Cohort query condensing to 1.
>> >>>>
>> >>>> OK.  That sounds good.  I just installed the module and I don't quite
>> >>>> see how to find these new indicator types.  Are they not exposed
>> >>>> through the UI?
>> >>>>
>> >>>>>I originally got hung up on the
>> >>>>> ability to intersect with a Cohort based on the default reporting
>> >>>>> framework UI, which optionally allows you to select a base Cohort,
>> >>>>> but
>> >>>>> in thinking about it, it allows us to ask interesting questions
>> >>>>> pretty
>> >>>>> easily.  Things like 'to what degree do patients in the HIV program
>> >>>>> also seek out primary care services outside of their monthly HIV
>> >>>>> visit' -- this is extremely straightforward using this intersection.
>> >>>>>
>> >>>>> Its funny that the perception is that the reporting framework is
>> >>>>> inflexible, because in truth I've found it to be the opposite.  I
>> >>>>> wrote the reportingobjectgroup module over a week,
>> >>>>
>> >>>> ... I think that defines what I mean by inflexible from the user's
>> >>>> perspective :-)  As a programming framework it seems mighty fine.
>> >>>>  But
>> >>>> I guess, as Mike has alluded to, the intention was that a range of
>> >>>> different indicator types can be implemented.  I guess that is where
>> >>>> we are now.
>> >>>>
>> >>>> Cheers
>> >>>> Bob
>> >>>>
>> >>>>> because i was
>> >>>>> facing the simple problem of counting primary care encounters at a
>> >>>>> health center over an arbitrary time period (usually a month).  So
>> >>>>> my
>> >>>>> thought was, 'what if I replicate SqlCohortDefinition functionality,
>> >>>>> almost exactly, but allow the IDs to correspond to the ID of any
>> >>>>> OpenmrsObject'.  This is the basic definition of an ObjectGroup.
>> >>>>>
>> >>>>> I took this approach having cracked open the code of the reporting
>> >>>>> framework, found CohortSQLDefinition, and then decided to copy it,
>> >>>>> figuring that it wouldn't be very hard...  It of course turned into
>> >>>>> a
>> >>>>> bit more of a project than i had expected, but we're using the
>> >>>>> results
>> >>>>> in production now, and we've been able to build some nice stuff on
>> >>>>> it.
>> >>>>>
>> >>>>> That being said, I don't really want to maintain the module forever,
>> >>>>> and Mike has pointed out to me that there were other approaches --
>> >>>>> one
>> >>>>> was building a SQLDataSetDefinition with a row-per-encounter
>> >>>>> structure
>> >>>>> and then building indicators off of this (not sure how much coding
>> >>>>> this would take?).  Another was writing a LogicDataSource and
>> >>>>> creating
>> >>>>> a Rule for 'given a patient, how many times did they come into the
>> >>>>> health center for a primary care visit over a give timeperiod?'  (is
>> >>>>> there a problem passing Reporting run-time parameters to logic
>> >>>>> Rules?).
>> >>>>>
>> >>>>> I don't have the bandwidth to try all three approaches,
>> >>>>> unfortunately,
>> >>>>> and I sort of wish that i had tried the SQLDataSetDefinition first
>> >>>>> (i'm not sure if it was already implemented at the time?).
>> >>>>> Ultimately, the goal should be to be able to write 5 lines of code
>> >>>>> defining the actual SQL you want, for any Object, and then define
>> >>>>> any
>> >>>>> number of indicators.  I'm not sure which approach is going to
>> >>>>> ultimately win, but i'm glad we're having this conversation, and i
>> >>>>> am
>> >>>>> willing to put in some programming time once there are firm
>> >>>>> specifications for how exactly a SQLIndicator works.  Transferring
>> >>>>> the
>> >>>>> objectgroup indicators we have in production to a more
>> >>>>> core-supported
>> >>>>> strategy would make me feel like we're on slightly firmer ground.
>> >>>>>
>> >>>>> d
>> >>>>>
>> >>>>> On Sat, Aug 20, 2011 at 4:04 AM, Michael Seaton <[email protected]>
>> >>>>> wrote:
>> >>>>>> I see no problem at all with a SqlIndicator, and I doubt that there
>> >>>>>> is any
>> >>>>>> reason why this wouldn't "just work" with the SDMX-HD module.  We
>> >>>>>> always
>> >>>>>> envisioned there would be all sorts of Indicator implementations
>> >>>>>> (or
>> >>>>>> Aggregated Data Element implementations for you Bob) - the
>> >>>>>> CohortIndicator
>> >>>>>> was just meant to be the beginning.
>> >>>>>>
>> >>>>>> As an alternative (or in addition), we could consider implementing
>> >>>>>> something
>> >>>>>> like a AggregatedDataSetColumnIndicator, which takes in:
>> >>>>>>
>> >>>>>> 1. A Mapped<DataSetDefinition>
>> >>>>>> 2. A column name
>> >>>>>> 3. An Aggregation
>> >>>>>>
>> >>>>>> Since we already have SqlDataSetDefinitions implemented, which
>> >>>>>> simply return
>> >>>>>> a table of Data that can contain absolutely anything, this
>> >>>>>> indicator would
>> >>>>>> wrap on of these, and then perform a particular aggregation on one
>> >>>>>> of the
>> >>>>>> columns in order to produce an Indicator value.  This would be
>> >>>>>> pretty easy
>> >>>>>> to implement...
>> >>>>>>
>> >>>>>> Bob - are either of these something you would be interested in
>> >>>>>> taking on
>> >>>>>> development-wise, or would you need one of us to take this on soon?
>> >>>>>>
>> >>>>>> Mike
>> >>>>>>
>> >>>>>>
>> >>>>>>
>> >>>>>> On 08/19/2011 05:08 PM, Bob Jolliffe wrote:
>> >>>>>>>
>> >>>>>>> On 19 August 2011 19:18, Dave Thomas<[email protected]>  wrote:
>> >>>>>>>>
>> >>>>>>>> This is exactly what the reportingobjectgroup module that i wrote
>> >>>>>>>> was
>> >>>>>>>> for -- the idea that you might want to use SQL to select groups
>> >>>>>>>> of any
>> >>>>>>>> OpenmrsObject, and still be able to intersect it with a base
>> >>>>>>>> cohort.
>> >>>>>>>
>> >>>>>>> Hi Dave.
>> >>>>>>>
>> >>>>>>> I haven't looked at the reportingobjectgroup module yet.  That was
>> >>>>>>> going to be step two after we figured out the "easy" reported
>> >>>>>>> dataelements which involved counting heads rather than counting
>> >>>>>>> other
>> >>>>>>> openmrs objects.  And I'm not sure that I understand fully the
>> >>>>>>> nuances
>> >>>>>>> of what you say above but I am worried that you still want to
>> >>>>>>> intersect with a base cohort ... as long as we are talking of a
>> >>>>>>> cohort
>> >>>>>>> then I'm guessing we don't count the same person twice.  So if I
>> >>>>>>> want
>> >>>>>>> to know how many opd encounters there were last month,
>> >>>>>>> "intersecting"
>> >>>>>>> this with a base cohort sounds like it will filter out the
>> >>>>>>> duplicates
>> >>>>>>> which will again produce an incorrect result.  Or maybe I am wrong
>> >>>>>>> -
>> >>>>>>> sorry to be speaking from ignorance having not yet looked at the
>> >>>>>>> module.
>> >>>>>>>
>> >>>>>>>> I'd really like to talk strategy about how to roll this module
>> >>>>>>>> into
>> >>>>>>>> reporting core (or substitute a core solution for the things we
>> >>>>>>>> already have built on it).
>> >>>>>>>
>> >>>>>>>  From our perspective (at least me and Viet :-) ) we are looking
>> >>>>>>> for a
>> >>>>>>> sweet spot.  The implementors of the highly customized version of
>> >>>>>>> openmrs running in Shimla, India, have already to a large extent
>> >>>>>>> "solved" their reporting problems by creating Birt reports
>> >>>>>>> containing
>> >>>>>>> the various odds and sods of aggregate dataelements they need to
>> >>>>>>> produce.  The flexibility of using birt meant they could execute
>> >>>>>>> whatever queries they want to populate the various reports.
>> >>>>>>>
>> >>>>>>> The downside being that the query, the data and the presentation
>> >>>>>>> all
>> >>>>>>> become hopelessly entangled in the birt report.  And this doesn't
>> >>>>>>> really help when you want to produce data to be consumed by
>> >>>>>>> another
>> >>>>>>> system (eg dhis).  Its possible of course to extract the data from
>> >>>>>>> the
>> >>>>>>> birt report but that is a bit of a hack, particularly when you
>> >>>>>>> need to
>> >>>>>>> map the anonymous birt dataelements.  Having aggregated
>> >>>>>>> dataelement
>> >>>>>>> (or indicator) objects defined within the system makes much more
>> >>>>>>> sense.
>> >>>>>>>
>> >>>>>>> The strength of the reporting module, and why I have been its
>> >>>>>>> loudest
>> >>>>>>> advocate, is that it separates the notion of reported dataelements
>> >>>>>>> (or
>> >>>>>>> Indicators as they are known as in this context) from the
>> >>>>>>> rendering or
>> >>>>>>> presentation of reports.  I am going to continue to use the term
>> >>>>>>> aggregate dataelement rather than indicator, but otherwise the
>> >>>>>>> semantics are not that important for the current discussion.  The
>> >>>>>>> ability to define aggregate dataelements, datasets and composite
>> >>>>>>> reports independently of how they are rendered is really a
>> >>>>>>> powerful
>> >>>>>>> and even essential notion if we are to have a reporting capability
>> >>>>>>> which meets a wide variety of use cases.  So the reporting module
>> >>>>>>> really does move in the right direction ...
>> >>>>>>>
>> >>>>>>> But at the highest level of abstraction, an aggregate dataelement
>> >>>>>>> object need only have a name, a description, and a mechanism
>> >>>>>>> (query)
>> >>>>>>> for deriving a value.  It should not be a cast iron requirement
>> >>>>>>> that
>> >>>>>>> there is an underlying cohort derived directly, or via an
>> >>>>>>> intersection.  I can see for many cases this is very useful ... ie
>> >>>>>>> to
>> >>>>>>> have an underlying cohort to drill down into.  But equally often
>> >>>>>>> it is
>> >>>>>>> not and all you want is a count or some other aggregation.  So
>> >>>>>>> what we
>> >>>>>>> find currently is that people argue that using the reporting
>> >>>>>>> module is
>> >>>>>>> too inflexible and don't understand why we can produce certain
>> >>>>>>> reports
>> >>>>>>> relatively simply in birt, but not in the reporting module.  And
>> >>>>>>> naturally conclude that we should stick with Birt.
>> >>>>>>>
>> >>>>>>> In order to find the sweet spot of retaining the flexibility of
>> >>>>>>> birt
>> >>>>>>> together with the organising structure of the reporting module, it
>> >>>>>>> seems we need to have a class of aggregate dataelement whose only
>> >>>>>>> constraint is that it must result in a number, but which can be
>> >>>>>>> derived from any sql query.  I think this is what Darius is also
>> >>>>>>> foreseeing in his SqlIndicator.  If we had such SqlIndicators, we
>> >>>>>>> could (i) reuse the queries which have already been developed for
>> >>>>>>> birt
>> >>>>>>> and (ii) render the resulting reports in various ways.  I think I
>> >>>>>>> even
>> >>>>>>> suggested in a previous mail that an ideal outcome of this might
>> >>>>>>> be
>> >>>>>>> that one of the possible renderings could in fact be a Birt
>> >>>>>>> report, in
>> >>>>>>> which case we will have closed the circle and have available all
>> >>>>>>> the
>> >>>>>>> presentation capabilities of Birt, but separated the definition of
>> >>>>>>> aggregated dataelements from the presentation of them.
>> >>>>>>>
>> >>>>>>> Apologies if I have misinterpreted many things re cohorts,
>> >>>>>>> intersections etc.  And if the reportingobject module meets the
>> >>>>>>> above
>> >>>>>>> requirement then I am already delighted.  I'm going to look at it
>> >>>>>>> tonight ...
>> >>>>>>>
>> >>>>>>> Regards
>> >>>>>>> Bob
>> >>>>>>>
>> >>>>>>>
>> >>>>>>>> d
>> >>>>>>>>
>> >>>>>>>> On Fri, Aug 19, 2011 at 5:30 PM, Darius Jazayeri
>> >>>>>>>> <[email protected]>  wrote:
>> >>>>>>>>>
>> >>>>>>>>> We talked off-list, and it turns out that:
>> >>>>>>>>>
>> >>>>>>>>> Many/most of the indicators Bob wants to build are not really
>> >>>>>>>>> cohort
>> >>>>>>>>> indicators, but rather counts of encounters, obs, log entries,
>> >>>>>>>>> etc.
>> >>>>>>>>> They'd mostly be calculated via SQL.
>> >>>>>>>>> They need to be able to export these via the sdmx-hd module,
>> >>>>>>>>> into DHIS.
>> >>>>>>>>>
>> >>>>>>>>> @Mike, @Ryan,
>> >>>>>>>>> If we were to do a SqlIndicator implementation (which wouldn't
>> >>>>>>>>> be too
>> >>>>>>>>> much
>> >>>>>>>>> work), would that easily fit into the current SDMX-HD export
>> >>>>>>>>> module? Or
>> >>>>>>>>> is
>> >>>>>>>>> that hardcoded to cohort indicators? And how much work would it
>> >>>>>>>>> be to
>> >>>>>>>>> change
>> >>>>>>>>> that?
>> >>>>>>>>> -Darius
>> >>>>>>>>>
>> >>>>>>>>> On Fri, Aug 19, 2011 at 7:33 AM, Bob
>> >>>>>>>>> Jolliffe<[email protected]>
>> >>>>>>>>>  wrote:
>> >>>>>>>>>>
>> >>>>>>>>>> On 19 August 2011 15:07, Darius
>> >>>>>>>>>> Jazayeri<[email protected]>
>> >>>>>>>>>>  wrote:
>> >>>>>>>>>>>
>> >>>>>>>>>>> You're not doing a count distinct, so if your
>> >>>>>>>>>>> opd_patient_queue_log
>> >>>>>>>>>>> can
>> >>>>>>>>>>> have
>> >>>>>>>>>>> the same patient_id more than once, that'd be why you get a
>> >>>>>>>>>>> difference.
>> >>>>>>>>>>> -Darius
>> >>>>>>>>>>
>> >>>>>>>>>> Thanks Darius.  You are absolutely right.  I also just figured
>> >>>>>>>>>> that
>> >>>>>>>>>> out a few minutes ago.
>> >>>>>>>>>>
>> >>>>>>>>>> Though it has left me with a sinking feeling about how to use
>> >>>>>>>>>> the
>> >>>>>>>>>> reporting module.  It makes sense now that the penny has slowly
>> >>>>>>>>>> dropped, that a cohort query is in fact a query to select a
>> >>>>>>>>>> distinct
>> >>>>>>>>>> group, or cohort, of patients.  Which you could then drill down
>> >>>>>>>>>> into
>> >>>>>>>>>> etc.
>> >>>>>>>>>>
>> >>>>>>>>>> But at the level of a typical service indicator, I am really
>> >>>>>>>>>> not
>> >>>>>>>>>> interested in who the individual patients are.  I need to know
>> >>>>>>>>>> how
>> >>>>>>>>>> many patients had OPD encounters this month, for example.
>> >>>>>>>>>>  Using a
>> >>>>>>>>>> cohort query for this seemed to make sense, but of course it
>> >>>>>>>>>> doesn't
>> >>>>>>>>>> as it filters the duplicate patients.  So I should in fact be
>> >>>>>>>>>> counting
>> >>>>>>>>>> the encounters rather than the patients, but then its not a
>> >>>>>>>>>> cohort
>> >>>>>>>>>> query :-(
>> >>>>>>>>>>
>> >>>>>>>>>>> On Fri, Aug 19, 2011 at 5:37 AM, Bob
>> >>>>>>>>>>> Jolliffe<[email protected]>
>> >>>>>>>>>>> wrote:
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> I am trying to compose an indicator which makes use of a join
>> >>>>>>>>>>>> with a
>> >>>>>>>>>>>> custom table.
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> Does anyone have an idea why executing the query directly as:
>> >>>>>>>>>>>> mysql -u ... -e 'Select count(patient.patient_id) from
>> >>>>>>>>>>>> patient inner
>> >>>>>>>>>>>> join opd_patient_queue_log on
>> >>>>>>>>>>>> patient.patient_id=opd_patient_queue_log.patient_id'
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> results in 16593,
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> but when I create a sql cohort query as above (without the
>> >>>>>>>>>>>> count), I
>> >>>>>>>>>>>> get a result of 13592.
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> How does openmrs count the size of the resultset?  It seems
>> >>>>>>>>>>>> its not a
>> >>>>>>>>>>>> simple count ...
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> Regards
>> >>>>>>>>>>>> Bob
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> _________________________________________
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> To unsubscribe from OpenMRS Developers' mailing list, send an
>> >>>>>>>>>>>> e-mail
>> >>>>>>>>>>>> to
>> >>>>>>>>>>>> [email protected] with "SIGNOFF openmrs-devel-l" in
>> >>>>>>>>>>>> the
>> >>>>>>>>>>>>  body
>> >>>>>>>>>>>> (not
>> >>>>>>>>>>>> the subject) of your e-mail.
>> >>>>>>>>>>>>
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>>>>>>>>
>> >>>>>>>>>>> ________________________________
>> >>>>>>>>>>> Click here to unsubscribe from OpenMRS Developers' mailing
>> >>>>>>>>>>> list
>> >>>>>>>>>>
>> >>>>>>>>>> _________________________________________
>> >>>>>>>>>>
>> >>>>>>>>>> To unsubscribe from OpenMRS Developers' mailing list, send an
>> >>>>>>>>>> e-mail to
>> >>>>>>>>>> [email protected] with "SIGNOFF openmrs-devel-l" in
>> >>>>>>>>>> the  body
>> >>>>>>>>>> (not
>> >>>>>>>>>> the subject) of your e-mail.
>> >>>>>>>>>>
>> >>>>>>>>>>
>> >>>>>>>>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>>>>>>
>> >>>>>>>>> ________________________________
>> >>>>>>>>> Click here to unsubscribe from OpenMRS Developers' mailing list
>> >>>>>>>>
>> >>>>>>>> _________________________________________
>> >>>>>>>>
>> >>>>>>>> To unsubscribe from OpenMRS Developers' mailing list, send an
>> >>>>>>>> e-mail to
>> >>>>>>>> [email protected] with "SIGNOFF openmrs-devel-l" in the
>> >>>>>>>>  body (not
>> >>>>>>>> the subject) of your e-mail.
>> >>>>>>>>
>> >>>>>>>>
>> >>>>>>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>>>>>
>> >>>>>>> _________________________________________
>> >>>>>>>
>> >>>>>>> To unsubscribe from OpenMRS Developers' mailing list, send an
>> >>>>>>> e-mail to
>> >>>>>>> [email protected] with "SIGNOFF openmrs-devel-l" in the
>> >>>>>>>  body (not
>> >>>>>>> the subject) of your e-mail.
>> >>>>>>>
>> >>>>>>>
>> >>>>>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>>>
>> >>>>>> _________________________________________
>> >>>>>>
>> >>>>>> To unsubscribe from OpenMRS Developers' mailing list, send an
>> >>>>>> e-mail to
>> >>>>>> [email protected] with "SIGNOFF openmrs-devel-l" in the
>> >>>>>>  body (not
>> >>>>>> the subject) of your e-mail.
>> >>>>>>
>> >>>>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>>>
>> >>>>>
>> >>>>> _________________________________________
>> >>>>>
>> >>>>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail
>> >>>>> to [email protected] with "SIGNOFF openmrs-devel-l" in the  
>> >>>>> body
>> >>>>> (not the subject) of your e-mail.
>> >>>>>
>> >>>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>>
>> >>>>
>> >>>> _________________________________________
>> >>>>
>> >>>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail
>> >>>> to [email protected] with "SIGNOFF openmrs-devel-l" in the  
>> >>>> body
>> >>>> (not the subject) of your e-mail.
>> >>>>
>> >>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>>
>> >>>
>> >>> _________________________________________
>> >>>
>> >>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail
>> >>> to [email protected] with "SIGNOFF openmrs-devel-l" in the  
>> >>> body
>> >>> (not the subject) of your e-mail.
>> >>>
>> >>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>>
>> >>
>> >> _________________________________________
>> >>
>> >> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to
>> >> [email protected] with "SIGNOFF openmrs-devel-l" in the  body 
>> >> (not
>> >> the subject) of your e-mail.
>> >>
>> >> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >>
>> >
>> > _________________________________________
>> >
>> > To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to
>> > [email protected] with "SIGNOFF openmrs-devel-l" in the  body 
>> > (not
>> > the subject) of your e-mail.
>> >
>> > [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>> >
>>
>> _________________________________________
>>
>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to
>> [email protected] with "SIGNOFF openmrs-devel-l" in the  body (not
>> the subject) of your e-mail.
>>
>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]
>
> ________________________________
> Click here to unsubscribe from OpenMRS Developers' mailing list

_________________________________________

To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to 
[email protected] with "SIGNOFF openmrs-devel-l" in the  body (not 
the subject) of your e-mail.

[mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

Reply via email to