class AnalysisRequestSchemaExtender(object): """Schema Extender for Sample objects """ adapts(IAnalysisRequest) implements(IOrderableSchemaExtender, IBrowserLayerAwareExtender) # Modify the schema only if senaite.panic is installed layer = ISenaitePanicLayer custom_fields = [ # Stores if a panic email has been sent ExtBooleanField( "PanicEmailAlertSent", default=False, widget=BooleanWidget(visible=False, ), ), ] def __init__(self, context): self.context = context def getOrder(self, schematas): return schematas def getFields(self): return self.custom_fields
class BikaSetupSchemaExtender(object): adapts(IBikaSetup) implements(ISchemaExtender) fields = [ ExtFixedPointField( 'LevyAmount', schemata='Accounting', default='0.00', widget=DecimalWidget( label=_("Levy Amount"), description= _("The levy percentage the university or parent organisation raises on all invoiced amounts" ), )), ExtRecordsField( 'StoragePricing', schemata='Storage', subfields=('storage_type', 'price', 'storage_type_uid'), subfield_hidden={'storage_type_uid': True}, required_subfields=('storage_type', 'price', 'storage_type_uid'), subfield_sizes={ 'storage_type': 50, 'price': 5 }, subfield_labels={ 'storage_type': _('Storage Type'), 'price': _('Price') }, widget=RecordsWidget( label=_("Storage Pricing"), description=_( "Set Sample storage pricing depending on storage type."), allowDelete=False, combogrid_options={ 'storage_type': { 'colModel': [{ 'columnName': 'storage_type', 'width': '30', 'label': _('Title') }, { 'columnName': 'Description', 'width': '70', 'label': _('Description') }, { 'columnName': 'storage_type_uid', 'hidden': True }], 'url': 'getstoragetypes', 'showOn': True, 'width': '550px' }, }, )), ExtBooleanField( 'ShowPartitions', schemata="Analyses", default=False, widget=BooleanWidget( label=_("Display individual sample partitions "), description=_( "Turn this on if you want to work with sample partitions") ), ), ] def __init__(self, context): self.context = context def getFields(self): return self.fields
class AnalysisRequestSchemaExtender(object): adapts(IAnalysisRequest) implements(IOrderableSchemaExtender) def __init__(self, context): self.context = context fields = [ ExtReferenceField( 'Doctor', allowed_types=('Doctor', ), referenceClass=HoldingReference, relationship='AnalysisRequestDoctor', widget=ReferenceWidget( label=_('Doctor'), size=20, render_own_label=True, visible={ 'add': 'edit', 'secondary': 'disabled' }, catalog_name='portal_catalog', base_query={ 'is_active': True, }, minLength=3, showOn=True, add_button={ 'visible': True, 'url': 'doctors/portal_factory/Doctor/new/edit', 'return_fields': ['Firstname', 'Surname'], }), ), ExtReferenceField( 'Patient', required=1, allowed_types=('Patient', ), referenceClass=HoldingReference, relationship='AnalysisRequestPatient', read_permission=ViewPatients, write_permission=permissions.ModifyPortalContent, widget=ReferenceWidget( label=_('Patient'), size=20, render_own_label=True, visible={ 'add': 'edit', 'secondary': 'disabled' }, catalog_name='bikahealth_catalog_patient_listing', search_fields=('listing_searchable_text', ), base_query={ 'is_active': True, 'sort_limit': 50, 'sort_on': 'getPatientID', 'sort_order': 'ascending' }, colModel=[ { 'columnName': "getPatientID", 'width': '30', 'label': _('PID'), 'align': 'left' }, { 'columnName': "getClientPatientID", 'width': '30', 'label': _('CPID'), 'align': 'left' }, { 'columnName': 'Title', 'width': '30', 'label': _('Fullname'), 'align': 'left' }, ], minLength=3, showOn=True, add_button={ 'visible': True, 'url': 'patients/portal_factory/Patient/new/edit', 'return_fields': ['Firstname', 'Surname'], 'js_controllers': [ '#patient-base-edit', ], 'overlay_handler': 'HealthPatientOverlayHandler', }), ), ExtBooleanField( 'PanicEmailAlertToClientSent', default=False, widget=BooleanWidget(visible={ 'edit': 'invisible', 'view': 'invisible', 'add': 'invisible' }, ), ), ExtStringField( 'ClientPatientID', searchable=True, required=0, read_permission=ViewPatients, write_permission=permissions.ModifyPortalContent, widget=ReferenceWidget( label=_("Client Patient ID"), size=20, render_own_label=True, visible={ 'add': 'edit', 'secondary': 'disabled' }, catalog_name='bikahealth_catalog_patient_listing', portal_types=('Patient', ), search_field='getClientPatientID', base_query={ 'is_active': True, 'sort_limit': 50, 'sort_on': 'getClientPatientID', 'sort_order': 'ascending' }, colModel=[ { 'columnName': "getPatientID", 'width': '30', 'label': _('PID'), 'align': 'left' }, { 'columnName': "getClientPatientID", 'width': '30', 'label': _('CPID'), 'align': 'left' }, { 'columnName': 'Title', 'width': '30', 'label': _('Fullname'), 'align': 'left' }, ], ui_item="getClientPatientID", minLength=3, showOn=True, ), ), ] def getOrder(self, schematas): default = schematas['default'] default.remove('Patient') default.remove('Doctor') default.remove('ClientPatientID') default.insert(default.index('Template'), 'ClientPatientID') default.insert(default.index('Template'), 'Patient') default.insert(default.index('Template'), 'Doctor') schematas['default'] = default return schematas def getFields(self): return self.fields
class AnalysisRequestSchemaExtender(object): adapts(IAnalysisRequest) implements(IOrderableSchemaExtender, IBrowserLayerAwareExtender) layer = INalLimsLayer fields = [ ExtStringField( 'PlantType', widget=StringWidget( label="Plant Type (Sap Samples)", description="The Plant Species or Crop the sample was taken from", render_own_label=True, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ExtStringField( 'Variety', widget=StringWidget( label="Variety (Sap Samples)", description="The Plant Variety or Cultivar the sample was taken from", render_own_label=True, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ExtStringField( 'GrowthStage', widget=StringWidget( label="Growth Stage (Sap Samples)", description="The development stage of the plant the sample was taken from", render_own_label=True, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ExtBooleanField( 'NewLeaf', widget=BooleanWidget( label="New Leaf (Sap Samples)", description="The sample is from the new growth of a plant", render_own_label=True, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ExtStringField( 'InternalLabID', widget=StringWidget( label="Internal Lab Sample ID", description="The Lab ID from a printed COC (Ex. '001')", render_own_label=True, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ExtDateTimeField( 'DateOfSampling', required=1, widget=DateTimeWidget( label="Date Sampled", description="The Date the sample was taken", render_own_label=True, show_time=False, datepicker_nofuture=1, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ExtStringField( 'TimeOfSampling', widget=StringWidget( label="Time Sampled", description="The time of day the sample was taken", render_own_label=True, visible={ 'edit':'visible', 'view':'visible', 'add':'edit', 'header_table':'visible', }, ) ), ] def __init__(self, context): self.context = context def getOrder(self, schematas): return schematas def getFields(self): return self.fields
class SampleTypeSchemaExtender(object): adapts(ISampleType) implements(IOrderableSchemaExtender) fields = [ ExtReferenceField( 'Service', schemata='Analyses', multiValued=1, allowed_types=('AnalysisService', ), relationship='SampleTypeAnalysisService', widget=ProjectAnalysesWidget( label=_("Sample Analyses"), description= _("The analyses included in this sample type, grouped per category" ), )), ExtReferenceField( 'SampleMatrix', required=0, allowed_types=('SampleMatrix', ), vocabulary='SampleMatricesVocabulary', relationship='SampleTypeSampleMatrix', referenceClass=HoldingReference, widget=ReferenceWidget(checkbox_bound=0, label=_("Sample Matrix"), visible=False), ), ReferenceField( 'ContainerType', required=0, allowed_types=('ContainerType', ), vocabulary='ContainerTypesVocabulary', relationship='SampleTypeContainerType', widget=ReferenceWidget( checkbox_bound=0, label=_("Default Container Type"), visible=False, description=_( "The default container type. New sample partitions " "are automatically assigned a container of this " "type, unless it has been specified in more details " "per analysis service"), ), ), ExtReferenceField( 'SamplePoints', required=0, multiValued=1, allowed_types=('SamplePoint', ), vocabulary='SamplePointsVocabulary', relationship='SampleTypeSamplePoint', widget=bika_ReferenceWidget( label=_("Sample Points"), visible=False, description=_( "The list of sample points from which this sample " "type can be collected. If no sample points are " "selected, then all sample points are available."), ), ), ExtBooleanField('HasBabyNumber', default=False, widget=BooleanWidget( label=_("Has Baby Number"), description=_('Sample Type that has Baby No.'), )), ExtStringField( 'ChangeUserName', widget=StringWidget( label=_('ChangeUserName'), description=_( 'The user who created or last made a change to this sample.' ), visible={ 'view': 'invisible', 'edit': 'invisible' })), ExtDateTimeField( 'ChangeDateTime', widget=StringWidget( label=_('ChangeDateTime'), description= _('The date and time when the sample was created or last updated.' ), visible={ 'view': 'invisible', 'edit': 'invisible' })), ] def __init__(self, context): self.context = context def getFields(self): return self.fields def getOrder(self, schematas): return schematas
class BatchSchemaExtender(object): adapts(IBatch) implements(IOrderableSchemaExtender) fields = [ ExtReferenceField( 'Doctor', required=1, multiValued=0, allowed_types=('Doctor', ), referenceClass=HoldingReference, relationship='BatchDoctor', widget=ReferenceWidget( label=_("Doctor"), description="", render_own_label=False, visible={ 'edit': 'visible', 'view': 'visible' }, base_query={'is_active': True}, catalog_name='portal_catalog', showOn=True, colModel=[ { 'columnName': 'DoctorID', 'width': '20', 'label': _('Doctor ID') }, { 'columnName': 'Title', 'width': '80', 'label': _('Full Name') }, ], ), ), ExtReferenceField( 'Patient', required=1, multiValued=0, allowed_types=('Patient', ), referenceClass=HoldingReference, relationship='BatchPatient', widget=ReferenceWidget( label=_("Patient"), description="", render_own_label=False, visible={ 'edit': 'visible', 'view': 'visible' }, catalog_name='bikahealth_catalog_patient_listing', search_fields=('listing_searchable_text', ), base_query={ 'is_active': True, 'sort_limit': 50, 'sort_on': 'getPatientID', 'sort_order': 'ascending' }, colModel=[ { 'columnName': "getPatientID", 'width': '30', 'label': _('PID'), 'align': 'left' }, { 'columnName': "getClientPatientID", 'width': '30', 'label': _('CPID'), 'align': 'left' }, { 'columnName': 'Title', 'width': '30', 'label': _('Title'), 'align': 'left' }, ], showOn=True, ), ), ExtDateTimeField( 'OnsetDate', required=1, widget=DateTimeWidget(label=_('Onset Date'), ), ), ExtRecordsField( 'PatientAgeAtCaseOnsetDate', widget=SplittedDateWidget( label=_('Patient Age at Case Onset Date'), ), ), ExtBooleanField( 'OnsetDateEstimated', default=False, widget=BooleanWidget(label=_("Onset Date Estimated"), ), ), ExtRecordsField( 'ProvisionalDiagnosis', type='provisionaldiagnosis', subfields=('Code', 'Title', 'Description', 'Onset'), # Temporary fix: https://github.com/bikalabs/bika.health/issues/89 #required_subfields=('Title'), subfield_sizes={ 'Code': 7, 'Title': 20, 'Description': 35, 'Onset': 10 }, subfield_labels={ 'Code': _('Code'), 'Title': _('Provisional diagnosis'), 'Description': _('Description'), 'Onset': _('Onset') }, subfield_types={'Onset': 'datepicker_nofuture'}, widget=RecordsWidget( label='Provisional diagnosis', combogrid_options={ 'Title': { 'colModel': [{ 'columnName': 'Code', 'width': '10', 'label': _('Code') }, { 'columnName': 'Title', 'width': '30', 'label': _('Title') }, { 'columnName': 'Description', 'width': '60', 'label': _('Description') }], 'url': 'getsymptomsbytitle', 'showOn': True, 'width': "650px", }, 'Code': { 'colModel': [{ 'columnName': 'Code', 'width': '10', 'label': _('Code') }, { 'columnName': 'Title', 'width': '30', 'label': _('Title') }, { 'columnName': 'Description', 'width': '60', 'label': _('Description') }], 'url': 'getsymptomsbycode', 'showOn': True, 'width': "650px", }, 'Description': { 'colModel': [{ 'columnName': 'Code', 'width': '10', 'label': _('Code') }, { 'columnName': 'Title', 'width': '30', 'label': _('Title') }, { 'columnName': 'Description', 'width': '60', 'label': _('Description') }], 'url': 'getsymptomsbydesc', 'showOn': True, 'width': "650px", }, }, ), ), ExtTextField( 'AdditionalNotes', default_content_type='text/plain', allowable_content_types=('text/plain', ), default_output_type="text/plain", widget=TextAreaWidget(label=_('Additional notes'), ), ), ExtLinesField( 'CaseStatus', vocabulary=getCaseStatus(), widget=MultiSelectionWidget(format='checkbox', label=_("Case status")), ), ExtLinesField( 'CaseOutcome', vocabulary=getCaseOutcome(), widget=MultiSelectionWidget(format='checkbox', label=_("Case outcome")), ), ExtRecordsField( 'Symptoms', type='symptoms', subfields=('UID', 'Title', 'Description', 'Severity'), widget=CaseSymptomsWidget(label='Symptoms', ), ), ExtRecordsField( 'AetiologicAgents', type='aetiologicagents', subfields=('Title', 'Description', 'Subtype'), subfield_sizes={ 'Title': 15, 'Description': 25, 'Subtype': 10 }, subfield_labels={ 'Title': _('Aetiologic agent'), 'Description': _b('Description'), 'Subtype': _('Subtype') }, # Temporary fix: https://github.com/bikalabs/bika.health/issues/89 # required_subfields=('Title'), widget=RecordsWidget( label='Aetiologic agents', combogrid_options={ 'Title': { 'colModel': [{ 'columnName': 'Title', 'width': '30', 'label': _('Aetiologic agent') }, { 'columnName': 'Description', 'width': '60', 'label': _b('Description') }, { 'columnName': 'Subtype', 'width': '30', 'label': _('Subtype') }], 'url': 'getaetiologicagents', 'showOn': True, 'width': "650px", }, }, ), ), ExtIntegerField( 'HoursFasting', required=0, widget=IntegerWidget(label=_('Hours fasting'), ), ), ExtRecordsField( 'PatientCondition', widget=CasePatientConditionWidget(label='Patient condition', ), ), ExtRecordsField( 'MenstrualStatus', widget=CaseMenstrualStatusWidget(label='Menstrual status', ), ), ExtRecordsField( 'BasalBodyTemperature', widget=CaseBasalBodyTempWidget(label='Basal body temperature', ), ), ExtStringField( 'ClientPatientID', required=0, widget=ReferenceWidget( label=_b("Client Patient ID"), size=20, visible={ 'edit': 'invisible', 'view': 'visible', 'add': 'edit' }, catalog_name='bikahealth_catalog_patient_listing', portal_types=('Patient', ), search_fields=('getClientPatientID', ), base_query={ 'is_active': True, 'sort_limit': 50, 'sort_on': 'getClientPatientID', 'sort_order': 'ascending' }, force_all=False, colModel=[ { 'columnName': "getPatientID", 'width': '30', 'label': _('PID'), 'align': 'left' }, { 'columnName': "getClientPatientID", 'width': '30', 'label': _('CPID'), 'align': 'left' }, { 'columnName': 'Title', 'width': '30', 'label': _('Fullname'), 'align': 'left' }, # UID is required in colModel { 'columnName': 'UID', 'hidden': True }, ], ui_item="getClientPatientID", showOn=False, ), ), ] def __init__(self, context): self.context = context def getOrder(self, schematas): schematas['default'] = [ 'id', 'title', 'description', 'BatchID', 'Client', 'ClientBatchID', 'ClientPatientID', 'Patient', 'Doctor', 'BatchDate', 'OnsetDate', 'OnsetDateEstimated', 'PatientAgeAtCaseOnsetDate', 'HoursFasting', 'PatientCondition', 'BasalBodyTemperature', 'MenstrualStatus', 'Symptoms', 'ProvisionalDiagnosis', 'CaseStatus', 'CaseOutcome', 'AetiologicAgents', 'AdditionalNotes', 'Remarks', 'BatchLabels', ] return schematas def getFields(self): return self.fields
class AnalysisRequestSchemaExtender(object): adapts(IAnalysisRequest) implements(IOrderableSchemaExtender) def __init__(self, context): self.context = context fields = [ ExtProxyField("ParticipantID", proxy="context.getSample()", mode="rw", required=1, widget=StringWidget( label=_("Participant ID"), maxlength=22, size=22, render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, )), ExtProxyField("OtherParticipantReference", proxy="context.getSample()", mode="rw", required=0, widget=StringWidget( label=_("Other Participant Ref"), maxlength=12, size=12, render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, )), ExtProxyField("ParticipantInitials", proxy="context.getSample()", mode="rw", required=1, widget=StringWidget( label=_("Participant Initials"), maxlength=3, size=2, render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, )), ExtProxyField("Gender", proxy="context.getSample()", mode="rw", required=1, vocabulary=GENDERS, widget=SelectionWidget( format="radio", label=_("Gender"), render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, )), ExtProxyField("Visit", proxy="context.getSample()", mode="rw", required=1, widget=StringWidget( label=_("Visit Number"), maxlength=4, size=4, render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, )), ExtProxyField( "Fasting", proxy="context.getSample()", mode="rw", required=0, default=False, widget=BooleanWidget( format="radio", label=_("Fasting"), render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, ), ), ExtProxyField( 'DateOfBirth', proxy="context.getSample()", mode="rw", required=1, widget=DateTimeWidget( label=_('Date of Birth'), datepicker_nofuture=1, show_time=False, render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, ), ), ExtProxyField("Volume", proxy="context.getSample()", mode="rw", required=1, widget=StringWidget( label=_("Estimated Sample Volume"), maxlength=8, size=8, render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, )), ExtProxyField( "OtherInformation", proxy="context.getSample()", mode="rw", default_content_type="text/plain", allowable_content_types=("text/plain", ), default_output_type="text/plain", widget=TextAreaWidget( label=_("Other relevant clinical information"), render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, ), ), ExtProxyField( "Courier", proxy="context.getSample()", required=0, allowed_types='Courier', relationship='AnalysisRequestCourier', mode="rw", read_permission=View, write_permission=ModifyPortalContent, widget=ReferenceWidget( label=_("Courier"), description=_("The person who delivered the sample"), render_own_label=True, visible={ 'view': 'visible', 'edit': 'visible', 'add': 'invisible', 'header_table': 'visible', 'secondary': 'disabled', 'sample_registered': { 'view': 'invisible', 'edit': 'invisible' }, 'to_be_sampled': { 'view': 'invisible', 'edit': 'invisible' }, 'scheduled_sampling': { 'view': 'invisible', 'edit': 'invisible' }, 'sampled': { 'view': 'invisible', 'edit': 'invisible' }, 'to_be_preserved': { 'view': 'invisible', 'edit': 'invisible' }, 'sample_ordered': { 'view': 'visible', 'edit': 'visible' }, 'sample_due': { 'view': 'visible', 'edit': 'visible' }, 'sample_prep': { 'view': 'visible', 'edit': 'invisible' }, 'sample_received': { 'view': 'visible', 'edit': 'invisible' }, 'attachment_due': { 'view': 'visible', 'edit': 'invisible' }, 'to_be_verified': { 'view': 'visible', 'edit': 'invisible' }, 'verified': { 'view': 'visible', 'edit': 'invisible' }, 'published': { 'view': 'visible', 'edit': 'invisible' }, 'invalid': { 'view': 'visible', 'edit': 'invisible' }, 'rejected': { 'view': 'visible', 'edit': 'invisible' }, }, catalog_name='bika_setup_catalog', base_query={'review_state': 'active'}, showOn=True, ), ), # This Analysis Request is only for internal use? # This field is useful when we create Partitions (AR-like), so we don't # want the client to see Analysis Requests / Samples that are meant to # be used in the lab. ExtProxyField( "InternalUse", proxy="context.getSample()", mode="rw", required=0, default=False, widget=BooleanWidget( format="radio", label=_("Internal use"), render_own_label=True, visible={ 'edit': 'visible', 'view': 'visible', 'add': 'edit', 'header_table': 'visible' }, ), ), ExtProxyField( "PrimarySample", proxy="context.getSample()", required=0, allowed_types=('Sample'), relationship='SamplePrimarySample', mode="rw", read_permission=View, write_permission=ModifyPortalContent, widget=ReferenceWidget( label=_("Primary Sample"), description=_("The sample this is originated from"), size=20, render_own_label=True, visible={ 'view': 'visible', 'edit': 'invisible', 'add': 'invisible', 'header_table': 'visible', 'secondary': 'disabled', }, catalog_name='bika_catalog', base_query={'review_state': 'active'}, showOn=False, ), ), ExtReferenceField( 'PrimaryAnalysisRequest', allowed_types=('AnalysisRequest', ), relationship='AnalysisRequestPrimaryAnalysisRequest', referenceClass=HoldingReference, mode="rw", read_permission=View, write_permission=ModifyPortalContent, widget=ReferenceWidget(visible=False, ), ), ExtBooleanField( "PanicEmailAlertSent", default=False, widget=BooleanWidget(visible={ 'edit': 'invisible', 'view': 'invisible', 'add': 'invisible' }, ), ) ] def getOrder(self, schematas): return schematas def getFields(self): return self.fields
), maxlength=4, size=4, render_own_label=True, visible={ 'add': 'edit', }, )), ExtBooleanField( "Fasting", mode="rw", required=0, read_permission=View, write_permission=ModifyPortalContent, default=False, widget=BooleanWidget( format="radio", label=_("Fasting"), render_own_label=True, visible={ 'add': 'edit', }, ), ), ExtDateTimeField( 'DateOfBirth', mode="rw", required=1, read_permission=View, write_permission=ModifyPortalContent, widget=DateTimeWidget( label=_('Date of Birth'),