Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import type { BusinessRuleResult } from './businessRules';
import {
COG_PRIMARY_KEY,
COG_TOITSELF,
COJO_PRIMARY_DELETE_KEY,
CURRENT_DETERMINATION_KEY,
DETERMINATION_TAXON_KEY,
ensureSingleCollectionObjectCheck,
hasNoCurrentDetermination,
PREPARATION_DISPOSED_KEY,
PREPARATION_EXCHANGED_IN_KEY,
PREPARATION_EXCHANGED_OUT_KEY,
PREPARATION_GIFTED_KEY,
PREPARATION_LOANED_KEY,
} from './businessRuleUtils';
import { cogTypes } from './helpers';
import type { AnySchema, CommonFields, TableFields } from './helperTypes';
Expand Down Expand Up @@ -332,7 +338,7 @@ export const businessRuleDefs: MappedBusinessRuleDefs = {
collection.related ?? cojo,
cojo.specifyTable.field.parentCog,
[resourcesText.deletePrimaryRecord()],
resourcesText.primaryDeletionErrorMessage()
COJO_PRIMARY_DELETE_KEY
);
}
if (collection?.related?.specifyTable === tables.CollectionObjectGroup) {
Expand Down Expand Up @@ -596,4 +602,48 @@ export const businessRuleDefs: MappedBusinessRuleDefs = {
},
},
},
Preparation: {
onRemoved: (preparation, collection): void => {
if (preparation.get('isOnLoan') === true) {
setSaveBlockers(
collection.related ?? preparation,
preparation.specifyTable.field.isOnLoan,
[resourcesText.deleteLoanedPrep()],
PREPARATION_LOANED_KEY
)
}
if (preparation.get('isOnGift') === true) {
setSaveBlockers(
collection.related ?? preparation,
preparation.specifyTable.field.isOnGift,
[resourcesText.deleteGiftedPrep()],
PREPARATION_GIFTED_KEY
)
}
if (preparation.get('isOnDisposal') === true) {
setSaveBlockers(
collection.related ?? preparation,
preparation.specifyTable.field.isOnDisposal,
[resourcesText.deleteDisposedPrep()],
PREPARATION_DISPOSED_KEY
)
}
if (preparation.get('isOnExchangeOut') === true) {
setSaveBlockers(
collection.related ?? preparation,
preparation.specifyTable.field.isOnExchangeOut,
[resourcesText.deleteExchangeOutPrep()],
PREPARATION_EXCHANGED_OUT_KEY
)
}
if (preparation.get('isOnExchangeIn') === true) {
setSaveBlockers(
collection.related ?? preparation,
preparation.specifyTable.field.isOnExchangeIn,
[resourcesText.deleteExchangeInPrep()],
PREPARATION_EXCHANGED_IN_KEY
)
}
}
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ export const COG_TOITSELF = 'cog-toItself';
export const PARENTCOG_KEY = 'cog-parentCog';
export const COG_PRIMARY_KEY = 'cog-isPrimary';
export const DETERMINATION_TAXON_KEY = 'determination-Taxon';
export const PREPARATION_LOANED_KEY = 'preparation-isLoaned';
export const PREPARATION_GIFTED_KEY = 'preparation-isGifted';
export const PREPARATION_DISPOSED_KEY = 'preparation-isDisposed';
export const PREPARATION_EXCHANGED_OUT_KEY = 'preparation-isExchangedOut';
export const PREPARATION_EXCHANGED_IN_KEY = 'preparation-isExchangedIn';
export const COJO_PRIMARY_DELETE_KEY = 'primary-cojo-delete'

/**
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,38 @@ export const schemaExtras: {
indexed: false,
unique: false,
}),
new LiteralField(table, {
name: 'isOnGift',
required: false,
readOnly: true,
type: 'java.lang.Boolean',
indexed: false,
unique: false,
}),
new LiteralField(table, {
name: 'isOnDisposal',
required: false,
readOnly: true,
type: 'java.lang.Boolean',
indexed: false,
unique: false,
}),
new LiteralField(table, {
name: 'isOnExchangeOut',
required: false,
readOnly: true,
type: 'java.lang.Boolean',
indexed: false,
unique: false,
}),
new LiteralField(table, {
name: 'isOnExchangeIn',
required: false,
readOnly: true,
type: 'java.lang.Boolean',
indexed: false,
unique: false,
}),
new LiteralField(table, {
name: 'actualCountAmt',
required: false,
Expand Down
4 changes: 4 additions & 0 deletions specifyweb/frontend/js_src/lib/components/DataModel/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4386,6 +4386,10 @@ export type Preparation = {
readonly integer1: number | null;
readonly integer2: number | null;
readonly isOnLoan: boolean | null;
readonly isOnGift: boolean | null;
readonly isOnDisposal: boolean | null;
readonly isOnExchangeOut: boolean | null;
readonly isOnExchangeIn: boolean | null;
readonly number1: number | null;
readonly number2: number | null;
readonly preparedDate: string | null;
Expand Down
17 changes: 14 additions & 3 deletions specifyweb/frontend/js_src/lib/localization/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -849,9 +849,20 @@ export const resourcesText = createDictionary({
deletePrimaryRecord: {
'en-us': 'Primary record CO cannot be deleted.',
},
primaryDeletionErrorMessage: {
'en-us':
'This record cannot be deleted as it is the primary record of the Collection Object Group. Please reload the page, then assign another CO as the primary record if a change is desired.',
deleteLoanedPrep: {
'en-us': 'A loaned preparation cannot be deleted',
},
deleteGiftedPrep: {
'en-us': 'A gifted preparation cannot be deleted',
},
deleteDisposedPrep: {
'en-us': 'A disposed preparation cannot be deleted',
},
deleteExchangeOutPrep: {
'en-us': 'A exchanged out preparation cannot be deleted',
},
deleteExchangeInPrep: {
'en-us': 'A exchanged in preparation cannot be deleted',
},
invalidDeterminationTaxon: {
'en-us':
Expand Down
4 changes: 4 additions & 0 deletions specifyweb/specify/calculated_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def calculate_extra_fields(obj, data: Dict[str, Any]) -> Dict[str, Any]:

extra["actualCountAmt"] = actual_count_amount
extra["isonloan"] = obj.isonloan()
extra["isongift"] = obj.isongift()
extra["isondisposal"] = obj.isondisposal()
extra["isonexchangeout"] = obj.isonexchangeout()
extra["isonexchangein"] = obj.isonexchangein()

elif isinstance(obj, Specifyuser):
extra["isadmin"] = obj.is_admin()
Expand Down
64 changes: 64 additions & 0 deletions specifyweb/specify/model_extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,70 @@ def isonloan(self):
result = cursor.fetchone()
return result[0] > 0

def isongift(self):
# TODO: needs unit tests
from django.db import connection
cursor = connection.cursor()

cursor.execute("""
SELECT COALESCE(
SUM({GREATEST}(0, COALESCE(Quantity, 0))),
0)
FROM giftpreparation
WHERE PreparationID = %s
""".format(GREATEST='MAX' if connection.vendor == 'sqlite' else 'GREATEST'), [self.id])

result = cursor.fetchone()
return result[0] > 0

def isondisposal(self):
# TODO: needs unit tests
from django.db import connection
cursor = connection.cursor()

cursor.execute("""
SELECT COALESCE(
SUM({GREATEST}(0, COALESCE(Quantity, 0))),
0)
FROM disposalpreparation
WHERE PreparationID = %s
""".format(GREATEST='MAX' if connection.vendor == 'sqlite' else 'GREATEST'), [self.id])

result = cursor.fetchone()
return result[0] > 0

def isonexchangeout(self):
# TODO: needs unit tests
from django.db import connection
cursor = connection.cursor()

cursor.execute("""
SELECT COALESCE(
SUM({GREATEST}(0, COALESCE(Quantity, 0))),
0)
FROM exchangeoutprep
WHERE PreparationID = %s
""".format(GREATEST='MAX' if connection.vendor == 'sqlite' else 'GREATEST'), [self.id])

result = cursor.fetchone()
return result[0] > 0

def isonexchangein(self):
# TODO: needs unit tests
from django.db import connection
cursor = connection.cursor()

cursor.execute("""
SELECT COALESCE(
SUM({GREATEST}(0, COALESCE(Quantity, 0))),
0)
FROM exchangeinprep
WHERE PreparationID = %s
""".format(GREATEST='MAX' if connection.vendor == 'sqlite' else 'GREATEST'), [self.id])

result = cursor.fetchone()
return result[0] > 0

class Meta:
abstract = True

Expand Down
Loading