diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index d0d3b9fe..693b4fe4 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -73,6 +73,7 @@ namespace AyaNova.Biz return null; else { + // await WorkOrderBizActionsAsync(AyaEvent.Created, newObject, null, null); newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrder.AddAsync(newObject); @@ -193,6 +194,11 @@ namespace AyaNova.Biz // internal async Task WorkOrderPutAsync(WorkOrder putObject) { + + //todo: bizactions, contract change update pricing entire workorder and return it entirely? + //no client must fetch it, just return concurrency as per normal here + + //Note: this is intentionally not using the getasync because //doing so would invoke the children which would then get deleted on save since putobject has no children WorkOrder dbObject = await ct.WorkOrder.AsNoTracking().FirstOrDefaultAsync(z => z.Id == putObject.Id); @@ -206,14 +212,20 @@ namespace AyaNova.Biz AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - - + bool contractChanged = false; + long? newContractId = null; + if (putObject.ContractId != dbObject.ContractId) + { + contractChanged = true; + newContractId = putObject.ContractId; + } putObject.Tags = TagBiz.NormalizeTags(putObject.Tags); putObject.CustomFields = JsonUtil.CompactJson(putObject.CustomFields); await WorkOrderValidateAsync(putObject, dbObject); if (HasErrors) return null; + // await WorkOrderBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null); ct.Replace(dbObject, putObject); try { @@ -230,6 +242,14 @@ namespace AyaNova.Biz await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); await WorkOrderSearchIndexAsync(putObject, false); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + if (contractChanged) + { + + if (newContractId != null) + mContractInEffect = await ct.Contract.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newContractId); + mFetchedContractAlready = true; + await ProcessChangeOfContractAsync(putObject.Id); + } await WorkOrderHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); return putObject; } @@ -373,6 +393,32 @@ namespace AyaNova.Biz } + + //////////////////////////////////////////////////////////////////////////////////////////////// + //CONTRACT CHANGE HANDLER + // + // + private async Task ProcessChangeOfContractAsync(long woId) + { + //contract has changed, update entire graph pricing and potentially response time stuff as well here now + //iterate graph calling *SetListPrice on each item + var wo = await WorkOrderGetAsync(woId, false, false); + foreach (WorkOrderItem wi in wo.Items) + { + foreach (WorkOrderItemLabor o in wi.Labors) + LaborSetListPrice(o, mContractInEffect); + foreach (WorkOrderItemTravel o in wi.Travels) + TravelSetListPrice(o, mContractInEffect); + foreach (WorkOrderItemPart o in wi.Parts) + PartSetListPrice(o, mContractInEffect); + + } + + + } + + + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -1789,20 +1835,23 @@ namespace AyaNova.Biz newObj.Cost = s.Cost; newObj.ListPrice = s.Charge; var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId); - LaborApplyContract(newObj, Contract); + LaborSetListPrice(newObj, Contract); } } } } //////////////////////////////////////////////////////////////////////////////////////////////// - // APPLY CONTRACT PER UNIT PRICING + // SET PER UNIT LIST PRICE // //(called by woitemlabor save and also by header save on change of contract) - private static void LaborApplyContract(WorkOrderItemLabor o, Contract c) + private static void LaborSetListPrice(WorkOrderItemLabor o, Contract c) { if (c == null || c.ServiceRatesOverridePct == 0) + { + o.Price = o.ListPrice;//default with no contract return; + } if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup) o.Price = o.Cost + (o.Cost * c.ServiceRatesOverridePct); else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount) @@ -2608,6 +2657,26 @@ namespace AyaNova.Biz // o.WorkOrderOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.WorkOrderOverseerId).Select(x => x.Name).FirstOrDefaultAsync(); } + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // SET PER UNIT LIST PRICE + // + //(called by woitempart save and also by header save on change of contract) + private static void PartSetListPrice(WorkOrderItemPart o, Contract c) + { + if (c == null || c.ServiceRatesOverridePct == 0) + { + o.Price = o.ListPrice;//default with no contract + return; + } + if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup) + o.Price = o.Cost + (o.Cost * c.ServiceRatesOverridePct); + else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount) + o.Price = o.ListPrice - (o.ListPrice * c.ServiceRatesOverridePct); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -2709,6 +2778,8 @@ namespace AyaNova.Biz + + #endregion work order item PARTS level @@ -3628,6 +3699,26 @@ namespace AyaNova.Biz // o.WorkOrderOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.WorkOrderOverseerId).Select(x => x.Name).FirstOrDefaultAsync(); } + + //////////////////////////////////////////////////////////////////////////////////////////////// + // SET PER UNIT LIST PRICE + // + //(called by woitemtravel save and also by header save on change of contract) + private static void TravelSetListPrice(WorkOrderItemTravel o, Contract c) + { + if (c == null || c.ServiceRatesOverridePct == 0) + { + o.Price = o.ListPrice;//default with no contract + return; + } + if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup) + o.Price = o.Cost + (o.Cost * c.ServiceRatesOverridePct); + else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount) + o.Price = o.ListPrice - (o.ListPrice * c.ServiceRatesOverridePct); + } + + + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION //