diff --git a/server/AyaNova/biz/NotifySubscriptionBiz.cs b/server/AyaNova/biz/NotifySubscriptionBiz.cs index 1c11286f..19ddf750 100644 --- a/server/AyaNova/biz/NotifySubscriptionBiz.cs +++ b/server/AyaNova/biz/NotifySubscriptionBiz.cs @@ -156,7 +156,7 @@ namespace AyaNova.Biz await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.EventType.ToString(), ct); // await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + //TODO: DELETE RELATED RECORDS HERE //all good do the commit diff --git a/server/AyaNova/biz/PMBiz.cs b/server/AyaNova/biz/PMBiz.cs index c523767a..40ad8095 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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + 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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await ExpenseHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -1756,16 +1756,11 @@ namespace AyaNova.Biz if (HasErrors) return null; else - { - // await LaborBizActionsAsync(AyaEvent.Created, newObject, null, null); - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + { await ct.PMItemLabor.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await LaborSearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await LaborHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LaborPopulateVizFields(newObject); return newObject; @@ -1824,7 +1819,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LaborSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LaborHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LaborPopulateVizFields(putObject); return putObject; @@ -1848,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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - // await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await LaborHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2062,7 +2057,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -2156,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await LoanHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LoanPopulateVizFields(newObject); return newObject; @@ -2212,7 +2207,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LoanSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LoanHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LoanPopulateVizFields(putObject); return putObject; @@ -2236,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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await LoanHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2458,7 +2453,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -2552,12 +2547,12 @@ namespace AyaNova.Biz else { // newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + 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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await OutsideServicePopulateVizFields(newObject); return newObject; @@ -2595,8 +2590,8 @@ namespace AyaNova.Biz } - // dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await OutsideServiceValidateAsync(putObject, dbObject); if (HasErrors) return null; @@ -2615,7 +2610,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await OutsideServiceSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await OutsideServicePopulateVizFields(putObject); @@ -2640,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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2777,7 +2772,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -2875,8 +2870,8 @@ namespace AyaNova.Biz else { await PartBizActionsAsync(AyaEvent.Created, newObject, null, null); - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.PMItemPart.AddAsync(newObject); await ct.SaveChangesAsync(); if (HasErrors) @@ -2887,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await PartPopulateVizFields(newObject); return newObject; } @@ -2927,8 +2922,8 @@ namespace AyaNova.Biz return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await PartValidateAsync(putObject, dbObject); if (HasErrors) return null; @@ -2953,7 +2948,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await PartSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await PartHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await transaction.CommitAsync(); await PartPopulateVizFields(putObject); @@ -2985,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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await PartHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3237,7 +3232,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3325,13 +3320,13 @@ namespace AyaNova.Biz return null; else { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.PMItemScheduledUser.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); - //await ScheduledUserSearchIndexAsync(newObject, true); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ScheduledUserPopulateVizFields(newObject); return newObject; @@ -3368,8 +3363,8 @@ namespace AyaNova.Biz return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await ScheduledUserValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3386,8 +3381,8 @@ namespace AyaNova.Biz return null; } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); - // await ScheduledUserSearchIndexAsync(dbObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await ScheduledUserPopulateVizFields(putObject); return putObject; @@ -3411,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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3515,7 +3510,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3599,13 +3594,13 @@ namespace AyaNova.Biz return null; else { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + 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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await TaskHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await TaskPopulateVizFields(newObject); return newObject; @@ -3639,8 +3634,8 @@ namespace AyaNova.Biz AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await TaskValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3658,7 +3653,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TaskSearchIndexAsync(dbObject, false); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await TaskHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TaskPopulateVizFields(putObject); return putObject; @@ -3682,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); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await TaskHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3795,7 +3790,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3939,7 +3934,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TravelSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await TravelHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TravelPopulateVizFields(putObject); return putObject; @@ -3963,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); - // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await TravelHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -4163,7 +4158,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4246,8 +4241,8 @@ namespace AyaNova.Biz // internal async Task UnitCreateAsync(PMItemUnit newObject) { - //todo: contract stuff and validation of no other existing contracted unit - //assumptions: this create only gets called if there is an existing woheader saved in all cases + + await UnitValidateAsync(newObject, null); @@ -4255,7 +4250,7 @@ namespace AyaNova.Biz return null; else { - //await UnitBizActionsAsync(AyaEvent.Created, newObject, null, null); + newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.PMItemUnit.AddAsync(newObject); @@ -4385,42 +4380,6 @@ namespace AyaNova.Biz } - - - - // //////////////////////////////////////////////////////////////////////////////////////////////// - // //BIZ ACTIONS - // // - // // - // private async Task UnitBizActionsAsync(AyaEvent ayaEvent, PMItemUnit newObj, PMItemUnit oldObj, IDbContextTransaction transaction) - // { - // //automatic actions on record change, called AFTER validation - - // //currently no processing required except for created or modified at this time - // if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified) - // return; - - - // if (newOrChangedActiveUnitContract != null && (ayaEvent == AyaEvent.Modified || ayaEvent == AyaEvent.Created))//note: keeping this qualification defensively in case more biz actions added later - // { - // //set contract if applicable - // //Note: validation has already set neworchangeactiveunitcontract and only sets it if it's applicable - // //so in here we just need to apply that contract to the header - // //I've decided that it will attempt to set the header here now rather than after the unit has set - // //as it's more important to have the unit record be saved than to - - - // // //If it wasn't a complete part change there is no need to set pricing - // // if (newObj.LoanUnitId == oldObj.LoanUnitId && newObj.Rate == oldObj.Rate) - // // { - // // SnapshotPricing = false; - // // //maintain old cost as it can come from the client as zero when it shouldn't be or someone using the api and setting it directly - // // //but we will only allow the price *we* set at the server initially - // // newObj.Cost = oldObj.Cost; - // // } - // } - // } - //////////////////////////////////////////////////////////////////////////////////////////////// //VIZ POPULATE // @@ -4462,9 +4421,8 @@ namespace AyaNova.Biz //skip validation if seeding // if (ServerBootConfig.SEEDING) return; - // - A work order *MUST* have only one Unit with a Contract, if there is already a unit with a contract on this quote then a new one cannot be added and it will reject with a validation error - // a unit record is saved only *after* there is already a header (by api users and our client software) so can easily check and set here - + + //run validation and biz rules bool isNew = currentObj == null; @@ -5657,7 +5615,7 @@ namespace AyaNova.Biz } */ - #endregion gen service wo from pm + #endregion v7 code gen service wo from pm ///////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/biz/QuoteBiz.cs b/server/AyaNova/biz/QuoteBiz.cs index 8b30008e..d6876557 100644 --- a/server/AyaNova/biz/QuoteBiz.cs +++ b/server/AyaNova/biz/QuoteBiz.cs @@ -579,76 +579,10 @@ namespace AyaNova.Biz public void DigestSearchText(Quote obj, Search.SearchIndexProcessObjectParameters searchParams) { if (obj != null) - searchParams.AddText(obj.Notes).AddText(obj.Serial).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + searchParams.AddText(obj.Notes).AddText(obj.Introduction).AddText(obj.Serial).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); } - - - //////////////////////////////////////////////////////////////////////////////////////////////// - // "The Andy" notification helper - // - // (for now this is only for the notification exceeds total so only need one grand total of - // line totals, if in future need more can return a Record object instead with split out - // taxes, net etc etc) - // - private async Task WorkorderGrandTotalAsync(long workOrderId, AyContext ct) - { - var wo = await ct.Quote.AsNoTracking().AsSplitQuery() - .Include(w => w.Items.OrderBy(item => item.Sequence)) - .ThenInclude(wi => wi.Expenses) - .Include(w => w.Items) - .ThenInclude(wi => wi.Labors) - .Include(w => w.Items) - .ThenInclude(wi => wi.Loans) - .Include(w => w.Items) - .ThenInclude(wi => wi.Parts) - .Include(w => w.Items) - .ThenInclude(wi => wi.Travels) - .Include(w => w.Items) - .ThenInclude(wi => wi.OutsideServices) - .SingleOrDefaultAsync(z => z.Id == workOrderId); - if (wo == null) return 0m; - - decimal GrandTotal = 0m; - //update pricing - foreach (QuoteItem wi in wo.Items) - { - foreach (QuoteItemExpense o in wi.Expenses) - await ExpensePopulateVizFields(o, true); - foreach (QuoteItemLabor o in wi.Labors) - await LaborPopulateVizFields(o, true); - foreach (QuoteItemLoan o in wi.Loans) - await LoanPopulateVizFields(o, null, true); - foreach (QuoteItemPart o in wi.Parts) - await PartPopulateVizFields(o, true); - foreach (QuoteItemTravel o in wi.Travels) - await TravelPopulateVizFields(o, true); - foreach (QuoteItemOutsideService o in wi.OutsideServices) - await OutsideServicePopulateVizFields(o, true); - } - - foreach (QuoteItem wi in wo.Items) - { - foreach (QuoteItemExpense o in wi.Expenses) - GrandTotal += o.LineTotalViz; - foreach (QuoteItemLabor o in wi.Labors) - GrandTotal += o.LineTotalViz; - foreach (QuoteItemLoan o in wi.Loans) - GrandTotal += o.LineTotalViz; - foreach (QuoteItemPart o in wi.Parts) - GrandTotal += o.LineTotalViz; - foreach (QuoteItemTravel o in wi.Travels) - GrandTotal += o.LineTotalViz; - foreach (QuoteItemOutsideService o in wi.OutsideServices) - GrandTotal += o.LineTotalViz; - } - - return GrandTotal; - } - - - //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -903,8 +837,6 @@ namespace AyaNova.Biz else o.ContractViz = "-"; - - } @@ -918,32 +850,7 @@ namespace AyaNova.Biz //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time return await GetReportData(dataListSelectedRequest); } - - // public async Task> ImportData(JArray ja) - // { - // List ImportResult = new List(); - // string ImportTag = $"imported-{FileUtil.GetSafeDateFileName()}"; - - // var jsset = JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = new AyaNova.Util.JsonUtil.ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "CustomFields" }) }); - // foreach (JObject j in ja) - // { - // var w = j.ToObject(jsset); - // if (j["CustomFields"] != null) - // w.CustomFields = j["CustomFields"].ToString(); - // w.Tags.Add(ImportTag);//so user can find them all and revert later if necessary - // var res = await QuoteCreateAsync(w); - // if (res == null) - // { - // ImportResult.Add($"* {w.Serial} - {this.GetErrorsAsString()}"); - // this.ClearErrors(); - // } - // else - // { - // ImportResult.Add($"{w.Serial} - ok"); - // } - // } - // return ImportResult; - // } + //////////////////////////////////////////////////////////////////////////////////////////////// //JOB / OPERATIONS @@ -1037,24 +944,19 @@ namespace AyaNova.Biz bool isNew = currentObj == null; Quote oProposed = (Quote)proposedObj; - + //STANDARD EVENTS FOR ALL OBJECTS await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct);//Note: will properly handle all delete events and event removal if deleted //SPECIFIC EVENTS FOR THIS OBJECT - - }//end of process notifications - #endregion quote level - - /* ███████╗████████╗ █████╗ ████████╗███████╗███████╗ @@ -1088,20 +990,14 @@ namespace AyaNova.Biz await ct.QuoteState.AddAsync(newObject); var qoute = await ct.Quote.FirstOrDefaultAsync(x => x.Id == newObject.QuoteId); var newStatusInfo = await ct.QuoteStatus.AsNoTracking().FirstOrDefaultAsync(x => x.Id == newObject.QuoteStatusId); - - - qoute.LastStatusId = newObject.QuoteStatusId; - await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.QuoteStatus, AyaEvent.Created), ct); await StateHandlePotentialNotificationEvent(AyaEvent.Created, newObject); return newObject; } } - //////////////////////////////////////////////////////////////////////////////////////////////// // GET // @@ -1118,17 +1014,12 @@ namespace AyaNova.Biz return ret; } - - //////////////////////////////////////////////////////////////////////////////////////////////// //VIZ POPULATE // private async Task StatePopulateVizFields(QuoteState o) { - o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync(); - // if (o.QuoteOverseerId != null) - // o.QuoteOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.QuoteOverseerId).Select(x => x.Name).FirstOrDefaultAsync(); } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -1316,7 +1207,7 @@ namespace AyaNova.Biz // }//quote complete by overdue change event - + // //# WorkorderCompleted - Customer AND User but customer only notifies if it's their quote // { @@ -1492,8 +1383,6 @@ namespace AyaNova.Biz if (HasErrors) return null; ct.Replace(dbObject, putObject); - - try { await ct.SaveChangesAsync(); @@ -1643,7 +1532,6 @@ namespace AyaNova.Biz foreach (var v in o.Units) await UnitPopulateVizFields(v, populateForReporting); - } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -1657,9 +1545,9 @@ namespace AyaNova.Biz //does it have a valid quote id if (proposedObj.QuoteId == 0) AddError(ApiErrorCode.VALIDATION_REQUIRED, "QuoteId"); - else if (!await QuoteExistsAsync(proposedObj.QuoteId)) + else if (!await QuoteExistsAsync(proposedObj.QuoteId)) AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "QuoteId"); - + //Check restricted role preventing create if (isNew && UserIsRestrictedType) { @@ -1713,7 +1601,6 @@ namespace AyaNova.Biz return;//this is a completely disqualifying error } - //re-check rights here necessary due to traversal delete from Principle object if (!Authorized.HasDeleteRole(CurrentUserRoles, AyaType.QuoteItem)) { @@ -1749,12 +1636,9 @@ namespace AyaNova.Biz //SPECIFIC EVENTS FOR THIS OBJECT - - }//end of process notifications - #endregion work order item level @@ -1789,7 +1673,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await ExpenseHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ExpensePopulateVizFields(newObject); return newObject; @@ -1871,8 +1755,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await ExpenseHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2155,16 +2039,15 @@ namespace AyaNova.Biz if (HasErrors) return null; else - { - // await LaborBizActionsAsync(AyaEvent.Created, newObject, null, null); - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + { + + await ct.QuoteItemLabor.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await LaborSearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await LaborHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LaborPopulateVizFields(newObject); return newObject; @@ -2223,7 +2106,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LaborSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LaborHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LaborPopulateVizFields(putObject); return putObject; @@ -2247,8 +2130,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - // await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await LaborHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2474,7 +2357,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -2565,7 +2448,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await LoanHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LoanPopulateVizFields(newObject); return newObject; @@ -2621,7 +2504,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LoanSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LoanHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LoanPopulateVizFields(putObject); return putObject; @@ -2645,8 +2528,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await LoanHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2878,7 +2761,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -2972,12 +2855,12 @@ namespace AyaNova.Biz else { // newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + await ct.QuoteItemOutsideService.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await OutsideServiceSearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await OutsideServicePopulateVizFields(newObject); return newObject; @@ -3014,10 +2897,6 @@ namespace AyaNova.Biz return null; } - - // dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); - await OutsideServiceValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3035,7 +2914,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await OutsideServiceSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await OutsideServicePopulateVizFields(putObject); @@ -3060,8 +2939,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3208,7 +3087,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3301,8 +3180,8 @@ namespace AyaNova.Biz else { await PartBizActionsAsync(AyaEvent.Created, newObject, null, null); - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.QuoteItemPart.AddAsync(newObject); await ct.SaveChangesAsync(); if (HasErrors) @@ -3313,7 +3192,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await PartPopulateVizFields(newObject); return newObject; } @@ -3353,8 +3232,8 @@ namespace AyaNova.Biz return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await PartValidateAsync(putObject, dbObject); if (HasErrors) return null; @@ -3379,7 +3258,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await PartSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await PartHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await transaction.CommitAsync(); await PartPopulateVizFields(putObject); @@ -3411,8 +3290,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await PartHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3678,7 +3557,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3766,13 +3645,13 @@ namespace AyaNova.Biz return null; else { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.QuoteItemScheduledUser.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); - //await ScheduledUserSearchIndexAsync(newObject, true); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ScheduledUserPopulateVizFields(newObject); return newObject; @@ -3809,8 +3688,8 @@ namespace AyaNova.Biz return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await ScheduledUserValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3827,8 +3706,8 @@ namespace AyaNova.Biz return null; } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); - // await ScheduledUserSearchIndexAsync(dbObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await ScheduledUserPopulateVizFields(putObject); return putObject; @@ -3852,8 +3731,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3935,27 +3814,28 @@ namespace AyaNova.Biz if (proposedObj.StartDate > proposedObj.StopDate) AddError(ApiErrorCode.VALIDATION_STARTDATE_AFTER_ENDDATE, "StartDate"); - //Scheduling conflict? - if (!AyaNova.Util.ServerGlobalBizSettings.Cache.AllowScheduleConflicts - && proposedObj.UserId != null - && proposedObj.StartDate != null - && proposedObj.StopDate != null - && (isNew - || (proposedObj.StartDate != currentObj.StartDate) - || (proposedObj.StopDate != currentObj.StopDate) - || (proposedObj.UserId != currentObj.UserId) - )) - { - if (await ct.QuoteItemScheduledUser.AnyAsync(x => x.Id != proposedObj.Id - && x.UserId == proposedObj.UserId - && x.StartDate <= proposedObj.StopDate - && proposedObj.StartDate <= x.StopDate)) - { - AddError(ApiErrorCode.VALIDATION_FAILED, "StartDate", await Translate("ScheduleConflict")); - AddError(ApiErrorCode.VALIDATION_FAILED, "StopDate", await Translate("ScheduleConflict")); - } + //For now decision is to not check for sched conflicts on pm as it's not a work order yet anyway + // //Scheduling conflict? + // if (!AyaNova.Util.ServerGlobalBizSettings.Cache.AllowScheduleConflicts + // && proposedObj.UserId != null + // && proposedObj.StartDate != null + // && proposedObj.StopDate != null + // && (isNew + // || (proposedObj.StartDate != currentObj.StartDate) + // || (proposedObj.StopDate != currentObj.StopDate) + // || (proposedObj.UserId != currentObj.UserId) + // )) + // { + // if (await ct.QuoteItemScheduledUser.AnyAsync(x => x.Id != proposedObj.Id + // && x.UserId == proposedObj.UserId + // && x.StartDate <= proposedObj.StopDate + // && proposedObj.StartDate <= x.StopDate)) + // { + // AddError(ApiErrorCode.VALIDATION_FAILED, "StartDate", await Translate("ScheduleConflict")); + // AddError(ApiErrorCode.VALIDATION_FAILED, "StopDate", await Translate("ScheduleConflict")); + // } - } + // } //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.QuoteItemScheduledUser.ToString()); @@ -3967,7 +3847,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4051,14 +3931,13 @@ namespace AyaNova.Biz if (HasErrors) return null; else - { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + { + await ct.QuoteItemTask.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await TaskSearchIndexAsync(newObject, true); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await TaskHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await TaskPopulateVizFields(newObject); return newObject; @@ -4092,8 +3971,8 @@ namespace AyaNova.Biz AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await TaskValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -4111,7 +3990,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TaskSearchIndexAsync(dbObject, false); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await TaskHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TaskPopulateVizFields(putObject); return putObject; @@ -4135,8 +4014,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await TaskHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -4259,7 +4138,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4403,7 +4282,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TravelSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await TravelHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TravelPopulateVizFields(putObject); return putObject; @@ -4427,8 +4306,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.QuoteItemId.ToString(), ct); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await TravelHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -4639,7 +4518,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4722,16 +4601,11 @@ namespace AyaNova.Biz // internal async Task UnitCreateAsync(QuoteItemUnit newObject) { - //todo: contract stuff and validation of no other existing contracted unit - //assumptions: this create only gets called if there is an existing woheader saved in all cases - - await UnitValidateAsync(newObject, null); if (HasErrors) return null; else - { - //await UnitBizActionsAsync(AyaEvent.Created, newObject, null, null); + { newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.QuoteItemUnit.AddAsync(newObject); @@ -4741,7 +4615,6 @@ namespace AyaNova.Biz await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await UnitHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await UnitPopulateVizFields(newObject, false); - return newObject; } } @@ -4861,42 +4734,6 @@ namespace AyaNova.Biz } - - - - // //////////////////////////////////////////////////////////////////////////////////////////////// - // //BIZ ACTIONS - // // - // // - // private async Task UnitBizActionsAsync(AyaEvent ayaEvent, QuoteItemUnit newObj, QuoteItemUnit oldObj, IDbContextTransaction transaction) - // { - // //automatic actions on record change, called AFTER validation - - // //currently no processing required except for created or modified at this time - // if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified) - // return; - - - // if (newOrChangedActiveUnitContract != null && (ayaEvent == AyaEvent.Modified || ayaEvent == AyaEvent.Created))//note: keeping this qualification defensively in case more biz actions added later - // { - // //set contract if applicable - // //Note: validation has already set neworchangeactiveunitcontract and only sets it if it's applicable - // //so in here we just need to apply that contract to the header - // //I've decided that it will attempt to set the header here now rather than after the unit has set - // //as it's more important to have the unit record be saved than to - - - // // //If it wasn't a complete part change there is no need to set pricing - // // if (newObj.LoanUnitId == oldObj.LoanUnitId && newObj.Rate == oldObj.Rate) - // // { - // // SnapshotPricing = false; - // // //maintain old cost as it can come from the client as zero when it shouldn't be or someone using the api and setting it directly - // // //but we will only allow the price *we* set at the server initially - // // newObj.Cost = oldObj.Cost; - // // } - // } - // } - //////////////////////////////////////////////////////////////////////////////////////////////// //VIZ POPULATE // @@ -4937,10 +4774,7 @@ namespace AyaNova.Biz { //skip validation if seeding // if (ServerBootConfig.SEEDING) return; - - // - A work order *MUST* have only one Unit with a Contract, if there is already a unit with a contract on this quote then a new one cannot be added and it will reject with a validation error - // a unit record is saved only *after* there is already a header (by api users and our client software) so can easily check and set here - + //run validation and biz rules bool isNew = currentObj == null; @@ -4977,64 +4811,6 @@ namespace AyaNova.Biz if (proposedObj.UnitId < 1 || !await ct.Unit.AnyAsync(x => x.Id == proposedObj.UnitId)) AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "UnitId"); - // //Contracted unit? Only one per work order is allowed - // if (isNew || proposedObj.UnitId != currentObj.UnitId) - // { - // bool AlreadyHasAContractedUnit = false; - // //See if this unit has a contract, if so then see if the contract is active, if so then iterate quote graph and check all other units for same - // //if any found then reject this - // var proposedUnitInfo = await ct.Unit.AsNoTracking().Where(x => x.Id == proposedObj.UnitId).Select(x => new { x.ContractExpires, x.ContractId }).FirstOrDefaultAsync(); - // if (proposedUnitInfo.ContractId != null && proposedUnitInfo.ContractExpires > DateTime.UtcNow) - // { - // //added woitemunit has a contract and apparently unexpired so need to check if contract is still active - // newOrChangedActiveUnitContractId = proposedUnitInfo.ContractId; - // if (await ct.Contract.AsNoTracking().Where(z => z.Id == proposedUnitInfo.ContractId).Select(x => x.Active).FirstOrDefaultAsync() == true) - // { - // //iterate work order and check for other contracted unit - // var woId = await GetQuoteIdFromRelativeAsync(AyaType.QuoteItem, proposedObj.QuoteItemId, ct); - // newOrChangedActiveUnitQuoteId = woId.QuoteId;//save for later contract update if necessary - // var w = await QuoteGetFullAsync(woId.QuoteId); - - // //iterate, look for *other* woitemunit records, are they contracted already? - // foreach (QuoteItem wi in w.Items) - // { - // if (AlreadyHasAContractedUnit) continue; - // foreach (QuoteItemUnit wiu in wi.Units) - // { - // if (isNew || wiu.Id != currentObj.Id) - // { - // var existingUnitInfo = await ct.Unit.AsNoTracking().Where(x => x.Id == wiu.UnitId).Select(x => new { x.ContractExpires, x.ContractId }).FirstOrDefaultAsync(); - // if (existingUnitInfo != null) - // { - // if (existingUnitInfo.ContractId != null && existingUnitInfo.ContractExpires > DateTime.UtcNow) - // { - // //Ok, we have a pre-existing contract, is it active? - // if (await ct.Contract.AsNoTracking().Where(x => x.Id == existingUnitInfo.ContractId).Select(x => x.Active).FirstOrDefaultAsync()) - // { - // AlreadyHasAContractedUnit = true; - // continue; - // } - // } - // } - // } - // } - // } - // if (AlreadyHasAContractedUnit) - // { - // AddError(ApiErrorCode.VALIDATION_WO_MULTIPLE_CONTRACTED_UNITS, "UnitId"); - // return;//this is a completely disqualifying error - // } - // } - // else - // { - // newOrChangedActiveUnitContractId = null;//just in case it's non active but present so later biz actions don't process it - // } - // } - // } - - - - //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.QuoteItemUnit.ToString()); if (FormCustomization != null) @@ -5284,27 +5060,6 @@ namespace AyaNova.Biz return mCurrentQuoteStatus; } - // internal static async Task GetCurrentQuoteStatusFromRelatedAsync(AyaType ayaType, long id, AyContext ct) - // { - // //static method - // var wid = await GetQuoteIdFromRelativeAsync(ayaType, id, ct); - // var stat = await ct.QuoteState.AsNoTracking() - // .Where(z => z.QuoteId == wid.ParentId) - // .OrderByDescending(z => z.Created) - // .Take(1) - // .FirstOrDefaultAsync(); - - - // //no state set yet? - // if (stat == null) - // { //default - // return new QuoteStatus() { Id = -1, Locked = false, Completed = false }; - // } - // return await ct.QuoteStatus.AsNoTracking().Where(z => z.Id == stat.QuoteStatusId).FirstAsync();//this should never not be null - - // } - - #endregion utility diff --git a/server/AyaNova/biz/TranslationBiz.cs b/server/AyaNova/biz/TranslationBiz.cs index b041d9e2..7b4ede95 100644 --- a/server/AyaNova/biz/TranslationBiz.cs +++ b/server/AyaNova/biz/TranslationBiz.cs @@ -188,7 +188,7 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); // await SearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + return newObject; } diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index e161c5eb..9ebd77bf 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -2369,7 +2369,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await ExpenseHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ExpensePopulateVizFields(newObject); return newObject; @@ -2451,8 +2451,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await ExpenseHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -2732,15 +2732,13 @@ namespace AyaNova.Biz return null; else { - // await LaborBizActionsAsync(AyaEvent.Created, newObject, null, null); - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + await ct.WorkOrderItemLabor.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await LaborSearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await LaborHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LaborPopulateVizFields(newObject); return newObject; @@ -2799,7 +2797,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LaborSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LaborHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LaborPopulateVizFields(putObject); return putObject; @@ -2823,8 +2821,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - // await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await LaborHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3050,7 +3048,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3141,7 +3139,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await LoanHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await LoanPopulateVizFields(newObject); return newObject; @@ -3197,7 +3195,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await LoanSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LoanHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await LoanPopulateVizFields(putObject); return putObject; @@ -3221,8 +3219,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await LoanHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3454,7 +3452,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -3548,12 +3546,12 @@ namespace AyaNova.Biz else { // newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + await ct.WorkOrderItemOutsideService.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await OutsideServiceSearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await OutsideServicePopulateVizFields(newObject); return newObject; @@ -3590,10 +3588,6 @@ namespace AyaNova.Biz return null; } - - // dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); - await OutsideServiceValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -3611,7 +3605,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await OutsideServiceSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await OutsideServicePopulateVizFields(putObject); @@ -3636,8 +3630,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await OutsideServiceHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -3784,7 +3778,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4023,8 +4017,8 @@ namespace AyaNova.Biz else { await PartBizActionsAsync(AyaEvent.Created, newObject, null, null); - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.WorkOrderItemPart.AddAsync(newObject); await ct.SaveChangesAsync(); await PartInventoryAdjustmentAsync(AyaEvent.Created, newObject, null, transaction); @@ -4036,7 +4030,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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await PartPopulateVizFields(newObject); return newObject; } @@ -4076,8 +4070,8 @@ namespace AyaNova.Biz return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await PartValidateAsync(putObject, dbObject); if (HasErrors) return null; @@ -4103,7 +4097,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await PartSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await PartHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await transaction.CommitAsync(); await PartPopulateVizFields(putObject); @@ -4136,8 +4130,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await PartHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -4548,7 +4542,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4635,13 +4629,13 @@ namespace AyaNova.Biz return null; else { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.WorkOrderItemPartRequest.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); //await PartRequestSearchIndexAsync(newObject, true); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await PartRequestHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await PartRequestPopulateVizFields(newObject); return newObject; @@ -4677,8 +4671,8 @@ namespace AyaNova.Biz AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - // dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await PartRequestValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -4695,8 +4689,8 @@ namespace AyaNova.Biz return null; } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); - // await PartRequestSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + + await PartRequestHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await PartRequestPopulateVizFields(putObject); return putObject; @@ -4720,8 +4714,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await PartRequestHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -4825,7 +4819,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -4911,13 +4905,13 @@ namespace AyaNova.Biz return null; else { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.WorkOrderItemScheduledUser.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); - //await ScheduledUserSearchIndexAsync(newObject, true); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await ScheduledUserPopulateVizFields(newObject); return newObject; @@ -4954,8 +4948,8 @@ namespace AyaNova.Biz return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await ScheduledUserValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -4972,8 +4966,8 @@ namespace AyaNova.Biz return null; } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); - // await ScheduledUserSearchIndexAsync(dbObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await ScheduledUserPopulateVizFields(putObject); return putObject; @@ -4997,8 +4991,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -5112,7 +5106,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -5312,13 +5306,13 @@ namespace AyaNova.Biz return null; else { - //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); - //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + + await ct.WorkOrderItemTask.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await TaskSearchIndexAsync(newObject, true); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await TaskHandlePotentialNotificationEvent(AyaEvent.Created, newObject); await TaskPopulateVizFields(newObject); return newObject; @@ -5352,8 +5346,8 @@ namespace AyaNova.Biz AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); - //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + await TaskValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); @@ -5371,7 +5365,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TaskSearchIndexAsync(dbObject, false); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await TaskHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TaskPopulateVizFields(putObject); return putObject; @@ -5395,8 +5389,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await TaskHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -5519,7 +5513,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -5663,7 +5657,7 @@ namespace AyaNova.Biz } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TravelSearchIndexAsync(putObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + await TravelHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); await TravelPopulateVizFields(putObject); return putObject; @@ -5687,8 +5681,8 @@ namespace AyaNova.Biz //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); - // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + + if (parentTransaction == null) await transaction.CommitAsync(); await TravelHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); @@ -5899,7 +5893,7 @@ namespace AyaNova.Biz RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields - //CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } } @@ -5982,8 +5976,8 @@ namespace AyaNova.Biz // internal async Task UnitCreateAsync(WorkOrderItemUnit newObject) { - //todo: contract stuff and validation of no other existing contracted unit - //assumptions: this create only gets called if there is an existing woheader saved in all cases + + await UnitValidateAsync(newObject, null); @@ -5991,7 +5985,7 @@ namespace AyaNova.Biz return null; else { - //await UnitBizActionsAsync(AyaEvent.Created, newObject, null, null); + newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemUnit.AddAsync(newObject); @@ -6199,8 +6193,7 @@ namespace AyaNova.Biz // if (ServerBootConfig.SEEDING) return; // - A work order *MUST* have only one Unit with a Contract, if there is already a unit with a contract on this workorder then a new one cannot be added and it will reject with a validation error - // a unit record is saved only *after* there is already a header (by api users and our client software) so can easily check and set here - + //run validation and biz rules bool isNew = currentObj == null; @@ -6237,64 +6230,6 @@ namespace AyaNova.Biz if (proposedObj.UnitId < 1 || !await ct.Unit.AnyAsync(x => x.Id == proposedObj.UnitId)) AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "UnitId"); - // //Contracted unit? Only one per work order is allowed - // if (isNew || proposedObj.UnitId != currentObj.UnitId) - // { - // bool AlreadyHasAContractedUnit = false; - // //See if this unit has a contract, if so then see if the contract is active, if so then iterate workorder graph and check all other units for same - // //if any found then reject this - // var proposedUnitInfo = await ct.Unit.AsNoTracking().Where(x => x.Id == proposedObj.UnitId).Select(x => new { x.ContractExpires, x.ContractId }).FirstOrDefaultAsync(); - // if (proposedUnitInfo.ContractId != null && proposedUnitInfo.ContractExpires > DateTime.UtcNow) - // { - // //added woitemunit has a contract and apparently unexpired so need to check if contract is still active - // newOrChangedActiveUnitContractId = proposedUnitInfo.ContractId; - // if (await ct.Contract.AsNoTracking().Where(z => z.Id == proposedUnitInfo.ContractId).Select(x => x.Active).FirstOrDefaultAsync() == true) - // { - // //iterate work order and check for other contracted unit - // var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, proposedObj.WorkOrderItemId, ct); - // newOrChangedActiveUnitWorkOrderId = woId.WorkOrderId;//save for later contract update if necessary - // var w = await WorkOrderGetFullAsync(woId.WorkOrderId); - - // //iterate, look for *other* woitemunit records, are they contracted already? - // foreach (WorkOrderItem wi in w.Items) - // { - // if (AlreadyHasAContractedUnit) continue; - // foreach (WorkOrderItemUnit wiu in wi.Units) - // { - // if (isNew || wiu.Id != currentObj.Id) - // { - // var existingUnitInfo = await ct.Unit.AsNoTracking().Where(x => x.Id == wiu.UnitId).Select(x => new { x.ContractExpires, x.ContractId }).FirstOrDefaultAsync(); - // if (existingUnitInfo != null) - // { - // if (existingUnitInfo.ContractId != null && existingUnitInfo.ContractExpires > DateTime.UtcNow) - // { - // //Ok, we have a pre-existing contract, is it active? - // if (await ct.Contract.AsNoTracking().Where(x => x.Id == existingUnitInfo.ContractId).Select(x => x.Active).FirstOrDefaultAsync()) - // { - // AlreadyHasAContractedUnit = true; - // continue; - // } - // } - // } - // } - // } - // } - // if (AlreadyHasAContractedUnit) - // { - // AddError(ApiErrorCode.VALIDATION_WO_MULTIPLE_CONTRACTED_UNITS, "UnitId"); - // return;//this is a completely disqualifying error - // } - // } - // else - // { - // newOrChangedActiveUnitContractId = null;//just in case it's non active but present so later biz actions don't process it - // } - // } - // } - - - - //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderItemUnit.ToString()); if (FormCustomization != null)