From 1b65059336b4edb11f0e647badde08963920cbd9 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Fri, 30 Jul 2021 23:46:30 +0000 Subject: [PATCH] --- .vscode/launch.json | 2 +- server/AyaNova/biz/PMBiz.cs | 173 +++++++++++++++++++++++------------- 2 files changed, 113 insertions(+), 62 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fcc80a75..b77f3b95 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": "true", + "AYANOVA_SERVER_TEST_MODE": "false", "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/PMBiz.cs b/server/AyaNova/biz/PMBiz.cs index 40ad8095..984b4f05 100644 --- a/server/AyaNova/biz/PMBiz.cs +++ b/server/AyaNova/biz/PMBiz.cs @@ -1406,7 +1406,7 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await ExpenseSearchIndexAsync(newObject, true); - + await ExpenseHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ExpensePopulateVizFields(newObject); return newObject; @@ -1488,8 +1488,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await ExpenseHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -1756,7 +1756,7 @@ namespace AyaNova.Biz if (HasErrors) return null; else - { + { await ct.PMItemLabor.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); @@ -1819,7 +1819,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LaborSearchIndexAsync(putObject, false); - + await LaborHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LaborPopulateVizFields(putObject); return putObject; @@ -1843,8 +1843,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await LaborHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2057,7 +2057,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -2151,7 +2151,7 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await LoanSearchIndexAsync(newObject, true); - + await LoanHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LoanPopulateVizFields(newObject); return newObject; @@ -2207,7 +2207,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LoanSearchIndexAsync(putObject, false); - + await LoanHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LoanPopulateVizFields(putObject); return putObject; @@ -2231,8 +2231,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await LoanHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2453,7 +2453,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -2547,12 +2547,12 @@ namespace AyaNova.Biz else { // newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - + await ct.PMItemOutsideService.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await OutsideServiceSearchIndexAsync(newObject, true); - + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await OutsideServicePopulateVizFields(newObject); return newObject; @@ -2590,8 +2590,8 @@ namespace AyaNova.Biz } - - + + await OutsideServiceValidateAsync(putObject, dbObject); if (HasErrors) return null; @@ -2610,7 +2610,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await OutsideServiceSearchIndexAsync(putObject, false); - + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await OutsideServicePopulateVizFields(putObject); @@ -2635,8 +2635,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2772,7 +2772,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -2870,8 +2870,8 @@ namespace AyaNova.Biz else { await PartBizActionsAsync(AyaEvent.Created, newObject, null, null); - - + + await ct.PMItemPart.AddAsync(newObject); await ct.SaveChangesAsync(); if (HasErrors) @@ -2882,7 +2882,7 @@ namespace AyaNova.Biz await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await PartSearchIndexAsync(newObject, true); await transaction.CommitAsync(); - + await PartPopulateVizFields(newObject); return newObject; } @@ -2922,8 +2922,8 @@ namespace AyaNova.Biz return null; } - - + + await PartValidateAsync(putObject, dbObject); if (HasErrors) return null; @@ -2948,7 +2948,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await PartSearchIndexAsync(putObject, false); - + await PartHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await transaction.CommitAsync(); await PartPopulateVizFields(putObject); @@ -2980,8 +2980,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await PartHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3232,7 +3232,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -3320,13 +3320,13 @@ namespace AyaNova.Biz return null; else { - - + + await ct.PMItemScheduledUser.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); - - + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ScheduledUserPopulateVizFields(newObject); return newObject; @@ -3363,8 +3363,8 @@ namespace AyaNova.Biz return null; } - - + + await ScheduledUserValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3381,8 +3381,8 @@ namespace AyaNova.Biz return null; } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); - - + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await ScheduledUserPopulateVizFields(putObject); return putObject; @@ -3406,8 +3406,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3510,7 +3510,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -3594,13 +3594,13 @@ namespace AyaNova.Biz return null; else { - - + + await ct.PMItemTask.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await TaskSearchIndexAsync(newObject, true); - + await TaskHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await TaskPopulateVizFields(newObject); return newObject; @@ -3634,8 +3634,8 @@ namespace AyaNova.Biz AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - - + + await TaskValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3653,7 +3653,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TaskSearchIndexAsync(dbObject, false); - + await TaskHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TaskPopulateVizFields(putObject); return putObject; @@ -3677,8 +3677,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await TaskHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3790,7 +3790,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -3934,7 +3934,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TravelSearchIndexAsync(putObject, false); - + await TravelHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TravelPopulateVizFields(putObject); return putObject; @@ -3958,8 +3958,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.PMItemId.ToString(), ct); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - - + + if (parentTransaction == null) await transaction.CommitAsync(); await TravelHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -4158,7 +4158,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - + } } @@ -4241,8 +4241,8 @@ namespace AyaNova.Biz // internal async Task UnitCreateAsync(PMItemUnit newObject) { - - + + await UnitValidateAsync(newObject, null); @@ -4250,7 +4250,7 @@ namespace AyaNova.Biz return null; else { - + newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.PMItemUnit.AddAsync(newObject); @@ -4421,8 +4421,8 @@ namespace AyaNova.Biz //skip validation if seeding // if (ServerBootConfig.SEEDING) return; - - + + //run validation and biz rules bool isNew = currentObj == null; @@ -4917,13 +4917,64 @@ namespace AyaNova.Biz foreach (PMItemPart pmp in pmi.Parts) { + + //Check inventory, if insufficient, create part request for balance and make a part record for the available amount even if it's zero as a placeholder + //Exception to this: if this part/warehouse combo was already requested anywhere on this work order then we know it's already out of stock so just add it all + //as a part request + + //Already requested part/warehouse combo? (means already out of stock effectively) + bool AlreadyRequestedOnThisWorkOrder = false; + + foreach (var inventCheckItem in wo.Items) + { + foreach (var inventRequest in inventCheckItem.PartRequests) + { + if (inventRequest.PartId == pmp.PartId && inventRequest.PartWarehouseId == pmp.PartWarehouseId) + { + AlreadyRequestedOnThisWorkOrder = true; + break; + } + } + if (AlreadyRequestedOnThisWorkOrder) break; + } + + decimal wipQuantity = pmp.Quantity; + decimal requestQuantity = 0; + + if (AlreadyRequestedOnThisWorkOrder) + { + wipQuantity = 0; + requestQuantity = pmp.Quantity; + } + else + { + //not already requested, so check inventory, this is new + var CurrentInventory = await ct.PartInventory.AsNoTracking().OrderByDescending(m => m.EntryDate).FirstOrDefaultAsync(m => m.PartId == pmp.PartId && m.PartWarehouseId == pmp.PartWarehouseId); + if (CurrentInventory.Balance < pmp.Quantity) + { + //we will need a part request here and also need to reserve what there is available + wipQuantity = (decimal)CurrentInventory.Balance; + requestQuantity = pmp.Quantity - wipQuantity; + } + } + + //Add request if necessary + if (requestQuantity != 0) + { + var wipr = new WorkOrderItemPartRequest(); + wipr.PartId = pmp.PartId; + wipr.PartWarehouseId = pmp.PartWarehouseId; + wipr.Quantity = requestQuantity; + woi.PartRequests.Add(wipr); + } + + //Add part var wip = new WorkOrderItemPart(); wip.Description = pmp.Description; wip.PartId = pmp.PartId; wip.PartWarehouseId = pmp.PartWarehouseId; wip.PriceOverride = pmp.PriceOverride; - wip.Quantity = pmp.Quantity; - //wip.Serials=pmp.Serials; + wip.Quantity = wipQuantity; wip.Tags = pmp.Tags; wip.TaxPartSaleId = pmp.TaxPartSaleId;