Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Business Rules #2924

Open
11 of 14 tasks
melton-jason opened this issue Jan 30, 2023 · 6 comments
Open
11 of 14 tasks

Refactor Business Rules #2924

melton-jason opened this issue Jan 30, 2023 · 6 comments
Assignees
Labels
1 - Request Improvements or extensions to existing behavior 2 - Forms Issues that are related to the form system
Projects

Comments

@melton-jason
Copy link
Contributor

melton-jason commented Jan 30, 2023

Priorities

After the Priorities have been addressed, any of the following issues (in no particular order) should be considered for fixing, organized by Frontend/Backend/Both:

Frontend

Backend

Both

@melton-jason melton-jason added 1 - Request Improvements or extensions to existing behavior pri:unknown labels Jan 30, 2023
@maxpatiiuk
Copy link
Member

All very important things. Thanks for doing this!
If you have any questions don't hesitate

@maxpatiiuk maxpatiiuk added this to Unsorted in Forms via automation Jan 31, 2023
@grantfitzsimmons grantfitzsimmons self-assigned this Feb 14, 2023
@melton-jason
Copy link
Contributor Author

In addition to refactoring, there may be many Uniqueness Rules enforced at a database level but not enforced in Specify.
When a value in the field violates such a rule, it throws a SQLAlchemy Integrity Error.

Here are the rules I have identified thus far:

  • Preparation.barCode
  • CollectionObject.UniqueIdentifier
  • CollectingEvent.UniqueIdentifier

The majority of these would be very easy to add as uniqueness rules, would prevent data loss from error dialogs, and give instant feed back when the field is changed that the value is violating a uniqueness rule.

The hard part is scouring through the database indices to find the unique fields.

@maxpatiiuk
Copy link
Member

Run grep UNIQUE _blank.sql on specify database dump:

blank.sql_:/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
blank.sql_:  UNIQUE KEY `Role` (`Role`,`AgentID`,`AccessionID`),
blank.sql_:  UNIQUE KEY `AgentID` (`AgentID`,`OrderNumber`),
blank.sql_:  UNIQUE KEY `AppraisalNumber` (`AppraisalNumber`),
blank.sql_:  UNIQUE KEY `ReferenceWorkID` (`ReferenceWorkID`,`AgentID`),
blank.sql_:  UNIQUE KEY `Role` (`Role`,`AgentID`,`BorrowID`),
blank.sql_:  UNIQUE KEY `DisciplineID` (`DisciplineID`,`UniqueIdentifier`),
blank.sql_:  UNIQUE KEY `CollectionID` (`CollectionID`,`UniqueIdentifier`),
blank.sql_:  UNIQUE KEY `CollectionID_2` (`CollectionID`,`CatalogNumber`),
blank.sql_:  UNIQUE KEY `AgentID` (`AgentID`,`CollectingEventID`),
blank.sql_:  UNIQUE KEY `Role` (`Role`,`AgentID`,`DeaccessionID`),
blank.sql_:  UNIQUE KEY `ReferenceWorkID` (`ReferenceWorkID`,`DeterminationID`),
blank.sql_:  UNIQUE KEY `Role` (`Role`,`AgentID`,`DisposalID`),
blank.sql_:  UNIQUE KEY `AgentID` (`AgentID`,`DNASequenceID`),
blank.sql_:  UNIQUE KEY `AgentID` (`AgentID`,`CollectingTripID`),
blank.sql_:  UNIQUE KEY `Role` (`Role`,`GiftID`,`AgentID`),
blank.sql_:  UNIQUE KEY `OrderNumber` (`OrderNumber`,`GroupID`),
blank.sql_:  UNIQUE KEY `Role` (`Role`,`LoanID`,`AgentID`),
blank.sql_:  UNIQUE KEY `DisciplineID` (`DisciplineID`,`UniqueIdentifier`),
blank.sql_:  UNIQUE KEY `ReferenceWorkID` (`ReferenceWorkID`,`LocalityID`),
blank.sql_:  UNIQUE KEY `AgentID` (`AgentID`,`DNASequenceID`),
blank.sql_:  UNIQUE KEY `CollectionMemberID` (`CollectionMemberID`,`BarCode`),
blank.sql_:  UNIQUE KEY `Name` (`Name`),
blank.sql_:/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;

@maxpatiiuk
Copy link
Member

not as helpful without table names, but you can probably open a database dump in an editor and search for UNIQUE

also, maybe there is a way to detect in Python whether a database field is unique?
Also, I belive the schema XML may have indication of what fields are unique - if it does, using that would be the best solution (as it would update automatically as new fields are added to schema)

@melton-jason
Copy link
Contributor Author

I have a SQL script which lists the table names index names, and columns on which to enforce uniqueness, so the hard part is mostly done.

Yes, there is probably a way in Python to detect unique/indexed fields. The best place to look for this might be in stored_queries/build_models.py as that heavily uses SQLAlchemy to build the models on top of the Django models built from the schema xml.

The schema XML does have an attribute for each field stating whether it is unique or not, but I don't think it provides information on what the field should be unique in. Does it?

@melton-jason
Copy link
Contributor Author

Here are a list of all Unique keys in the Specify7 database:

(Note that there may be some discrepancies between databases, as discovered in #2886 (comment))

TableName IndexName Unique Columns
accessionagent Role Role, AgentID, AccessionID
agentspecialty AgentID AgentID, OrderNumber
appraisal AppraisalNumber AppraisalNumber
author ReferenceWorkID ReferenceWorkID, AgentID
auth_group name name
auth_group_permissions auth_group_permissions_group_id_permission_id_0cd325b0_uniq group_id, permission_id
auth_permission auth_permission_content_type_id_codename_01ab375a_uniq content_type_id, codename
borrowagent Role Role, AgentID, BorrowID
collectingevent DisciplineID DisciplineID, UniqueIdentifier
collectionobject CollectionID CollectionID, UniqueIdentifier
collectionobject CollectionID_2 CollectionID, CatalogNumber
collector AgentID AgentID, CollectingEventID
deaccessionagent Role Role, AgentID, DeaccessionID
determinationcitation ReferenceWorkID ReferenceWorkID, DeterminationID
determiner AgentID AgentID, DeterminationID
disposalagent Role Role, AgentID, DisposalID
django_content_type django_content_type_app_label_model_76bd3d3b_uniq app_label, model
extractor AgentID AgentID, DNASequenceID
fundingagent AgentID AgentID, CollectingTripID
giftagent Role Role, GiftID, AgentID
groupperson OrderNumber OrderNumber, GroupID
loanagent Role Role, LoanID, AgentID
locality DisciplineID DisciplineID, UniqueIdentifier
localitycitation ReferenceWorkID ReferenceWorkID, LocalityID
pcrperson AgentID AgentID, DNASequenceID
preparation CollectionMemberID CollectionMemberID, BarCode
specifyuser Name Name

Here is the SQL script:

select stat.table_name,
       stat.index_name,
       group_concat(stat.column_name
       order by stat.seq_in_index separator ', ') as columns
from information_schema.statistics stat
join information_schema.table_constraints tco
       on stat.table_schema = tco.table_schema
       and stat.table_name = tco.table_name
       and stat.index_name = tco.constraint_name
where stat.non_unique = 0
       and stat.table_schema = 'specify'
       and tco.constraint_type = 'UNIQUE'
group by stat.table_schema,
       stat.table_name,
       stat.index_name,
       tco.constraint_type
order by stat.table_name;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1 - Request Improvements or extensions to existing behavior 2 - Forms Issues that are related to the form system
Projects
Status: 🏗 In progress
Forms
  
Unsorted
Status: 📋 Backlog
Development

No branches or pull requests

3 participants