This commit is contained in:
@@ -2962,7 +2962,7 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
await PartValidateAsync(putObject, dbObject);
|
await PartValidateAsync(putObject, dbObject);
|
||||||
if (HasErrors) return null;
|
if (HasErrors) return null;
|
||||||
// await PartBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
|
// await PartBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
|
||||||
ct.Replace(dbObject, putObject);
|
ct.Replace(dbObject, putObject);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -3044,7 +3044,7 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
private async Task PartPopulateVizFields(WorkOrderItemPart o)
|
private async Task PartPopulateVizFields(WorkOrderItemPart o)
|
||||||
{
|
{
|
||||||
if (o.PartWarehouseId != 0)
|
if (o.PartWarehouseId != 0)
|
||||||
o.PartWarehouseViz = await ct.PartWarehouse.AsNoTracking().Where(x => x.Id == o.PartWarehouseId).Select(x => x.Name).FirstOrDefaultAsync();
|
o.PartWarehouseViz = await ct.PartWarehouse.AsNoTracking().Where(x => x.Id == o.PartWarehouseId).Select(x => x.Name).FirstOrDefaultAsync();
|
||||||
Part part = null;
|
Part part = null;
|
||||||
if (o.PartId != 0)
|
if (o.PartId != 0)
|
||||||
@@ -4117,7 +4117,7 @@ namespace AyaNova.Biz
|
|||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await TravelBizActionsAsync(AyaEvent.Created, newObject, null, null);
|
//await TravelBizActionsAsync(AyaEvent.Created, newObject, null, null);
|
||||||
//newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
//newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
||||||
//newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
//newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
||||||
await ct.WorkOrderItemTravel.AddAsync(newObject);
|
await ct.WorkOrderItemTravel.AddAsync(newObject);
|
||||||
@@ -4163,7 +4163,7 @@ namespace AyaNova.Biz
|
|||||||
// dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
|
// dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
|
||||||
await TravelValidateAsync(putObject, dbObject);
|
await TravelValidateAsync(putObject, dbObject);
|
||||||
if (HasErrors) return null;
|
if (HasErrors) return null;
|
||||||
await TravelBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
|
// await TravelBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
|
||||||
ct.Replace(dbObject, putObject);
|
ct.Replace(dbObject, putObject);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -4248,103 +4248,195 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
private async Task TravelPopulateVizFields(WorkOrderItemTravel o)
|
private async Task TravelPopulateVizFields(WorkOrderItemTravel o)
|
||||||
{
|
{
|
||||||
await Task.CompletedTask;
|
if (o.UserId != null)
|
||||||
// if (o.WorkOrderOverseerId != null)
|
o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync();
|
||||||
// o.WorkOrderOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.WorkOrderOverseerId).Select(x => x.Name).FirstOrDefaultAsync();
|
TravelRate Rate = null;
|
||||||
}
|
if (o.TravelRateId != null)
|
||||||
|
Rate = await ct.TravelRate.AsNoTracking().FirstOrDefaultAsync(x => x.Id == o.TravelRateId);
|
||||||
|
TaxCode Tax = null;
|
||||||
|
if (o.TaxCodeSaleId != null)
|
||||||
|
Tax = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == o.TaxCodeSaleId);
|
||||||
|
if (Tax != null)
|
||||||
|
o.TaxCodeSaleViz = Tax.Name;
|
||||||
|
|
||||||
|
o.PriceViz = 0;
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
if (Rate != null)
|
||||||
//BIZ ACTIONS
|
|
||||||
//
|
|
||||||
//
|
|
||||||
private async Task TravelBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemTravel newObj, WorkOrderItemTravel 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;
|
|
||||||
|
|
||||||
//SET TAXES AND PRICING
|
|
||||||
|
|
||||||
//by default apply all automatic actions with further restrictions possible below
|
|
||||||
bool ApplyTax = true;
|
|
||||||
bool ApplyPricingUpdate = true;
|
|
||||||
|
|
||||||
//if modifed, see what has changed and should be re-applied
|
|
||||||
if (ayaEvent == AyaEvent.Modified)
|
|
||||||
{
|
{
|
||||||
//If it wasn't a service rate change there is no need to set pricing
|
o.CostViz = Rate.Cost;
|
||||||
if (newObj.TravelRateId == oldObj.TravelRateId)
|
o.ListPriceViz = Rate.Charge;
|
||||||
{
|
o.UnitOfMeasureViz = Rate.Unit;
|
||||||
ApplyPricingUpdate = false;
|
o.PriceViz = Rate.Charge;//default price used if not manual or contract override
|
||||||
}
|
|
||||||
//If taxes haven't change then no need to update taxes
|
|
||||||
if (newObj.TaxCodeSaleId == oldObj.TaxCodeSaleId)
|
|
||||||
ApplyTax = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Tax code
|
//manual price overrides anything
|
||||||
if (ApplyTax)
|
if (o.PriceOverride != null)
|
||||||
|
o.PriceViz = (decimal)o.PriceOverride;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//Default in case nothing to apply
|
//not manual so could potentially have a contract adjustment
|
||||||
newObj.TaxAPct = 0;
|
var c = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, o.WorkOrderItemId);
|
||||||
newObj.TaxBPct = 0;
|
if (c != null)
|
||||||
newObj.TaxOnTax = false;
|
|
||||||
|
|
||||||
if (newObj.TaxCodeSaleId != null)
|
|
||||||
{
|
{
|
||||||
var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TaxCodeSaleId);
|
decimal pct = 0;
|
||||||
if (t != null)
|
ContractOverrideType cot = ContractOverrideType.PriceDiscount;
|
||||||
|
|
||||||
|
bool TaggedAdjustmentInEffect = false;
|
||||||
|
|
||||||
|
//POTENTIAL CONTRACT ADJUSTMENTS
|
||||||
|
//First check if there is a matching tagged Travel rate contract discount, that takes precedence
|
||||||
|
if (c.ContractTravelRateOverrideItems.Count > 0)
|
||||||
{
|
{
|
||||||
newObj.TaxAPct = t.TaxAPct;
|
//Iterate all contract tagged items in order of ones with the most tags first
|
||||||
newObj.TaxBPct = t.TaxBPct;
|
foreach (var csr in c.ContractTravelRateOverrideItems.OrderByDescending(z => z.Tags.Count))
|
||||||
newObj.TaxOnTax = t.TaxOnTax;
|
if (csr.Tags.All(z => Rate.Tags.Any(x => x == z)))
|
||||||
|
{
|
||||||
|
if (csr.OverridePct != 0)
|
||||||
|
{
|
||||||
|
pct = csr.OverridePct / 100;
|
||||||
|
cot = csr.OverrideType;
|
||||||
|
TaggedAdjustmentInEffect = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generic discount?
|
||||||
|
if (!TaggedAdjustmentInEffect && c.TravelRatesOverridePct != 0)
|
||||||
|
{
|
||||||
|
pct = c.TravelRatesOverridePct / 100;
|
||||||
|
cot = c.TravelRatesOverrideType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//apply if discount found
|
||||||
|
if (pct != 0)
|
||||||
|
{
|
||||||
|
if (cot == ContractOverrideType.CostMarkup)
|
||||||
|
o.PriceViz = o.CostViz + (o.CostViz * pct);
|
||||||
|
else if (cot == ContractOverrideType.PriceDiscount)
|
||||||
|
o.PriceViz = o.ListPriceViz - (o.ListPriceViz * pct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Pricing
|
//Calculate totals and taxes
|
||||||
if (ApplyPricingUpdate)
|
//NET
|
||||||
{
|
o.NetViz = o.PriceViz * o.TravelRateQuantity;
|
||||||
//default in case nothing to apply
|
|
||||||
newObj.Cost = 0;
|
|
||||||
newObj.ListPrice = 0;
|
|
||||||
newObj.Price = 0;
|
|
||||||
|
|
||||||
//in v7 it was ok to have no service rate selected
|
//TAX
|
||||||
//not sure why but carried forward to v8 so..
|
o.TaxAViz = 0;
|
||||||
if (newObj.TravelRateId != null)
|
o.TaxBViz = 0;
|
||||||
|
if (Tax != null)
|
||||||
|
{
|
||||||
|
if (Tax.TaxAPct != 0)
|
||||||
{
|
{
|
||||||
var s = await ct.TravelRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TravelRateId);
|
o.TaxAViz = o.NetViz * (Tax.TaxAPct / 100);
|
||||||
if (s != null)
|
}
|
||||||
|
if (Tax.TaxBPct != 0)
|
||||||
|
{
|
||||||
|
if (Tax.TaxOnTax)
|
||||||
{
|
{
|
||||||
newObj.Cost = s.Cost;
|
o.TaxBViz = (o.NetViz + o.TaxAViz) * (Tax.TaxBPct / 100);
|
||||||
newObj.ListPrice = s.Charge;
|
}
|
||||||
var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
|
else
|
||||||
TravelSetListPrice(newObj, Contract);
|
{
|
||||||
|
o.TaxBViz = o.NetViz * (Tax.TaxBPct / 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
o.LineTotalViz = o.NetViz + o.TaxAViz + o.TaxBViz;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SET PER UNIT LIST PRICE
|
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
// //BIZ ACTIONS
|
||||||
//(called by woitemtravel save and also by header save on change of contract)
|
// //
|
||||||
private static void TravelSetListPrice(WorkOrderItemTravel o, Contract c)
|
// //
|
||||||
{
|
// private async Task TravelBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemTravel newObj, WorkOrderItemTravel oldObj, IDbContextTransaction transaction)
|
||||||
if (c == null || c.ServiceRatesOverridePct == 0)
|
// {
|
||||||
{
|
// //automatic actions on record change, called AFTER validation
|
||||||
o.Price = o.ListPrice;//default with no contract
|
|
||||||
return;
|
// //currently no processing required except for created or modified at this time
|
||||||
}
|
// if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified)
|
||||||
if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup)
|
// return;
|
||||||
o.Price = o.Cost + (o.Cost * c.ServiceRatesOverridePct);
|
|
||||||
else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount)
|
// //SET TAXES AND PRICING
|
||||||
o.Price = o.ListPrice - (o.ListPrice * c.ServiceRatesOverridePct);
|
|
||||||
}
|
// //by default apply all automatic actions with further restrictions possible below
|
||||||
|
// bool ApplyTax = true;
|
||||||
|
// bool ApplyPricingUpdate = true;
|
||||||
|
|
||||||
|
// //if modifed, see what has changed and should be re-applied
|
||||||
|
// if (ayaEvent == AyaEvent.Modified)
|
||||||
|
// {
|
||||||
|
// //If it wasn't a service rate change there is no need to set pricing
|
||||||
|
// if (newObj.TravelRateId == oldObj.TravelRateId)
|
||||||
|
// {
|
||||||
|
// ApplyPricingUpdate = false;
|
||||||
|
// }
|
||||||
|
// //If taxes haven't change then no need to update taxes
|
||||||
|
// if (newObj.TaxCodeSaleId == oldObj.TaxCodeSaleId)
|
||||||
|
// ApplyTax = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //Tax code
|
||||||
|
// if (ApplyTax)
|
||||||
|
// {
|
||||||
|
// //Default in case nothing to apply
|
||||||
|
// newObj.TaxAPct = 0;
|
||||||
|
// newObj.TaxBPct = 0;
|
||||||
|
// newObj.TaxOnTax = false;
|
||||||
|
|
||||||
|
// if (newObj.TaxCodeSaleId != null)
|
||||||
|
// {
|
||||||
|
// var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TaxCodeSaleId);
|
||||||
|
// if (t != null)
|
||||||
|
// {
|
||||||
|
// newObj.TaxAPct = t.TaxAPct;
|
||||||
|
// newObj.TaxBPct = t.TaxBPct;
|
||||||
|
// newObj.TaxOnTax = t.TaxOnTax;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //Pricing
|
||||||
|
// if (ApplyPricingUpdate)
|
||||||
|
// {
|
||||||
|
// //default in case nothing to apply
|
||||||
|
// newObj.Cost = 0;
|
||||||
|
// newObj.ListPrice = 0;
|
||||||
|
// newObj.Price = 0;
|
||||||
|
|
||||||
|
// //in v7 it was ok to have no service rate selected
|
||||||
|
// //not sure why but carried forward to v8 so..
|
||||||
|
// if (newObj.TravelRateId != null)
|
||||||
|
// {
|
||||||
|
// var s = await ct.TravelRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TravelRateId);
|
||||||
|
// if (s != null)
|
||||||
|
// {
|
||||||
|
// newObj.Cost = s.Cost;
|
||||||
|
// newObj.ListPrice = s.Charge;
|
||||||
|
// var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
|
||||||
|
// TravelSetListPrice(newObj, Contract);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// // 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);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,20 @@ namespace AyaNova.Models
|
|||||||
public uint Concurrency { get; set; }
|
public uint Concurrency { get; set; }
|
||||||
|
|
||||||
public long? UserId { get; set; }
|
public long? UserId { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public string UserViz { get; set; }
|
||||||
public DateTime? TravelStartDate { get; set; }
|
public DateTime? TravelStartDate { get; set; }
|
||||||
public DateTime? TravelStopDate { get; set; }
|
public DateTime? TravelStopDate { get; set; }
|
||||||
public long? TravelRateId { get; set; }
|
public long? TravelRateId { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public string TravelRateViz { get; set; }
|
||||||
public string TravelDetails { get; set; }
|
public string TravelDetails { get; set; }
|
||||||
public decimal TravelRateQuantity { get; set; }
|
public decimal TravelRateQuantity { get; set; }
|
||||||
public decimal NoChargeQuantity { get; set; }
|
public decimal NoChargeQuantity { get; set; }
|
||||||
public long? ServiceBankId { get; set; }
|
public long? ServiceBankId { get; set; }
|
||||||
public long? TaxCodeSaleId { get; set; }
|
public long? TaxCodeSaleId { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public string TaxCodeSaleViz { get; set; }
|
||||||
public decimal Distance { get; set; }
|
public decimal Distance { get; set; }
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +51,7 @@ namespace AyaNova.Models
|
|||||||
// [NotMapped]
|
// [NotMapped]
|
||||||
// public decimal LineTotalViz { get; set; }
|
// public decimal LineTotalViz { get; set; }
|
||||||
|
|
||||||
//Standard pricing fields (mostly to support printed reports though some show in UI)
|
//Standard pricing fields (mostly to support printed reports though some show in UI)
|
||||||
//some not to be sent with record depending on role (i.e. cost and charge in some cases)
|
//some not to be sent with record depending on role (i.e. cost and charge in some cases)
|
||||||
public decimal? PriceOverride { get; set; }//user entered manually overridden price, if null then ignored in calcs otherwise this *is* the price even if zero
|
public decimal? PriceOverride { get; set; }//user entered manually overridden price, if null then ignored in calcs otherwise this *is* the price even if zero
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
|||||||
Reference in New Issue
Block a user