From c56a9666f3d0f3726aad51f9329597cee8ee2863 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:16:02 -0700 Subject: [PATCH 01/33] Create new component table Fixes #6388 --- specifyweb/specify/datamodel.py | 58 ++++++++++++++++++++++-- specifyweb/specify/models.py | 45 ++++++++++++++++++ specifyweb/specify/models_by_table_id.py | 1 + 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 2c17b72b039..b85118941d9 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,6 +1601,7 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), +), ], fieldAliases=[ @@ -2197,6 +2198,54 @@ def is_tree_table(table: Table): ] ), + Table( + classname='edu.ku.brc.specify.datamodel.Component', + table='component', + tableId=1028, + idColumn='ComponentID', + idFieldName='componentId', + idField=IdField(name='componentId', column='ComponentID', type='java.lang.Integer'), + fields=[ + Field(name='verbatimName', column='VerbatimName', indexed=False, unique=False, required=False, type='text'), + Field(name='role', column='Role', indexed=False, unique=False, required=False, type='java.lang.String', length=64), + Field(name='proportion', column='Proportion', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='uniqueIdentifier', column='UniqueIdentifier', indexed=True, unique=False, required=False, type='java.lang.String', length=128), + Field(name='text1', column='Text1', indexed=False, unique=False, required=False, type='text', length=65535), + Field(name='text2', column='Text2', indexed=False, unique=False, required=False, type='text', length=65535), + Field(name='text3', column='Text3', indexed=False, unique=False, required=False, type='text', length=65535), + Field(name='text4', column='Text4', indexed=False, unique=False, required=False, type='text', length=65535), + Field(name='text5', column='Text5', indexed=False, unique=False, required=False, type='text', length=65535), + Field(name='text6', column='Text6', indexed=False, unique=False, required=False, type='text', length=65535), + Field(name='yesNo1', column='YesNo1', indexed=False, unique=False, required=False, type='java.lang.Boolean'), + Field(name='yesNo2', column='YesNo2', indexed=False, unique=False, required=False, type='java.lang.Boolean'), + Field(name='yesNo3', column='YesNo3', indexed=False, unique=False, required=False, type='java.lang.Boolean'), + Field(name='yesNo4', column='YesNo4', indexed=False, unique=False, required=False, type='java.lang.Boolean'), + Field(name='yesNo5', column='YesNo5', indexed=False, unique=False, required=False, type='java.lang.Boolean'), + Field(name='yesNo6', column='YesNo6', indexed=False, unique=False, required=False, type='java.lang.Boolean'), + Field(name='integer1', column='Integer1', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='integer2', column='Integer2', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='integer3', column='Integer3', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='integer4', column='Integer4', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='integer5', column='Integer5', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='integer6', column='Integer6', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='number1', column='Number1', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + Field(name='number2', column='Number2', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + Field(name='number3', column='Number3', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + Field(name='number4', column='Number4', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + Field(name='number5', column='Number5', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + Field(name='number6', column='Number6', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + ], + indexes=[], + relationships=[ + Relationship(name='collectionObject', type='many-to-one',required=True, relatedModelName='CollectionObject', column='CollectionObjectID', otherSideName='components'), + Relationship(name='taxon', type='many-to-one',required=False, relatedModelName='Taxon', column='TaxonID', otherSideName='components'), + Relationship(name='componentType', type='many-to-one', required=True, relatedModelName='CollectionObjectType', column='CollectionObjectTypeID'), + Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ComponentID'), + Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='component', dependent=True), + Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='component', dependent=True), + ], + fieldAliases=[] + ), Table( classname='edu.ku.brc.specify.datamodel.ConservDescription', table='conservdescription', @@ -7151,7 +7200,8 @@ def is_tree_table(table: Table): Relationship(name='taxonAttachments', type='one-to-many',required=False, relatedModelName='TaxonAttachment', otherSideName='taxon', dependent=True), Relationship(name='taxonAttribute', type='many-to-one',required=False, relatedModelName='TaxonAttribute', column='TaxonAttributeID', otherSideName='taxons', dependent=True), Relationship(name='taxonCitations', type='one-to-many',required=False, relatedModelName='TaxonCitation', otherSideName='taxon', dependent=True), - Relationship(name='visibilitySetBy', type='many-to-one',required=False, relatedModelName='SpecifyUser', column='VisibilitySetByID') + Relationship(name='visibilitySetBy', type='many-to-one',required=False, relatedModelName='SpecifyUser', column='VisibilitySetByID'), + Relationship(name='components', type='one-to-many',required=False, relatedModelName='Component', otherSideName='taxon'), ], fieldAliases=[ {'vname':'acceptedParent', 'aname':'acceptedTaxon'} @@ -8416,7 +8466,8 @@ def is_tree_table(table: Table): Relationship(name='collectionObject', type='many-to-one', required=True, relatedModelName='CollectionObject', column='CollectionObjectID', otherSideName='absoluteAges'), Relationship(name='absoluteAgeCitations', type='one-to-many',required=False, relatedModelName='AbsoluteAgeCitation', otherSideName='absoluteAge', dependent=True), Relationship(name='createdByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='CreatedByAgentID'), - Relationship(name='modifiedByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='ModifiedByAgentID') + Relationship(name='modifiedByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='ModifiedByAgentID'), + Relationship(name='component', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID', otherSideName='absoluteAges'), ], fieldAliases=[ @@ -8465,7 +8516,8 @@ def is_tree_table(table: Table): Relationship(name='collectionObject', type='many-to-one', required=True, relatedModelName='CollectionObject', column='CollectionObjectID', otherSideName='relativeAges'), Relationship(name='relativeAgeCitations', type='one-to-many',required=False, relatedModelName='RelativeAgeCitation', otherSideName='relativeAge', dependent=True), Relationship(name='createdByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='CreatedByAgentID'), - Relationship(name='modifiedByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='ModifiedByAgentID') + Relationship(name='modifiedByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='ModifiedByAgentID'), + Relationship(name='component', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID', otherSideName='relativeAges'), ], fieldAliases=[ diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index cfcbc4e2201..9fbe33cd333 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -1471,6 +1471,7 @@ class Collectionobject(models.Model): paleocontext = models.ForeignKey('PaleoContext', db_column='PaleoContextID', related_name='collectionobjects', null=True, on_delete=protect_with_blockers) visibilitysetby = models.ForeignKey('SpecifyUser', db_column='VisibilitySetByID', related_name='+', null=True, on_delete=protect_with_blockers) collectionobjecttype = models.ForeignKey('CollectionObjectType', db_column='CollectionObjectTypeID', related_name='collectionobjects', null=True, on_delete=models.SET_NULL) + component = models.ForeignKey('Component', db_column='ComponentID', related_name='components', null=True, on_delete=models.SET_NULL) class Meta: db_table = 'collectionobject' @@ -2076,6 +2077,48 @@ class Meta: save = partialmethod(custom_save) +class Component(models.Model): + specify_model = datamodel.get_table_strict('component') + + # ID Field + id = models.AutoField(primary_key=True, db_column='componentid') + + # Fields + verbatimname = models.TextField(blank=True, null=True, unique=False, db_column='VerbatimName', db_index=False) + role = models.CharField(blank=False, max_length=50, null=False, unique=False, db_column='Role', db_index=False) + proportion= models.IntegerField(blank=True, null=True, unique=False, db_column='Proportion', db_index=False) + uniqueidentifier = models.CharField(blank=True, max_length=128, null=True, unique=False, db_column='UniqueIdentifier', db_index=False) + text1 = models.TextField(blank=True, null=True, unique=False, db_column='Text1', db_index=False) + text2 = models.TextField(blank=True, null=True, unique=False, db_column='Text2', db_index=False) + text3 = models.TextField(blank=True, null=True, unique=False, db_column='Text3', db_index=False) + text4 = models.TextField(blank=True, null=True, unique=False, db_column='Text4', db_index=False) + text5 = models.TextField(blank=True, null=True, unique=False, db_column='Text5', db_index=False) + text6 = models.TextField(blank=True, null=True, unique=False, db_column='Text6', db_index=False) + yesno1 = models.BooleanField(blank=True, null=True, unique=False, db_column='YesNo1', db_index=False) + yesno2 = models.BooleanField(blank=True, null=True, unique=False, db_column='YesNo2', db_index=False) + yesno3 = models.BooleanField(blank=True, null=True, unique=False, db_column='YesNo3', db_index=False) + yesno4 = models.BooleanField(blank=True, null=True, unique=False, db_column='YesNo4', db_index=False) + yesno5 = models.BooleanField(blank=True, null=True, unique=False, db_column='YesNo5', db_index=False) + yesno6 = models.BooleanField(blank=True, null=True, unique=False, db_column='YesNo6', db_index=False) + integer1 = models.IntegerField(blank=True, null=True, unique=False, db_column='Integer1', db_index=False) + integer2 = models.IntegerField(blank=True, null=True, unique=False, db_column='Integer2', db_index=False) + integer3 = models.IntegerField(blank=True, null=True, unique=False, db_column='Integer3', db_index=False) + integer4 = models.IntegerField(blank=True, null=True, unique=False, db_column='Integer4', db_index=False) + integer5 = models.IntegerField(blank=True, null=True, unique=False, db_column='Integer5', db_index=False) + integer6 = models.IntegerField(blank=True, null=True, unique=False, db_column='Integer6', db_index=False) + number1 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number1', db_index=False) + number2 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number2', db_index=False) + number3 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number3', db_index=False) + number4 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number4', db_index=False) + number5 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number5', db_index=False) + number6 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number6', db_index=False) + + # Relationships: Many-to-One + collectionobject = models.ForeignKey('CollectionObject', db_column='CollectionObjectID', related_name='components', null=False, on_delete=models.CASCADE) + name = models.ForeignKey('Taxon', db_column='TaxonID', related_name='components', null=True, on_delete=protect_with_blockers) + componenttype = models.ForeignKey('CollectionObjectType', db_column='CollectionObjectTypeID', related_name='components', null=True, on_delete=models.SET_NULL) + parentcomponent = models.ForeignKey('Component', db_column='ParentComponentID', related_name='+', null=True, on_delete=protect_with_blockers) + class Conservdescription(models.Model): specify_model = datamodel.get_table_strict('conservdescription') @@ -7657,6 +7700,7 @@ class Absoluteage(models.Model): absoluteagecitation = models.ForeignKey(db_column='AbsoluteAgeCitationID', null=True, on_delete=protect_with_blockers, related_name='absoluteages', to='specify.absoluteagecitation') createdbyagent = models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') modifiedbyagent = models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') + component = models.ForeignKey('Component', db_column='ComponentID', related_name='absoluteages', null=False, on_delete=models.CASCADE) class Meta: db_table = 'absoluteage' @@ -7702,6 +7746,7 @@ class Relativeage(models.Model): relativeagecitation = models.ForeignKey(db_column='RelativeAgeCitationID', null=True, on_delete=protect_with_blockers, related_name='relativeages', to='specify.relativeagecitation') createdbyagent = models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') modifiedbyagent = models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') + component = models.ForeignKey('Component', db_column='ComponentID', related_name='relativeages', null=False, on_delete=models.CASCADE) class Meta: db_table = 'relativeage' diff --git a/specifyweb/specify/models_by_table_id.py b/specifyweb/specify/models_by_table_id.py index eeab58013e8..a20f9429c0b 100644 --- a/specifyweb/specify/models_by_table_id.py +++ b/specifyweb/specify/models_by_table_id.py @@ -216,6 +216,7 @@ 1025:'Tectonicunittreedef', 1026:'Tectonicunittreedefitem', 1027:'Tectonicunit', + 1028: 'Component' } model_names_by_app = { From 01a5bd75fcc45d6de0a38dce601cc0f28a7cb834 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:17:38 -0700 Subject: [PATCH 02/33] Typo --- specifyweb/specify/datamodel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index b85118941d9..2e96151084d 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,7 +1601,6 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), -), ], fieldAliases=[ From caf8c59651cc397f272fc2f993c49ed849d34f09 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:35:14 -0700 Subject: [PATCH 03/33] Add component to types.ts --- .../js_src/lib/components/DataModel/types.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index 28152becfc6..17927a4cd9a 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -69,6 +69,7 @@ export type Tables = { readonly Collector: Collector; readonly CommonNameTx: CommonNameTx; readonly CommonNameTxCitation: CommonNameTxCitation; + readonly Component: Component; readonly ConservDescription: ConservDescription; readonly ConservDescriptionAttachment: ConservDescriptionAttachment; readonly ConservEvent: ConservEvent; @@ -1470,6 +1471,7 @@ export type CollectionObject = { readonly rightSideRels: RA; readonly treatmentEvents: RA; readonly voucherRelationships: RA; + readonly components: RA; }; readonly toManyIndependent: { readonly projects: RA }; }; @@ -1966,6 +1968,51 @@ export type CommonNameTxCitation = { readonly toManyDependent: RR; readonly toManyIndependent: RR; }; +export type Component = { + readonly tableName: 'Component'; + readonly fields: { + readonly verbatimName: string | null; + readonly role: string | null; + readonly proportion: number | null; + readonly uniqueIdentifier: string | null; + readonly text1: string | null; + readonly text2: string | null; + readonly text3: string | null; + readonly text4: string | null; + readonly text5: string | null; + readonly text6: string | null; + readonly yesNo1: boolean | null; + readonly yesNo2: boolean | null; + readonly yesNo3: boolean | null; + readonly yesNo4: boolean | null; + readonly yesNo5: boolean | null; + readonly yesNo6: boolean | null; + readonly integer1: number | null; + readonly integer2: number | null; + readonly integer3: number | null; + readonly integer4: number | null; + readonly integer5: number | null; + readonly integer6: number | null; + readonly number1: number | null; + readonly number2: number | null; + readonly number3: number | null; + readonly number4: number | null; + readonly number5: number | null; + readonly number6: number | null; + }; + readonly toOneDependent: { + readonly collectionObject: CollectionObject | null; + }; + readonly toOneIndependent: { + readonly collectionObjectType: CollectionObjectType; + readonly name: Taxon | null; + readonly parentComponent: Component | null; + }; + readonly toManyDependent: { + readonly absoluteAges: RA; + readonly relativeAges: RA; + }; +}; export type ConservDescription = { readonly tableName: 'ConservDescription'; readonly fields: { @@ -5736,6 +5783,7 @@ export type Taxon = { readonly hybridChildren2: RA; readonly preferredTaxonOf: RA; readonly acceptedChildren: RA; + readonly components: RA; }; }; export type TaxonAttachment = { @@ -6602,6 +6650,7 @@ export type AbsoluteAge = { readonly collectionObject: CollectionObject; readonly createdByAgent: Agent | null; readonly modifiedByAgent: Agent | null; + readonly component: Component; }; readonly toManyDependent: { readonly absoluteAgeAttachments: RA; @@ -6642,6 +6691,7 @@ export type RelativeAge = { readonly collectionObject: CollectionObject; readonly createdByAgent: Agent | null; readonly modifiedByAgent: Agent | null; + readonly component: Component; }; readonly toManyDependent: { readonly relativeAgeAttachments: RA; From 8ef77d14c10e2cb2d4acaeb95ff8f12d87a42f51 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:23:40 -0700 Subject: [PATCH 04/33] Create migration file for component table --- .../js_src/lib/components/DataModel/types.ts | 7 +- specifyweb/specify/datamodel.py | 9 +- .../migration_utils/sp7_schemaconfig.py | 23 +++ .../specify/migrations/0027_component.py | 141 ++++++++++++++++++ specifyweb/specify/models.py | 9 +- specifyweb/specify/models_by_table_id.py | 1 + 6 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 specifyweb/specify/migrations/0027_component.py diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index 17927a4cd9a..d29e965c55c 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -1999,14 +1999,19 @@ export type Component = { readonly number4: number | null; readonly number5: number | null; readonly number6: number | null; + readonly version: number | null; + readonly timestampCreated: string; + readonly timestampModified: string | null; }; readonly toOneDependent: { readonly collectionObject: CollectionObject | null; }; readonly toOneIndependent: { - readonly collectionObjectType: CollectionObjectType; + readonly type: CollectionObjectType; readonly name: Taxon | null; readonly parentComponent: Component | null; + readonly createdByAgent: Agent | null; + readonly modifiedByAgent: Agent | null; }; readonly toManyDependent: { readonly absoluteAges: RA; diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 2e96151084d..928b86a9100 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -2233,15 +2233,20 @@ def is_tree_table(table: Table): Field(name='number4', column='Number4', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), Field(name='number5', column='Number5', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), Field(name='number6', column='Number6', indexed=False, unique=False, required=False, type='java.math.BigDecimal'), + Field(name='version', column='Version', indexed=False, unique=False, required=False, type='java.lang.Integer'), + Field(name='timestampCreated', column='TimestampCreated', indexed=False, unique=False, required=True, type='java.sql.Timestamp'), + Field(name='timestampModified', column='TimestampModified', indexed=False, unique=False, required=False, type='java.sql.Timestamp'), ], indexes=[], relationships=[ Relationship(name='collectionObject', type='many-to-one',required=True, relatedModelName='CollectionObject', column='CollectionObjectID', otherSideName='components'), Relationship(name='taxon', type='many-to-one',required=False, relatedModelName='Taxon', column='TaxonID', otherSideName='components'), - Relationship(name='componentType', type='many-to-one', required=True, relatedModelName='CollectionObjectType', column='CollectionObjectTypeID'), - Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ComponentID'), + Relationship(name='type', type='many-to-one', required=True, relatedModelName='CollectionObjectType', column='CollectionObjectTypeID'), + Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ParentComponentID'), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='component', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='component', dependent=True), + Relationship(name='createdByAgent', type='many-to-one',required=False, relatedModelName='Agent', column='CreatedByAgentID'), + Relationship(name='modifiedByAgent', type='many-to-one',required=False, relatedModelName='Agent', column='ModifiedByAgentID'), ], fieldAliases=[] ), diff --git a/specifyweb/specify/migration_utils/sp7_schemaconfig.py b/specifyweb/specify/migration_utils/sp7_schemaconfig.py index 6090848cfea..c4b8e725b64 100644 --- a/specifyweb/specify/migration_utils/sp7_schemaconfig.py +++ b/specifyweb/specify/migration_utils/sp7_schemaconfig.py @@ -167,4 +167,27 @@ MIGRATION_0024_FIELDS = { 'Storage': ['uniqueIdentifier'], +} + +MIGRATION_0027_TABLES = [ + ('Component', None), +] + +MIGRATION_0027_FIELDS = { + 'Collectionobject': ['components'], + 'Taxon': ['components'], + 'RelativeAge': ['components'], + 'AbsoluteAge': ['components'], +} + + +MIGRATION_0027_UPDATE_FIELDS = { + 'Component': [ + ('type', 'Component Type', 'This type determines the valid options for component names.'), + ('name', 'Component Name', 'The name from a taxon tree corresponding to the chosen type.'), + ('verbatimName', 'Verbatim Name', 'The original name printed or associated with the component.'), + ('role', 'Component Role', 'Define the role or purpose of the component in the overall collection.'), + ('proportion', 'Component Proportion', 'Specify the proportion of the component relative to the whole.'), + ('uniqueIdentifier', 'Unique Identifier', 'Unique Identifier [/+][-]Unique Identifier'), + ], } \ No newline at end of file diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py new file mode 100644 index 00000000000..80a66247259 --- /dev/null +++ b/specifyweb/specify/migrations/0027_component.py @@ -0,0 +1,141 @@ +from django.apps import apps as specify_apps +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +from specifyweb.specify.models import protect_with_blockers +from specifyweb.specify.migration_utils.update_schema_config import revert_table_field_schema_config, revert_table_schema_config, update_table_field_schema_config_with_defaults, update_table_schema_config_with_defaults + +from specifyweb.specify.migration_utils.sp7_schemaconfig import MIGRATION_0027_TABLES as SCHEMA_CONFIG_TABLES, MIGRATION_0027_FIELDS as SCHEMA_CONFIG_TABLE_FIELDS, MIGRATION_0027_UPDATE_FIELDS as SCHEMA_CONFIG_COMPONENT_TABLE_FIELDS + +def create_table_schema_config_with_defaults(apps): + Discipline = specify_apps.get_model('specify', 'Discipline') + for discipline in Discipline.objects.all(): + for table, desc in SCHEMA_CONFIG_TABLES: + update_table_schema_config_with_defaults(table, discipline.id, desc, apps) + + for table, fields in SCHEMA_CONFIG_TABLE_FIELDS.items(): + for field in fields: + update_table_field_schema_config_with_defaults(table, discipline.id, field, apps) + +def update_schema_config_field_desc(apps, schema_editor): + Splocalecontainer = apps.get_model('specify', 'Splocalecontainer') + Splocalecontaineritem = apps.get_model('specify', 'Splocalecontaineritem') + Splocaleitemstr = apps.get_model('specify', 'Splocaleitemstr') + + for table, fields in SCHEMA_CONFIG_COMPONENT_TABLE_FIELDS.items(): + #i.e: Collection Object + containers = Splocalecontainer.objects.filter( + name=table.lower(), + ) + + for container in containers: + for field_name, new_name, new_desc in fields: + #i.e: COType + items = Splocalecontaineritem.objects.filter( + container=container, + name=field_name.lower() + ) + + for item in items: + localized_items_desc = Splocaleitemstr.objects.filter(itemdesc_id=item.id).first() + localized_items_name = Splocaleitemstr.objects.filter(itemname_id=item.id).first() + + if localized_items_desc is None or localized_items_name is None: + continue + + localized_items_desc.text = new_desc + localized_items_desc.save() + + localized_items_name.text = new_name + localized_items_name.save() + +def revert_table_schema_config_with_defaults(apps): + for table, _ in SCHEMA_CONFIG_TABLES: + revert_table_schema_config(table, apps) + for table, fields in SCHEMA_CONFIG_MOD_TABLE_FIELDS.items(): + for field in fields: + revert_table_field_schema_config(table, field, apps) + +def revert_update_hidden_prop(apps, schema_editor): + Splocalecontainer = apps.get_model('specify', 'Splocalecontainer') + Splocalecontaineritem = apps.get_model('specify', 'Splocalecontaineritem') + + for table, fields in SCHEMA_CONFIG_COMPONENT_TABLE_FIELDS.items(): + containers = Splocalecontainer.objects.filter( + name=table.lower(), + ) + for container in containers: + for field_name in fields: + items = Splocalecontaineritem.objects.filter( + container=container, + name=field_name.lower() + ) + + for item in items: + item.ishidden = False + item.save() + +class Migration(migrations.Migration): + + dependencies = [ + ('specify', '0026_taxontreedef_alter_delete'), + ] + + def consolidated_python_django_migration_operations(apps, schema_editor): + pass + create_table_schema_config_with_defaults(apps) + update_schema_config_field_desc(apps) + + def revert_cosolidated_python_django_migration_operations(apps, schema_editor): + pass + revert_table_schema_config_with_defaults(apps) + revert_update_hidden_prop(apps) + + operation = [ + migrations.CreateModel( + name='Component', + fields=[ + ('id', models.AutoField(db_column='ComponentID', primary_key=True, serialize=False)), + ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', max_length=64, null=True)), + ('role', models.CharField(blank=True, db_column='Role', max_length=64, null=True)), + ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), + ('uniqueidentifier', models.CharField(blank=True,db_column='UniqueIdentifier', max_length=255, null=True, unique=True)), + ('text1', models.TextField(blank=True, db_column='Text1', null=True)), + ('text2', models.TextField(blank=True, db_column='Text2', null=True)), + ('text3', models.TextField(blank=True, db_column='Text3', null=True)), + ('text4', models.TextField(blank=True, db_column='Text4', null=True)), + ('text5', models.TextField(blank=True, db_column='Text5', null=True)), + ('text6', models.TextField(blank=True, db_column='Text6', null=True)), + ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), + ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), + ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), + ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), + ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), + ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), + ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), + ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), + ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), + ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), + ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), + ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), + ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), + ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), + ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), + ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), + ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), + ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), + ('version', models.IntegerField(blank=True, db_column='Version', null=True)), + ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), + ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), + + #relationships + ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), + ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), + ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=protect_with_blockers, related_name='components', to='specify.collectionobject')), + ('name', models.ForeignKey(db_column='TaxonID', on_delete=protect_with_blockers, related_name='components', to='specify.taxon')), + ('type', models.ForeignKey(db_column='CollectionObjectTypeID', on_delete=protect_with_blockers, related_name='components', to='specify.collectionobjecttype')), + ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', on_delete=protect_with_blockers, related_name='componentChildren', to='specify.component')), + ] + ), + migrations.RunPython(consolidated_python_django_migration_operations, revert_cosolidated_python_django_migration_operations, atomic=True), + ] \ No newline at end of file diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index 9fbe33cd333..a18f79e2532 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -2112,12 +2112,17 @@ class Component(models.Model): number4 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number4', db_index=False) number5 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number5', db_index=False) number6 = models.DecimalField(blank=True, max_digits=22, decimal_places=10, null=True, unique=False, db_column='Number6', db_index=False) + timestampcreated = models.DateTimeField(blank=False, null=False, unique=False, db_column='TimestampCreated', db_index=False, default=timezone.now) + timestampmodified = models.DateTimeField(blank=True, null=True, unique=False, db_column='TimestampModified', db_index=False, default=timezone.now) + version = models.IntegerField(blank=True, null=True, unique=False, db_column='Version', db_index=False, default=0) # Relationships: Many-to-One collectionobject = models.ForeignKey('CollectionObject', db_column='CollectionObjectID', related_name='components', null=False, on_delete=models.CASCADE) name = models.ForeignKey('Taxon', db_column='TaxonID', related_name='components', null=True, on_delete=protect_with_blockers) - componenttype = models.ForeignKey('CollectionObjectType', db_column='CollectionObjectTypeID', related_name='components', null=True, on_delete=models.SET_NULL) - parentcomponent = models.ForeignKey('Component', db_column='ParentComponentID', related_name='+', null=True, on_delete=protect_with_blockers) + type = models.ForeignKey('CollectionObjectType', db_column='CollectionObjectTypeID', related_name='components', null=True, on_delete=models.SET_NULL) + parentcomponent = models.ForeignKey('Component', db_column='ParentComponentID', related_name='componentChildren', null=True, on_delete=protect_with_blockers) + createdbyagent = models.ForeignKey('Agent', db_column='CreatedByAgentID', related_name='+', null=True, on_delete=protect_with_blockers) + modifiedbyagent = models.ForeignKey('Agent', db_column='ModifiedByAgentID', related_name='+', null=True, on_delete=protect_with_blockers) class Conservdescription(models.Model): specify_model = datamodel.get_table_strict('conservdescription') diff --git a/specifyweb/specify/models_by_table_id.py b/specifyweb/specify/models_by_table_id.py index a20f9429c0b..519aefe2a43 100644 --- a/specifyweb/specify/models_by_table_id.py +++ b/specifyweb/specify/models_by_table_id.py @@ -446,6 +446,7 @@ 'Tectonicunittreedef', 'Tectonicunittreedefitem', 'Tectonicunit', + 'Component' } } From 44941e0e0c92620b57e6916df4bb21c8fa81c676 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:28:29 -0700 Subject: [PATCH 05/33] Update children --- specifyweb/specify/migrations/0027_component.py | 2 +- specifyweb/specify/models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index 80a66247259..f3dc8370167 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -134,7 +134,7 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=protect_with_blockers, related_name='components', to='specify.collectionobject')), ('name', models.ForeignKey(db_column='TaxonID', on_delete=protect_with_blockers, related_name='components', to='specify.taxon')), ('type', models.ForeignKey(db_column='CollectionObjectTypeID', on_delete=protect_with_blockers, related_name='components', to='specify.collectionobjecttype')), - ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', on_delete=protect_with_blockers, related_name='componentChildren', to='specify.component')), + ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', on_delete=protect_with_blockers, related_name='children', to='specify.component')), ] ), migrations.RunPython(consolidated_python_django_migration_operations, revert_cosolidated_python_django_migration_operations, atomic=True), diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index a18f79e2532..b2d73e1c069 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -2120,7 +2120,7 @@ class Component(models.Model): collectionobject = models.ForeignKey('CollectionObject', db_column='CollectionObjectID', related_name='components', null=False, on_delete=models.CASCADE) name = models.ForeignKey('Taxon', db_column='TaxonID', related_name='components', null=True, on_delete=protect_with_blockers) type = models.ForeignKey('CollectionObjectType', db_column='CollectionObjectTypeID', related_name='components', null=True, on_delete=models.SET_NULL) - parentcomponent = models.ForeignKey('Component', db_column='ParentComponentID', related_name='componentChildren', null=True, on_delete=protect_with_blockers) + parentcomponent = models.ForeignKey('Component', db_column='ParentComponentID', related_name='children', null=True, on_delete=protect_with_blockers) createdbyagent = models.ForeignKey('Agent', db_column='CreatedByAgentID', related_name='+', null=True, on_delete=protect_with_blockers) modifiedbyagent = models.ForeignKey('Agent', db_column='ModifiedByAgentID', related_name='+', null=True, on_delete=protect_with_blockers) From 39e10bbf0aa6754a633fd91e486eb9dc233290f7 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:36:03 -0700 Subject: [PATCH 06/33] Modify migration --- specifyweb/specify/datamodel.py | 4 +- .../specify/migrations/0027_component.py | 103 ++++++++++-------- specifyweb/specify/models.py | 4 +- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 928b86a9100..11038fdeb38 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -8471,7 +8471,7 @@ def is_tree_table(table: Table): Relationship(name='absoluteAgeCitations', type='one-to-many',required=False, relatedModelName='AbsoluteAgeCitation', otherSideName='absoluteAge', dependent=True), Relationship(name='createdByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='CreatedByAgentID'), Relationship(name='modifiedByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='ModifiedByAgentID'), - Relationship(name='component', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID', otherSideName='absoluteAges'), + Relationship(name='component', type='many-to-one', required=False, relatedModelName='Component', column='ComponentID', otherSideName='absoluteAges'), ], fieldAliases=[ @@ -8521,7 +8521,7 @@ def is_tree_table(table: Table): Relationship(name='relativeAgeCitations', type='one-to-many',required=False, relatedModelName='RelativeAgeCitation', otherSideName='relativeAge', dependent=True), Relationship(name='createdByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='CreatedByAgentID'), Relationship(name='modifiedByAgent', type='many-to-one', required=False, relatedModelName='Agent', column='ModifiedByAgentID'), - Relationship(name='component', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID', otherSideName='relativeAges'), + Relationship(name='component', type='many-to-one', required=False, relatedModelName='Component', column='ComponentID', otherSideName='relativeAges'), ], fieldAliases=[ diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index f3dc8370167..bdedc330414 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -92,50 +92,63 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): revert_update_hidden_prop(apps) operation = [ - migrations.CreateModel( - name='Component', - fields=[ - ('id', models.AutoField(db_column='ComponentID', primary_key=True, serialize=False)), - ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', max_length=64, null=True)), - ('role', models.CharField(blank=True, db_column='Role', max_length=64, null=True)), - ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), - ('uniqueidentifier', models.CharField(blank=True,db_column='UniqueIdentifier', max_length=255, null=True, unique=True)), - ('text1', models.TextField(blank=True, db_column='Text1', null=True)), - ('text2', models.TextField(blank=True, db_column='Text2', null=True)), - ('text3', models.TextField(blank=True, db_column='Text3', null=True)), - ('text4', models.TextField(blank=True, db_column='Text4', null=True)), - ('text5', models.TextField(blank=True, db_column='Text5', null=True)), - ('text6', models.TextField(blank=True, db_column='Text6', null=True)), - ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), - ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), - ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), - ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), - ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), - ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), - ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), - ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), - ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), - ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), - ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), - ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), - ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), - ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), - ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), - ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), - ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), - ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), - ('version', models.IntegerField(blank=True, db_column='Version', null=True)), - ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), - ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), - - #relationships - ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), - ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), - ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=protect_with_blockers, related_name='components', to='specify.collectionobject')), - ('name', models.ForeignKey(db_column='TaxonID', on_delete=protect_with_blockers, related_name='components', to='specify.taxon')), - ('type', models.ForeignKey(db_column='CollectionObjectTypeID', on_delete=protect_with_blockers, related_name='components', to='specify.collectionobjecttype')), - ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', on_delete=protect_with_blockers, related_name='children', to='specify.component')), - ] - ), + migrations.CreateModel( + name='Component', + fields=[ + ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), + ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), + ('role', models.CharField(db_column='Role', max_length=50)), + ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), + ('uniqueidentifier', models.CharField(blank=True, db_column='UniqueIdentifier', max_length=128, null=True)), + ('text1', models.TextField(blank=True, db_column='Text1', null=True)), + ('text2', models.TextField(blank=True, db_column='Text2', null=True)), + ('text3', models.TextField(blank=True, db_column='Text3', null=True)), + ('text4', models.TextField(blank=True, db_column='Text4', null=True)), + ('text5', models.TextField(blank=True, db_column='Text5', null=True)), + ('text6', models.TextField(blank=True, db_column='Text6', null=True)), + ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), + ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), + ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), + ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), + ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), + ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), + ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), + ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), + ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), + ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), + ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), + ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), + ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), + ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), + ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), + ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), + ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), + ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), + ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), + ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), + ('version', models.IntegerField(blank=True, db_column='Version', default=0, null=True)), + ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=django.db.models.deletion.CASCADE, related_name='components', to='specify.collectionobject')), + ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='+', to='specify.agent')), + ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='+', to='specify.agent')), + ('name', models.ForeignKey(db_column='TaxonID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='components', to='specify.taxon')), + ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='children', to='specify.component')), + ('type', models.ForeignKey(db_column='CollectionObjectTypeID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.collectionobjecttype')), + ], + ), + migrations.AddField( + model_name='absoluteage', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='absoluteages', to='specify.component'), + ), + migrations.AddField( + model_name='collectionobject', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.component'), + ), + migrations.AddField( + model_name='relativeage', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='relativeages', to='specify.component'), + ), migrations.RunPython(consolidated_python_django_migration_operations, revert_cosolidated_python_django_migration_operations, atomic=True), ] \ No newline at end of file diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index b2d73e1c069..a8fbd8d9990 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -7705,7 +7705,7 @@ class Absoluteage(models.Model): absoluteagecitation = models.ForeignKey(db_column='AbsoluteAgeCitationID', null=True, on_delete=protect_with_blockers, related_name='absoluteages', to='specify.absoluteagecitation') createdbyagent = models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') modifiedbyagent = models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') - component = models.ForeignKey('Component', db_column='ComponentID', related_name='absoluteages', null=False, on_delete=models.CASCADE) + component = models.ForeignKey('Component', db_column='ComponentID', related_name='absoluteages', null=True, on_delete=models.CASCADE) class Meta: db_table = 'absoluteage' @@ -7751,7 +7751,7 @@ class Relativeage(models.Model): relativeagecitation = models.ForeignKey(db_column='RelativeAgeCitationID', null=True, on_delete=protect_with_blockers, related_name='relativeages', to='specify.relativeagecitation') createdbyagent = models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') modifiedbyagent = models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent') - component = models.ForeignKey('Component', db_column='ComponentID', related_name='relativeages', null=False, on_delete=models.CASCADE) + component = models.ForeignKey('Component', db_column='ComponentID', related_name='relativeages', null=True, on_delete=models.CASCADE) class Meta: db_table = 'relativeage' From 16dbf8cc92f01146e110da27f8e92639b738dee5 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:38:26 -0700 Subject: [PATCH 07/33] Update migration delete --- .../specify/migrations/0027_component.py | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index bdedc330414..3335e2fcb80 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -92,60 +92,60 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): revert_update_hidden_prop(apps) operation = [ - migrations.CreateModel( - name='Component', - fields=[ - ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), - ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), - ('role', models.CharField(db_column='Role', max_length=50)), - ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), - ('uniqueidentifier', models.CharField(blank=True, db_column='UniqueIdentifier', max_length=128, null=True)), - ('text1', models.TextField(blank=True, db_column='Text1', null=True)), - ('text2', models.TextField(blank=True, db_column='Text2', null=True)), - ('text3', models.TextField(blank=True, db_column='Text3', null=True)), - ('text4', models.TextField(blank=True, db_column='Text4', null=True)), - ('text5', models.TextField(blank=True, db_column='Text5', null=True)), - ('text6', models.TextField(blank=True, db_column='Text6', null=True)), - ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), - ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), - ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), - ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), - ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), - ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), - ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), - ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), - ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), - ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), - ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), - ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), - ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), - ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), - ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), - ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), - ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), - ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), - ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), - ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), - ('version', models.IntegerField(blank=True, db_column='Version', default=0, null=True)), - ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=django.db.models.deletion.CASCADE, related_name='components', to='specify.collectionobject')), - ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='+', to='specify.agent')), - ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='+', to='specify.agent')), - ('name', models.ForeignKey(db_column='TaxonID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='components', to='specify.taxon')), - ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', null=True, on_delete=specifyweb.specify.models.protect_with_blockers, related_name='children', to='specify.component')), - ('type', models.ForeignKey(db_column='CollectionObjectTypeID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.collectionobjecttype')), - ], - ), - migrations.AddField( - model_name='absoluteage', - name='component', - field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='absoluteages', to='specify.component'), - ), - migrations.AddField( - model_name='collectionobject', - name='component', - field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.component'), - ), - migrations.AddField( + migrations.CreateModel( + name='Component', + fields=[ + ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), + ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), + ('role', models.CharField(db_column='Role', max_length=50)), + ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), + ('uniqueidentifier', models.CharField(blank=True, db_column='UniqueIdentifier', max_length=128, null=True)), + ('text1', models.TextField(blank=True, db_column='Text1', null=True)), + ('text2', models.TextField(blank=True, db_column='Text2', null=True)), + ('text3', models.TextField(blank=True, db_column='Text3', null=True)), + ('text4', models.TextField(blank=True, db_column='Text4', null=True)), + ('text5', models.TextField(blank=True, db_column='Text5', null=True)), + ('text6', models.TextField(blank=True, db_column='Text6', null=True)), + ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), + ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), + ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), + ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), + ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), + ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), + ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), + ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), + ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), + ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), + ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), + ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), + ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), + ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), + ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), + ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), + ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), + ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), + ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), + ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), + ('version', models.IntegerField(blank=True, db_column='Version', default=0, null=True)), + ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=django.db.models.deletion.CASCADE, related_name='components', to='specify.collectionobject')), + ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), + ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), + ('name', models.ForeignKey(db_column='TaxonID', null=True, on_delete=protect_with_blockers, related_name='components', to='specify.taxon')), + ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', null=True, on_delete=protect_with_blockers, related_name='children', to='specify.component')), + ('type', models.ForeignKey(db_column='CollectionObjectTypeID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.collectionobjecttype')), + ], + ), + migrations.AddField( + model_name='absoluteage', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='absoluteages', to='specify.component'), + ), + migrations.AddField( + model_name='collectionobject', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.component'), + ), + migrations.AddField( model_name='relativeage', name='component', field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='relativeages', to='specify.component'), From a8646d959f6fef1550bccca19e5639ef4bb2e9fd Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:47:48 -0700 Subject: [PATCH 08/33] Add component to Co --- specifyweb/specify/datamodel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 11038fdeb38..0f0c0a78801 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,6 +1601,7 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), + Relationship(name='component', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID') ], fieldAliases=[ From db6c3d7688512d84717c9a602570fdfd3fa966eb Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:55:17 -0700 Subject: [PATCH 09/33] Typo --- specifyweb/specify/datamodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 0f0c0a78801..567a0436a51 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,7 +1601,7 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), - Relationship(name='component', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID') + Relationship(name='components', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID') ], fieldAliases=[ From 1f627afe08bd69ac955ae29f6351dcc529beb85a Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:00:21 -0700 Subject: [PATCH 10/33] Remove component from CO --- specifyweb/specify/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index a8fbd8d9990..300f4013087 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -1471,7 +1471,6 @@ class Collectionobject(models.Model): paleocontext = models.ForeignKey('PaleoContext', db_column='PaleoContextID', related_name='collectionobjects', null=True, on_delete=protect_with_blockers) visibilitysetby = models.ForeignKey('SpecifyUser', db_column='VisibilitySetByID', related_name='+', null=True, on_delete=protect_with_blockers) collectionobjecttype = models.ForeignKey('CollectionObjectType', db_column='CollectionObjectTypeID', related_name='collectionobjects', null=True, on_delete=models.SET_NULL) - component = models.ForeignKey('Component', db_column='ComponentID', related_name='components', null=True, on_delete=models.SET_NULL) class Meta: db_table = 'collectionobject' From ee4ec5f54d8d90d1ddb7b49d9a77b77dfe36e56f Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 07:12:12 -0700 Subject: [PATCH 11/33] Remove pass --- .../specify/migrations/0027_component.py | 112 +++++++++--------- 1 file changed, 55 insertions(+), 57 deletions(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index 3335e2fcb80..85503e6d050 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -82,73 +82,71 @@ class Migration(migrations.Migration): ] def consolidated_python_django_migration_operations(apps, schema_editor): - pass create_table_schema_config_with_defaults(apps) update_schema_config_field_desc(apps) def revert_cosolidated_python_django_migration_operations(apps, schema_editor): - pass revert_table_schema_config_with_defaults(apps) revert_update_hidden_prop(apps) operation = [ - migrations.CreateModel( - name='Component', - fields=[ - ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), - ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), - ('role', models.CharField(db_column='Role', max_length=50)), - ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), - ('uniqueidentifier', models.CharField(blank=True, db_column='UniqueIdentifier', max_length=128, null=True)), - ('text1', models.TextField(blank=True, db_column='Text1', null=True)), - ('text2', models.TextField(blank=True, db_column='Text2', null=True)), - ('text3', models.TextField(blank=True, db_column='Text3', null=True)), - ('text4', models.TextField(blank=True, db_column='Text4', null=True)), - ('text5', models.TextField(blank=True, db_column='Text5', null=True)), - ('text6', models.TextField(blank=True, db_column='Text6', null=True)), - ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), - ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), - ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), - ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), - ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), - ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), - ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), - ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), - ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), - ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), - ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), - ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), - ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), - ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), - ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), - ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), - ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), - ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), - ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), - ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), - ('version', models.IntegerField(blank=True, db_column='Version', default=0, null=True)), - ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=django.db.models.deletion.CASCADE, related_name='components', to='specify.collectionobject')), - ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), - ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), - ('name', models.ForeignKey(db_column='TaxonID', null=True, on_delete=protect_with_blockers, related_name='components', to='specify.taxon')), - ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', null=True, on_delete=protect_with_blockers, related_name='children', to='specify.component')), - ('type', models.ForeignKey(db_column='CollectionObjectTypeID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.collectionobjecttype')), - ], - ), - migrations.AddField( - model_name='absoluteage', - name='component', - field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='absoluteages', to='specify.component'), - ), - migrations.AddField( - model_name='collectionobject', - name='component', - field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.component'), - ), - migrations.AddField( + migrations.CreateModel( + name='Component', + fields=[ + ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), + ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), + ('role', models.CharField(db_column='Role', max_length=50)), + ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), + ('uniqueidentifier', models.CharField(blank=True, db_column='UniqueIdentifier', max_length=128, null=True)), + ('text1', models.TextField(blank=True, db_column='Text1', null=True)), + ('text2', models.TextField(blank=True, db_column='Text2', null=True)), + ('text3', models.TextField(blank=True, db_column='Text3', null=True)), + ('text4', models.TextField(blank=True, db_column='Text4', null=True)), + ('text5', models.TextField(blank=True, db_column='Text5', null=True)), + ('text6', models.TextField(blank=True, db_column='Text6', null=True)), + ('yesno1', models.BooleanField(blank=True, db_column='YesNo1', null=True)), + ('yesno2', models.BooleanField(blank=True, db_column='YesNo2', null=True)), + ('yesno3', models.BooleanField(blank=True, db_column='YesNo3', null=True)), + ('yesno4', models.BooleanField(blank=True, db_column='YesNo4', null=True)), + ('yesno5', models.BooleanField(blank=True, db_column='YesNo5', null=True)), + ('yesno6', models.BooleanField(blank=True, db_column='YesNo6', null=True)), + ('integer1', models.IntegerField(blank=True, db_column='Integer1', null=True)), + ('integer2', models.IntegerField(blank=True, db_column='Integer2', null=True)), + ('integer3', models.IntegerField(blank=True, db_column='Integer3', null=True)), + ('integer4', models.IntegerField(blank=True, db_column='Integer4', null=True)), + ('integer5', models.IntegerField(blank=True, db_column='Integer5', null=True)), + ('integer6', models.IntegerField(blank=True, db_column='Integer6', null=True)), + ('number1', models.DecimalField(blank=True, db_column='Number1', decimal_places=10, max_digits=22, null=True)), + ('number2', models.DecimalField(blank=True, db_column='Number2', decimal_places=10, max_digits=22, null=True)), + ('number3', models.DecimalField(blank=True, db_column='Number3', decimal_places=10, max_digits=22, null=True)), + ('number4', models.DecimalField(blank=True, db_column='Number4', decimal_places=10, max_digits=22, null=True)), + ('number5', models.DecimalField(blank=True, db_column='Number5', decimal_places=10, max_digits=22, null=True)), + ('number6', models.DecimalField(blank=True, db_column='Number6', decimal_places=10, max_digits=22, null=True)), + ('timestampcreated', models.DateTimeField(db_column='TimestampCreated', default=django.utils.timezone.now)), + ('timestampmodified', models.DateTimeField(blank=True, db_column='TimestampModified', default=django.utils.timezone.now, null=True)), + ('version', models.IntegerField(blank=True, db_column='Version', default=0, null=True)), + ('collectionobject', models.ForeignKey(db_column='CollectionObjectID', on_delete=django.db.models.deletion.CASCADE, related_name='components', to='specify.collectionobject')), + ('createdbyagent', models.ForeignKey(db_column='CreatedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), + ('modifiedbyagent', models.ForeignKey(db_column='ModifiedByAgentID', null=True, on_delete=protect_with_blockers, related_name='+', to='specify.agent')), + ('name', models.ForeignKey(db_column='TaxonID', null=True, on_delete=protect_with_blockers, related_name='components', to='specify.taxon')), + ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', null=True, on_delete=protect_with_blockers, related_name='children', to='specify.component')), + ('type', models.ForeignKey(db_column='CollectionObjectTypeID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.collectionobjecttype')), + ], + ), + migrations.AddField( + model_name='absoluteage', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='absoluteages', to='specify.component'), + ), + migrations.AddField( + model_name='collectionobject', + name='component', + field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.component'), + ), + migrations.AddField( model_name='relativeage', name='component', field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='relativeages', to='specify.component'), ), - migrations.RunPython(consolidated_python_django_migration_operations, revert_cosolidated_python_django_migration_operations, atomic=True), + migrations.RunPython(consolidated_python_django_migration_operations, revert_cosolidated_python_django_migration_operations, atomic=True), ] \ No newline at end of file From d7d6731ada1259b947ceac1a547547ddf7fb611e Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 07:12:58 -0700 Subject: [PATCH 12/33] Remove add field on CO in migration --- specifyweb/specify/migrations/0027_component.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index 85503e6d050..932e1bdc2c0 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -138,11 +138,6 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): name='component', field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='absoluteages', to='specify.component'), ), - migrations.AddField( - model_name='collectionobject', - name='component', - field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.component'), - ), migrations.AddField( model_name='relativeage', name='component', From aa64b8a89ec6a765e0bc34a6ec33a82fc53ba3d8 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 07:14:59 -0700 Subject: [PATCH 13/33] Capitalize --- specifyweb/specify/migrations/0027_component.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index 932e1bdc2c0..74e1422846c 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -93,7 +93,7 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): migrations.CreateModel( name='Component', fields=[ - ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), + ('id', models.AutoField(db_column='ComponentID', primary_key=True, serialize=False)), ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), ('role', models.CharField(db_column='Role', max_length=50)), ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), From a72660fe43da26724157c957385ac038a95fceb0 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 07:17:29 -0700 Subject: [PATCH 14/33] Chnage operatio to operations --- specifyweb/specify/migrations/0027_component.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index 74e1422846c..2c929cc881a 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -7,7 +7,7 @@ from specifyweb.specify.migration_utils.sp7_schemaconfig import MIGRATION_0027_TABLES as SCHEMA_CONFIG_TABLES, MIGRATION_0027_FIELDS as SCHEMA_CONFIG_TABLE_FIELDS, MIGRATION_0027_UPDATE_FIELDS as SCHEMA_CONFIG_COMPONENT_TABLE_FIELDS -def create_table_schema_config_with_defaults(apps): +def create_table_schema_config_with_defaults(apps, schema_editor): Discipline = specify_apps.get_model('specify', 'Discipline') for discipline in Discipline.objects.all(): for table, desc in SCHEMA_CONFIG_TABLES: @@ -49,7 +49,7 @@ def update_schema_config_field_desc(apps, schema_editor): localized_items_name.text = new_name localized_items_name.save() -def revert_table_schema_config_with_defaults(apps): +def revert_table_schema_config_with_defaults(apps, schema_editor): for table, _ in SCHEMA_CONFIG_TABLES: revert_table_schema_config(table, apps) for table, fields in SCHEMA_CONFIG_MOD_TABLE_FIELDS.items(): @@ -82,14 +82,14 @@ class Migration(migrations.Migration): ] def consolidated_python_django_migration_operations(apps, schema_editor): - create_table_schema_config_with_defaults(apps) - update_schema_config_field_desc(apps) + create_table_schema_config_with_defaults(apps, schema_editor) + update_schema_config_field_desc(apps, schema_editor) def revert_cosolidated_python_django_migration_operations(apps, schema_editor): - revert_table_schema_config_with_defaults(apps) - revert_update_hidden_prop(apps) + revert_table_schema_config_with_defaults(apps, schema_editor) + revert_update_hidden_prop(apps, schema_editor) - operation = [ + operations = [ migrations.CreateModel( name='Component', fields=[ From 2fef32654789c558ba60dffe9b09488e2f1a37ff Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:11:45 -0700 Subject: [PATCH 15/33] Remove component from CO datamodel --- specifyweb/specify/datamodel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 567a0436a51..11038fdeb38 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,7 +1601,6 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), - Relationship(name='components', type='many-to-one', required=True, relatedModelName='Component', column='ComponentID') ], fieldAliases=[ From 723f716d212334256640ba8cfe86111943ab2de9 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:32:37 -0700 Subject: [PATCH 16/33] Change import --- specifyweb/specify/migrations/0027_component.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index 2c929cc881a..cf98983391d 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -52,7 +52,7 @@ def update_schema_config_field_desc(apps, schema_editor): def revert_table_schema_config_with_defaults(apps, schema_editor): for table, _ in SCHEMA_CONFIG_TABLES: revert_table_schema_config(table, apps) - for table, fields in SCHEMA_CONFIG_MOD_TABLE_FIELDS.items(): + for table, fields in SCHEMA_CONFIG_TABLE_FIELDS.items(): for field in fields: revert_table_field_schema_config(table, field, apps) From 7ea76658c5d02b1176069ee4ddec470bab3c02c2 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:35:40 -0700 Subject: [PATCH 17/33] Update schemaconfig field --- specifyweb/specify/migration_utils/sp7_schemaconfig.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/specifyweb/specify/migration_utils/sp7_schemaconfig.py b/specifyweb/specify/migration_utils/sp7_schemaconfig.py index c4b8e725b64..0322b38234e 100644 --- a/specifyweb/specify/migration_utils/sp7_schemaconfig.py +++ b/specifyweb/specify/migration_utils/sp7_schemaconfig.py @@ -174,10 +174,9 @@ ] MIGRATION_0027_FIELDS = { - 'Collectionobject': ['components'], 'Taxon': ['components'], - 'RelativeAge': ['components'], - 'AbsoluteAge': ['components'], + 'RelativeAge': ['component'], + 'AbsoluteAge': ['component'], } From f61bad63b0ec13389eeabe3104b5c8b1e40b5440 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:04:43 -0700 Subject: [PATCH 18/33] Additions --- specifyweb/specify/datamodel.py | 1 + specifyweb/specify/migration_utils/sp7_schemaconfig.py | 1 + 2 files changed, 2 insertions(+) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 11038fdeb38..5afd8992078 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,6 +1601,7 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), + Relationship(name='components', type='one-to-many',required=False, relatedModelName='Component', otherSideName='collectionObject') ], fieldAliases=[ diff --git a/specifyweb/specify/migration_utils/sp7_schemaconfig.py b/specifyweb/specify/migration_utils/sp7_schemaconfig.py index 0322b38234e..a41c74cc1bb 100644 --- a/specifyweb/specify/migration_utils/sp7_schemaconfig.py +++ b/specifyweb/specify/migration_utils/sp7_schemaconfig.py @@ -174,6 +174,7 @@ ] MIGRATION_0027_FIELDS = { + 'CollectionObject': ['components'], 'Taxon': ['components'], 'RelativeAge': ['component'], 'AbsoluteAge': ['component'], From 552c97e56f84d0315c837f769015a7b79e4becb9 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:09:09 -0700 Subject: [PATCH 19/33] Updates in models --- specifyweb/specify/models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index 300f4013087..0eff3701af2 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -2123,6 +2123,13 @@ class Component(models.Model): createdbyagent = models.ForeignKey('Agent', db_column='CreatedByAgentID', related_name='+', null=True, on_delete=protect_with_blockers) modifiedbyagent = models.ForeignKey('Agent', db_column='ModifiedByAgentID', related_name='+', null=True, on_delete=protect_with_blockers) + class Meta: + db_table = 'component' + ordering = () + + + save = partialmethod(custom_save) + class Conservdescription(models.Model): specify_model = datamodel.get_table_strict('conservdescription') From 5fba994bc9e16ae91c7d5cbdbc3b64f56f0242ce Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:10:09 -0700 Subject: [PATCH 20/33] Updates --- specifyweb/specify/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index 0eff3701af2..17da32ad47f 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -2127,7 +2127,6 @@ class Meta: db_table = 'component' ordering = () - save = partialmethod(custom_save) class Conservdescription(models.Model): From bde1cf210a03fbde6fb552d8b3ba8afe48d41323 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:22:49 -0700 Subject: [PATCH 21/33] Regenerate migration --- specifyweb/specify/migrations/0027_component.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index cf98983391d..e6060cb9167 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -1,7 +1,9 @@ -from django.apps import apps as specify_apps +# Generated by Django 3.2.15 on 2025-04-08 16:19 + from django.db import migrations, models import django.db.models.deletion import django.utils.timezone +import specifyweb.specify.models from specifyweb.specify.models import protect_with_blockers from specifyweb.specify.migration_utils.update_schema_config import revert_table_field_schema_config, revert_table_schema_config, update_table_field_schema_config_with_defaults, update_table_schema_config_with_defaults @@ -93,7 +95,7 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): migrations.CreateModel( name='Component', fields=[ - ('id', models.AutoField(db_column='ComponentID', primary_key=True, serialize=False)), + ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), ('role', models.CharField(db_column='Role', max_length=50)), ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), @@ -132,6 +134,10 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): ('parentcomponent', models.ForeignKey(db_column='ParentComponentID', null=True, on_delete=protect_with_blockers, related_name='children', to='specify.component')), ('type', models.ForeignKey(db_column='CollectionObjectTypeID', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='components', to='specify.collectionobjecttype')), ], + options={ + 'db_table': 'component', + 'ordering': (), + }, ), migrations.AddField( model_name='absoluteage', @@ -144,4 +150,4 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): field=models.ForeignKey(db_column='ComponentID', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='relativeages', to='specify.component'), ), migrations.RunPython(consolidated_python_django_migration_operations, revert_cosolidated_python_django_migration_operations, atomic=True), - ] \ No newline at end of file + ] From bf3845477a70346793b5c2596ea3a96e665d83c1 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:38:03 -0700 Subject: [PATCH 22/33] import --- specifyweb/specify/migrations/0027_component.py | 1 + 1 file changed, 1 insertion(+) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index e6060cb9167..f642b73fae7 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -1,5 +1,6 @@ # Generated by Django 3.2.15 on 2025-04-08 16:19 +from django.apps import apps as specify_apps from django.db import migrations, models import django.db.models.deletion import django.utils.timezone From 2d6748c376081171a258af6328001a7ea1c4b884 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:20:20 -0700 Subject: [PATCH 23/33] Add children --- specifyweb/frontend/js_src/lib/components/DataModel/types.ts | 1 + specifyweb/specify/datamodel.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index d29e965c55c..606aa6d7ddb 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -2012,6 +2012,7 @@ export type Component = { readonly parentComponent: Component | null; readonly createdByAgent: Agent | null; readonly modifiedByAgent: Agent | null; + readonly children: Component | null; }; readonly toManyDependent: { readonly absoluteAges: RA; diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 5afd8992078..fd76bd6c575 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -2243,7 +2243,8 @@ def is_tree_table(table: Table): Relationship(name='collectionObject', type='many-to-one',required=True, relatedModelName='CollectionObject', column='CollectionObjectID', otherSideName='components'), Relationship(name='taxon', type='many-to-one',required=False, relatedModelName='Taxon', column='TaxonID', otherSideName='components'), Relationship(name='type', type='many-to-one', required=True, relatedModelName='CollectionObjectType', column='CollectionObjectTypeID'), - Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ParentComponentID'), + Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ParentComponentID', otherSideName='children'), + Relationship(name='children', type='one-to-many', required=False, relatedModelName='Component', otherSideName='parentComponent'), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='component', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='component', dependent=True), Relationship(name='createdByAgent', type='many-to-one',required=False, relatedModelName='Agent', column='CreatedByAgentID'), From a5e4ed8428c81a338c0135ec1c68c03487eece01 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:33:01 -0700 Subject: [PATCH 24/33] Change children type --- specifyweb/frontend/js_src/lib/components/DataModel/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index 606aa6d7ddb..b8619a9621c 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -2012,12 +2012,14 @@ export type Component = { readonly parentComponent: Component | null; readonly createdByAgent: Agent | null; readonly modifiedByAgent: Agent | null; - readonly children: Component | null; }; readonly toManyDependent: { readonly absoluteAges: RA; readonly relativeAges: RA; }; + readonly toManyIndependent: { + readonly children: RA; + }; }; export type ConservDescription = { readonly tableName: 'ConservDescription'; From 06afaed6d0ba7622b7c9d145216ad4265086b791 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:38:04 -0700 Subject: [PATCH 25/33] Chnage children to dependent --- specifyweb/frontend/js_src/lib/components/DataModel/types.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index b8619a9621c..429f9c72096 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -2016,8 +2016,6 @@ export type Component = { readonly toManyDependent: { readonly absoluteAges: RA; readonly relativeAges: RA; - }; - readonly toManyIndependent: { readonly children: RA; }; }; From e069118972c5115719251c63c852984d198a6cb1 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:51:56 -0700 Subject: [PATCH 26/33] chnage role requirement --- specifyweb/specify/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/models.py b/specifyweb/specify/models.py index 17da32ad47f..75cfbb0ea8a 100644 --- a/specifyweb/specify/models.py +++ b/specifyweb/specify/models.py @@ -2084,7 +2084,7 @@ class Component(models.Model): # Fields verbatimname = models.TextField(blank=True, null=True, unique=False, db_column='VerbatimName', db_index=False) - role = models.CharField(blank=False, max_length=50, null=False, unique=False, db_column='Role', db_index=False) + role = models.CharField(blank=False, max_length=50, null=True, unique=False, db_column='Role', db_index=False) proportion= models.IntegerField(blank=True, null=True, unique=False, db_column='Proportion', db_index=False) uniqueidentifier = models.CharField(blank=True, max_length=128, null=True, unique=False, db_column='UniqueIdentifier', db_index=False) text1 = models.TextField(blank=True, null=True, unique=False, db_column='Text1', db_index=False) From 8ae557e86ecca82cb7ab144cd95b32f449c9cef7 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:05:16 -0700 Subject: [PATCH 27/33] Update taxon to name --- specifyweb/specify/datamodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index fd76bd6c575..c5e08c4fd14 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -2241,7 +2241,7 @@ def is_tree_table(table: Table): indexes=[], relationships=[ Relationship(name='collectionObject', type='many-to-one',required=True, relatedModelName='CollectionObject', column='CollectionObjectID', otherSideName='components'), - Relationship(name='taxon', type='many-to-one',required=False, relatedModelName='Taxon', column='TaxonID', otherSideName='components'), + Relationship(name='name', type='many-to-one',required=False, relatedModelName='Taxon', column='TaxonID', otherSideName='components'), Relationship(name='type', type='many-to-one', required=True, relatedModelName='CollectionObjectType', column='CollectionObjectTypeID'), Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ParentComponentID', otherSideName='children'), Relationship(name='children', type='one-to-many', required=False, relatedModelName='Component', otherSideName='parentComponent'), From c7fd70980fce25a8e2a4b16190738ff56bb07c6b Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:07:25 -0700 Subject: [PATCH 28/33] Change role in migration --- specifyweb/specify/migrations/0027_component.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/migrations/0027_component.py b/specifyweb/specify/migrations/0027_component.py index f642b73fae7..9065dfcfe75 100644 --- a/specifyweb/specify/migrations/0027_component.py +++ b/specifyweb/specify/migrations/0027_component.py @@ -98,7 +98,7 @@ def revert_cosolidated_python_django_migration_operations(apps, schema_editor): fields=[ ('id', models.AutoField(db_column='componentid', primary_key=True, serialize=False)), ('verbatimname', models.TextField(blank=True, db_column='VerbatimName', null=True)), - ('role', models.CharField(db_column='Role', max_length=50)), + ('role', models.CharField(db_column='Role', max_length=50, null=True)), ('proportion', models.IntegerField(blank=True, db_column='Proportion', null=True)), ('uniqueidentifier', models.CharField(blank=True, db_column='UniqueIdentifier', max_length=128, null=True)), ('text1', models.TextField(blank=True, db_column='Text1', null=True)), From c0194c80580df42841535a43f5743143fb3f3fdb Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:32:11 -0700 Subject: [PATCH 29/33] Add dependent to CO component --- specifyweb/specify/datamodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index c5e08c4fd14..31cd7e9f9ca 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -1601,7 +1601,7 @@ def is_tree_table(table: Table): Relationship(name='cojo', type='one-to-one', required=False, relatedModelName='CollectionObjectGroupJoin', otherSideName='childco', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='collectionObject', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='collectionObject', dependent=True), - Relationship(name='components', type='one-to-many',required=False, relatedModelName='Component', otherSideName='collectionObject') + Relationship(name='components', type='one-to-many',required=False, relatedModelName='Component', otherSideName='collectionObject', dependent=True) ], fieldAliases=[ From 53809cb5328c89c38b4945d5c6cbb084288ffc28 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Wed, 9 Apr 2025 06:58:35 -0700 Subject: [PATCH 30/33] include toManyIndependent in types --- specifyweb/frontend/js_src/lib/components/DataModel/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index 429f9c72096..987108159f9 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -2018,6 +2018,7 @@ export type Component = { readonly relativeAges: RA; readonly children: RA; }; + readonly toManyIndependent: RR; }; export type ConservDescription = { readonly tableName: 'ConservDescription'; From 9d469a6ac131adcf848568b1d02fb0a7173a89f2 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:24:18 -0700 Subject: [PATCH 31/33] Set component CO with the parent CO --- specifyweb/businessrules/rules/__init__.py | 1 + specifyweb/businessrules/rules/component_rules.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 specifyweb/businessrules/rules/component_rules.py diff --git a/specifyweb/businessrules/rules/__init__.py b/specifyweb/businessrules/rules/__init__.py index 1936a08b063..a7dc046580d 100644 --- a/specifyweb/businessrules/rules/__init__.py +++ b/specifyweb/businessrules/rules/__init__.py @@ -25,4 +25,5 @@ workbench_rules, cojo_rules, cogtype_rules, + component_rules ) diff --git a/specifyweb/businessrules/rules/component_rules.py b/specifyweb/businessrules/rules/component_rules.py new file mode 100644 index 00000000000..04b1c1d59de --- /dev/null +++ b/specifyweb/businessrules/rules/component_rules.py @@ -0,0 +1,14 @@ +from enum import Enum + +from django.db.models import Max + +from specifyweb.businessrules.exceptions import BusinessRuleException +from specifyweb.businessrules.orm_signal_handler import orm_signal_handler +from specifyweb.specify.models import Component + +@orm_signal_handler('pre_save', 'Component') +def component_pre_save(component): + if component.parentcomponent is not None: + component.collectionobject = component.parentcomponent.collectionobject + + From 5df922a3ced3f8794860517e575ca27e283bc84f Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Thu, 10 Apr 2025 07:03:29 -0700 Subject: [PATCH 32/33] Improve conditional in backendrules --- specifyweb/businessrules/rules/component_rules.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specifyweb/businessrules/rules/component_rules.py b/specifyweb/businessrules/rules/component_rules.py index 04b1c1d59de..8c4c9d7eb86 100644 --- a/specifyweb/businessrules/rules/component_rules.py +++ b/specifyweb/businessrules/rules/component_rules.py @@ -8,7 +8,9 @@ @orm_signal_handler('pre_save', 'Component') def component_pre_save(component): - if component.parentcomponent is not None: + if component.parentcomponent is not None and not hasattr(component, "collectionobject"): component.collectionobject = component.parentcomponent.collectionobject + component.save() + component.parentcomponent.collectionobject.components.add(component) From a2ae877b663895c3797c7645831423a3fd0b5ff7 Mon Sep 17 00:00:00 2001 From: Caroline D <108160931+CarolineDenis@users.noreply.github.com> Date: Fri, 11 Apr 2025 08:26:55 -0700 Subject: [PATCH 33/33] Make component dependent --- specifyweb/businessrules/rules/component_rules.py | 14 +++++++------- .../js_src/lib/components/DataModel/types.ts | 2 +- specifyweb/specify/datamodel.py | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/specifyweb/businessrules/rules/component_rules.py b/specifyweb/businessrules/rules/component_rules.py index 8c4c9d7eb86..accfef6aaf1 100644 --- a/specifyweb/businessrules/rules/component_rules.py +++ b/specifyweb/businessrules/rules/component_rules.py @@ -1,6 +1,3 @@ -from enum import Enum - -from django.db.models import Max from specifyweb.businessrules.exceptions import BusinessRuleException from specifyweb.businessrules.orm_signal_handler import orm_signal_handler @@ -8,9 +5,12 @@ @orm_signal_handler('pre_save', 'Component') def component_pre_save(component): - if component.parentcomponent is not None and not hasattr(component, "collectionobject"): - component.collectionobject = component.parentcomponent.collectionobject - component.save() - component.parentcomponent.collectionobject.components.add(component) + if component.parentcomponent is not None and not hasattr(component, "collectionobject"): + component.collectionobject = component.parentcomponent.collectionobject + component.save() + component.parentcomponent.children.add(component) + component.parentcomponent.save() + component.parentcomponent.collectionobject.components.add(component) + component.parentcomponent.collectionobject.save() diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts index 987108159f9..8349415dc17 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/types.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/types.ts @@ -2009,9 +2009,9 @@ export type Component = { readonly toOneIndependent: { readonly type: CollectionObjectType; readonly name: Taxon | null; - readonly parentComponent: Component | null; readonly createdByAgent: Agent | null; readonly modifiedByAgent: Agent | null; + readonly parentComponent: Component | null; }; readonly toManyDependent: { readonly absoluteAges: RA; diff --git a/specifyweb/specify/datamodel.py b/specifyweb/specify/datamodel.py index 31cd7e9f9ca..048c72e56a7 100644 --- a/specifyweb/specify/datamodel.py +++ b/specifyweb/specify/datamodel.py @@ -2244,7 +2244,7 @@ def is_tree_table(table: Table): Relationship(name='name', type='many-to-one',required=False, relatedModelName='Taxon', column='TaxonID', otherSideName='components'), Relationship(name='type', type='many-to-one', required=True, relatedModelName='CollectionObjectType', column='CollectionObjectTypeID'), Relationship(name='parentComponent', type='many-to-one', required=False, relatedModelName='Component', column='ParentComponentID', otherSideName='children'), - Relationship(name='children', type='one-to-many', required=False, relatedModelName='Component', otherSideName='parentComponent'), + Relationship(name='children', type='one-to-many', required=False, relatedModelName='Component', otherSideName='parentComponent', dependent=True), Relationship(name='absoluteAges', type='one-to-many', required=False, relatedModelName='AbsoluteAge', otherSideName='component', dependent=True), Relationship(name='relativeAges', type='one-to-many', required=False, relatedModelName='RelativeAge', otherSideName='component', dependent=True), Relationship(name='createdByAgent', type='many-to-one',required=False, relatedModelName='Agent', column='CreatedByAgentID'),