diff --git a/.vscode/launch.json b/.vscode/launch.json index 0e2049e9..8fd97968 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -53,7 +53,7 @@ "AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles", "AYANOVA_FOLDER_BACKUP_FILES": "c:\\temp\\RavenTestData\\backupfiles", "AYANOVA_FOLDER_TEMPORARY_SERVER_FILES": "c:\\temp\\RavenTestData\\tempfiles", - "AYANOVA_SERVER_TEST_MODE": "false", + "AYANOVA_SERVER_TEST_MODE": "true", "AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "small", "AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-7", "AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_13\\bin\\" diff --git a/server/AyaNova/biz/PartInventoryBiz.cs b/server/AyaNova/biz/PartInventoryBiz.cs index dae5d038..49cc2faf 100644 --- a/server/AyaNova/biz/PartInventoryBiz.cs +++ b/server/AyaNova/biz/PartInventoryBiz.cs @@ -54,8 +54,8 @@ namespace AyaNova.Biz newObject.EntryDate = DateTime.UtcNow; newObject.PartId = newDtObject.PartId; newObject.PartWarehouseId = newDtObject.PartWarehouseId; - newObject.SourceId = 0; - newObject.SourceType = AyaType.NoType; + newObject.SourceId = null; + newObject.SourceType = null; newObject.Quantity = newDtObject.Quantity; if (LastEntry != null) @@ -162,6 +162,7 @@ namespace AyaNova.Biz private async Task ValidateAsync(PartInventory proposedObj) { + //NOTE: Many of these errors wouldn't happen in the official ayanova UI (api developer error only) so are not translated if (!await BizObjectExistsInDatabase.ExistsAsync(AyaType.Part, proposedObj.PartId, ct)) { AddError(ApiErrorCode.NOT_FOUND, "generalerror", $"PartInventory Part specified doesn't exist [id:{proposedObj.PartId}]"); @@ -174,21 +175,18 @@ namespace AyaNova.Biz return; } - if (proposedObj.SourceType != AyaType.NoType && proposedObj.SourceId != 0 && !await BizObjectExistsInDatabase.ExistsAsync(proposedObj.SourceType, proposedObj.SourceId, ct)) + //Source id and type must either both be null or neither be null + if ((proposedObj.SourceId == null && proposedObj.SourceType != null) || (proposedObj.SourceId != null && proposedObj.SourceType == null)) { - AddError(ApiErrorCode.NOT_FOUND, "generalerror", $"PartInventory source object causing inventory change specified doesn't exist [type:{proposedObj.SourceType}, id:{proposedObj.SourceId}]"); + AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "generalerror", "Source type and id must be specified or both null for a manual adjustment"); return; } - - /* - "CONSTRAINT UNQ_PartInventory UNIQUE (sourceid, sourcetype, entrydate, balance), " + - "CONSTRAINT UNQ_PartInventory_Previous_values UNIQUE (sourceid, sourcetype, lastentrydate, lastbalance), " + - "CONSTRAINT fk_PartInventory_self FOREIGN KEY (sourceid, sourcetype, lastentrydate, lastbalance) references apartinventory(sourceid, sourcetype, entrydate, balance), " + - "CONSTRAINT CHK_PartInventory_Valid_Balance CHECK(balance >= 0 AND (balance = COALESCE(lastbalance, 0) + quantity)), " + - "CONSTRAINT CHK_PartInventory_Valid_Dates_Sequence CHECK(lastentrydate < entrydate), " + - "CONSTRAINT CHK_PartInventory_Valid_Previous_Columns CHECK((lastentrydate IS NULL AND lastbalance IS NULL) OR (lastentrydate IS NOT NULL AND lastbalance IS NOT NULL)) " + - */ + if (proposedObj.SourceType != null && proposedObj.SourceId != null && !await BizObjectExistsInDatabase.ExistsAsync((AyaType)proposedObj.SourceType, (long)proposedObj.SourceId, ct)) + { + AddError(ApiErrorCode.NOT_FOUND, "generalerror", $"PartInventory source object causing inventory change specified doesn't exist [type:{proposedObj.SourceType}, id:{proposedObj.SourceId}]"); + return; + } //New entry must have *something* to bank if (proposedObj.Quantity == 0) @@ -214,8 +212,6 @@ namespace AyaNova.Biz //valid previous columns? //either they're all null or none of them are null - - //fix and re-test if (!((proposedObj.LastEntryDate == null && proposedObj.LastBalance == null) || (proposedObj.LastEntryDate != null diff --git a/server/AyaNova/models/PartInventory.cs b/server/AyaNova/models/PartInventory.cs index 9298672c..bd3ad6a4 100644 --- a/server/AyaNova/models/PartInventory.cs +++ b/server/AyaNova/models/PartInventory.cs @@ -25,10 +25,10 @@ namespace AyaNova.Models public long PartId { get; set; } [Required] public long PartWarehouseId { get; set; } - [Required] - public long SourceId { get; set; } - [Required] - public AyaType SourceType { get; set; } + + public long? SourceId { get; set; } + public AyaType? SourceType { get; set; } + [Required] public decimal Quantity { get; set; } [Required] @@ -39,9 +39,7 @@ namespace AyaNova.Models public PartInventory() { - EntryDate = DateTime.UtcNow; - SourceId = 0; - SourceType = AyaType.NoType; + EntryDate = DateTime.UtcNow; } diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 9cfadeda..55c80fb2 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -691,7 +691,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); //PART INVENTORY await ExecQueryAsync("CREATE TABLE apartinventory (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, description TEXT NULL, " + "entrydate TIMESTAMP NOT NULL, lastentrydate TIMESTAMP NULL, partid BIGINT NOT NULL REFERENCES apart, partwarehouseid BIGINT NOT NULL REFERENCES apartwarehouse, " + - "sourcetype INTEGER NOT NULL, sourceid BIGINT NOT NULL, " + + "sourcetype INTEGER, sourceid BIGINT, " + "quantity DECIMAL(19,4) NOT NULL, balance DECIMAL(19,4) NOT NULL, lastbalance DECIMAL(19,4) NULL, " + "CONSTRAINT unq_partinventory UNIQUE (sourceid, sourcetype, entrydate, balance), " + "CONSTRAINT unq_partinventory_previous_values UNIQUE (sourceid, sourcetype, lastentrydate, lastbalance), " + @@ -699,6 +699,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); "CONSTRAINT chk_partinventory_valid_balance CHECK(balance >= 0 AND (balance = COALESCE(lastbalance, 0) + quantity)), " + "CONSTRAINT chk_partinventory_valid_dates_sequence CHECK(lastentrydate < entrydate), " + "CONSTRAINT chk_partinventory_valid_previous_columns CHECK((lastentrydate IS NULL AND lastbalance IS NULL) OR (lastentrydate IS NOT NULL AND lastbalance IS NOT NULL)) " + + "CONSTRAINT chk_partinventory_valid_source CHECK((sourcetype IS NULL AND sourceid IS NULL) OR (sourcetype IS NOT NULL AND sourceid IS NOT NULL)) " + " )"); //PART INVENTORY VIEW