Package: edc-timepoint
edc-timepointLock a “timepoint” from further editing once data is cleaned and reviewed.With moduleedc_timepointa data manager or supervisor is able to flag a model instance, that represents a timepoint, as closed to further edit. A good candidate for a “timepoint” model is one that is used to cover other data collection, such as anedc_appointment.Appointment. When the appointment status is set to something like ‘complete’ the timepoint status is set toclosedand no further edits are allowed for data covered by that appointment.Configuring the Timepoint ModelSelect a model that represent a timepoint. The model should at least have adatetimefield and astatusfield. For exampleAppointment:classAppointment(TimepointModelMixin,BaseUuidModel):appt_datetime=models.DateTimeField(verbose_name='Appointment date and time')appt_status=models.CharField(verbose_name='Status',choices=APPT_STATUS,max_length=25,default='NEW')TheTimepointModelMixinadds fields and methods prefixed astimepoint_<something>. There is also a signal that is loaded in theAppConfig.readythat resets the timepoint attributes shouldAppointment.appt_statuschange fromDONE.Only fieldtimepoint_statusis meant to be edited by the user. The othertimepoint_<something>are managed automatically.In your projectsapps.pysubclassedc_timepoint.apps.AppConfigand declareAppointmentas a timepoint model by creating aTimepointinstance and appending it toAppConfig.timepoints:fromdjango.appsimportAppConfigasDjangoAppConfigfromedc_timepoint.appsimportAppConfigasEdcTimepointAppConfigParentfromedc_timepoint.timepointimportTimepointclassAppConfig(DjangoAppConfig):name='example'classEdcTimepointAppConfig(EdcTimepointAppConfigParent):timepoints=TimepointCollection(timepoints=[Timepoint(model='example.appointment',datetime_field='appt_datetime',status_field='appt_status',closed_status='DONE')])The user updates theAppointmentnormally closing it when the appointment is done. Then a data manager or supervisor can close theAppointmentto further edit once the data has been reviewed.To close theAppointmentto further edit the code needs to call thetimepoint_close_timepointmethod:appointment=Appointment.objects.create(**options)appointment.appt_status='DONE'appointment.timepoint_close_timepoint()If theappointment.appt_statusis notDONEwhentimepoint_close_timepointis called, aTimepointErroris raised.If the appointment is successfully closed to further edit, any attempts to callappointment.save()will raise aTimepointError.TheAppointmentmay be re-opened for edit by calling methodtimepoint_open_timepoint.Configuring others to use the Timepoint ModelContinuing with the example above whereAppointmentis the timepoint model.To prevent further edits to models related toAppointment, configure the model with theTimepointLookupModelMixinand theTimepointLookupclass. These models will refer to the timepoint model onsave.For example:classVisitTimepointLookup(TimepointLookup):timepoint_related_model_lookup='appointment'classVisitModel(TimepointLookupModelMixin,BaseUuidModel):timepoint_lookup_cls=VisitTimepointLookupappointment=models.ForeignKey(Appointment)report_datetime=models.DateTimeField(default=timezone.now)If the timepoint model’stimepoint_statusisclosed, any attempt to create or modifyVisitModelwill raise aTimepointClosedexception.