This commit is contained in:
@@ -61,44 +61,64 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
internal async Task<WorkOrder> WorkOrderCreateAsync(WorkOrder newObject, bool populateViz = true)
|
internal async Task<WorkOrder> WorkOrderCreateAsync(WorkOrder newObject, bool populateViz = true)
|
||||||
{
|
{
|
||||||
await WorkOrderValidateAsync(newObject, null);
|
using (var transaction = await ct.Database.BeginTransactionAsync())
|
||||||
if (HasErrors)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
await WorkOrderBizActionsAsync(AyaEvent.Created, newObject, null, null);
|
await WorkOrderValidateAsync(newObject, null);
|
||||||
newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
if (HasErrors)
|
||||||
newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
return null;
|
||||||
await ct.WorkOrder.AddAsync(newObject);
|
else
|
||||||
await ct.SaveChangesAsync();
|
|
||||||
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct);
|
|
||||||
await WorkOrderSearchIndexAsync(newObject, true);
|
|
||||||
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null);
|
|
||||||
|
|
||||||
//Was this a full workorder posted all at once?
|
|
||||||
//(seeder or api user, not something AyaNova front end would do)
|
|
||||||
if (newObject.Items.Count > 0)//our front end will post the header alone on new so this indicates a fully populated wo was saved
|
|
||||||
{
|
{
|
||||||
await GetCurrentContractFromContractIdAsync(newObject.ContractId);
|
await WorkOrderBizActionsAsync(AyaEvent.Created, newObject, null, null);
|
||||||
|
newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
||||||
|
newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
||||||
if (mContractInEffect != null && mContractInEffect.ResponseTime != TimeSpan.Zero)
|
await ct.WorkOrder.AddAsync(newObject);
|
||||||
newObject.CompleteByDate = DateTime.UtcNow.Add(mContractInEffect.ResponseTime);
|
|
||||||
|
|
||||||
//GRANDCHILD BIZ ACTIONS
|
|
||||||
foreach (WorkOrderItem wi in newObject.Items)
|
|
||||||
{
|
|
||||||
foreach (WorkOrderItemPart wip in wi.Parts)
|
|
||||||
await PartBizActionsAsync(AyaEvent.Created, wip, null, null);
|
|
||||||
foreach (WorkOrderItemLoan wil in wi.Loans)
|
|
||||||
await LoanBizActionsAsync(AyaEvent.Created, wil, null, null);
|
|
||||||
}
|
|
||||||
await ct.SaveChangesAsync();
|
await ct.SaveChangesAsync();
|
||||||
|
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct);
|
||||||
|
await WorkOrderSearchIndexAsync(newObject, true);
|
||||||
|
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null);
|
||||||
|
|
||||||
|
//Was this a full workorder posted all at once?
|
||||||
|
//(seeder or api user, not something AyaNova front end would do)
|
||||||
|
if (newObject.Items.Count > 0)//our front end will post the header alone on new so this indicates a fully populated wo was saved
|
||||||
|
{
|
||||||
|
await GetCurrentContractFromContractIdAsync(newObject.ContractId);
|
||||||
|
|
||||||
|
|
||||||
|
if (mContractInEffect != null && mContractInEffect.ResponseTime != TimeSpan.Zero)
|
||||||
|
newObject.CompleteByDate = DateTime.UtcNow.Add(mContractInEffect.ResponseTime);
|
||||||
|
|
||||||
|
//GRANDCHILD BIZ ACTIONS
|
||||||
|
foreach (WorkOrderItem wi in newObject.Items)
|
||||||
|
{
|
||||||
|
foreach (WorkOrderItemPart wip in wi.Parts)
|
||||||
|
await PartBizActionsAsync(AyaEvent.Created, wip, null, null);
|
||||||
|
foreach (WorkOrderItemLoan wil in wi.Loans)
|
||||||
|
await LoanBizActionsAsync(AyaEvent.Created, wil, null, null);
|
||||||
|
}
|
||||||
|
await ct.SaveChangesAsync();
|
||||||
|
|
||||||
|
//INVENTORY ADJUSTMENTS
|
||||||
|
foreach (WorkOrderItem wi in newObject.Items)
|
||||||
|
{
|
||||||
|
foreach (WorkOrderItemPart wip in wi.Parts)
|
||||||
|
{
|
||||||
|
await PartInventoryAdjustmentAsync(AyaEvent.Created, wip, null, transaction);
|
||||||
|
if (HasErrors)
|
||||||
|
{
|
||||||
|
await transaction.RollbackAsync();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await transaction.CommitAsync();
|
||||||
|
if (populateViz)
|
||||||
|
await WorkOrderPopulateVizFields(newObject, true);
|
||||||
|
|
||||||
|
await WorkOrderHandlePotentialNotificationEvent(AyaEvent.Created, newObject);
|
||||||
|
return newObject;
|
||||||
}
|
}
|
||||||
if (populateViz)
|
|
||||||
await WorkOrderPopulateVizFields(newObject, true);
|
|
||||||
await WorkOrderHandlePotentialNotificationEvent(AyaEvent.Created, newObject);
|
|
||||||
return newObject;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3088,21 +3108,31 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
internal async Task<WorkOrderItemPart> CreatePartAsync(WorkOrderItemPart newObject)
|
internal async Task<WorkOrderItemPart> CreatePartAsync(WorkOrderItemPart newObject)
|
||||||
{
|
{
|
||||||
await PartValidateAsync(newObject, null);
|
using (var transaction = await ct.Database.BeginTransactionAsync())
|
||||||
if (HasErrors)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
await PartBizActionsAsync(AyaEvent.Created, newObject, null, null);
|
await PartValidateAsync(newObject, null);
|
||||||
//newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
if (HasErrors)
|
||||||
//newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
return null;
|
||||||
await ct.WorkOrderItemPart.AddAsync(newObject);
|
else
|
||||||
await ct.SaveChangesAsync();
|
{
|
||||||
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct);
|
await PartBizActionsAsync(AyaEvent.Created, newObject, null, null);
|
||||||
await PartSearchIndexAsync(newObject, true);
|
//newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
||||||
//await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null);
|
//newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
||||||
await PartPopulateVizFields(newObject);
|
await ct.WorkOrderItemPart.AddAsync(newObject);
|
||||||
return newObject;
|
await ct.SaveChangesAsync();
|
||||||
|
await PartInventoryAdjustmentAsync(AyaEvent.Created, newObject, null, transaction);
|
||||||
|
if (HasErrors)
|
||||||
|
{
|
||||||
|
await transaction.RollbackAsync();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3122,43 +3152,53 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
internal async Task<WorkOrderItemPart> PartPutAsync(WorkOrderItemPart putObject)
|
internal async Task<WorkOrderItemPart> PartPutAsync(WorkOrderItemPart putObject)
|
||||||
{
|
{
|
||||||
WorkOrderItemPart dbObject = await PartGetAsync(putObject.Id, false);
|
using (var transaction = await ct.Database.BeginTransactionAsync())
|
||||||
if (dbObject == null)
|
|
||||||
{
|
{
|
||||||
AddError(ApiErrorCode.NOT_FOUND, "id");
|
WorkOrderItemPart dbObject = await PartGetAsync(putObject.Id, false);
|
||||||
return null;
|
if (dbObject == null)
|
||||||
}
|
{
|
||||||
if (dbObject.Concurrency != putObject.Concurrency)
|
AddError(ApiErrorCode.NOT_FOUND, "id");
|
||||||
{
|
return null;
|
||||||
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
|
}
|
||||||
return null;
|
if (dbObject.Concurrency != putObject.Concurrency)
|
||||||
}
|
{
|
||||||
|
|
||||||
//dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
|
|
||||||
//dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
|
|
||||||
|
|
||||||
await PartValidateAsync(putObject, dbObject);
|
|
||||||
if (HasErrors) return null;
|
|
||||||
await PartBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
|
|
||||||
ct.Replace(dbObject, putObject);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await ct.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
catch (DbUpdateConcurrencyException)
|
|
||||||
{
|
|
||||||
if (!await PartExistsAsync(putObject.Id))
|
|
||||||
AddError(ApiErrorCode.NOT_FOUND);
|
|
||||||
else
|
|
||||||
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
|
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
|
||||||
|
//dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
|
||||||
|
|
||||||
|
await PartValidateAsync(putObject, dbObject);
|
||||||
|
if (HasErrors) return null;
|
||||||
|
await PartBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
|
||||||
|
ct.Replace(dbObject, putObject);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ct.SaveChangesAsync();
|
||||||
|
await PartInventoryAdjustmentAsync(AyaEvent.Modified, putObject, dbObject, transaction);
|
||||||
|
if (HasErrors)
|
||||||
|
{
|
||||||
|
await transaction.RollbackAsync();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DbUpdateConcurrencyException)
|
||||||
|
{
|
||||||
|
if (!await PartExistsAsync(putObject.Id))
|
||||||
|
AddError(ApiErrorCode.NOT_FOUND);
|
||||||
|
else
|
||||||
|
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
return putObject;
|
||||||
}
|
}
|
||||||
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 PartPopulateVizFields(putObject);
|
|
||||||
return putObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -3166,29 +3206,38 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
internal async Task<bool> PartDeleteAsync(long id, IDbContextTransaction parentTransaction = null)
|
internal async Task<bool> PartDeleteAsync(long id, IDbContextTransaction parentTransaction = null)
|
||||||
{
|
{
|
||||||
var transaction = parentTransaction ?? await ct.Database.BeginTransactionAsync();
|
// var transaction = parentTransaction ?? await ct.Database.BeginTransactionAsync();
|
||||||
try
|
using (var transaction = parentTransaction ?? await ct.Database.BeginTransactionAsync())
|
||||||
{
|
{
|
||||||
var dbObject = await PartGetAsync(id, false);
|
try
|
||||||
PartValidateCanDelete(dbObject);
|
{
|
||||||
if (HasErrors)
|
var dbObject = await PartGetAsync(id, false);
|
||||||
return false;
|
PartValidateCanDelete(dbObject);
|
||||||
await PartBizActionsAsync(AyaEvent.Modified, null, dbObject, transaction);
|
if (HasErrors)
|
||||||
ct.WorkOrderItemPart.Remove(dbObject);
|
return false;
|
||||||
await ct.SaveChangesAsync();
|
await PartBizActionsAsync(AyaEvent.Deleted, null, dbObject, transaction);
|
||||||
//Log event
|
ct.WorkOrderItemPart.Remove(dbObject);
|
||||||
await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix??
|
await ct.SaveChangesAsync();
|
||||||
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct);
|
await PartInventoryAdjustmentAsync(AyaEvent.Deleted, null, dbObject, transaction);
|
||||||
//await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
|
if (HasErrors)
|
||||||
//await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct);
|
{
|
||||||
if (parentTransaction == null)
|
await transaction.RollbackAsync();
|
||||||
await transaction.CommitAsync();
|
return false;
|
||||||
await PartHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject);
|
}
|
||||||
}
|
//Log event
|
||||||
catch
|
await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix??
|
||||||
{
|
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct);
|
||||||
//Just re-throw for now, let exception handler deal, but in future may want to deal with this more here
|
//await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
|
||||||
throw;
|
//await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct);
|
||||||
|
if (parentTransaction == null)
|
||||||
|
await transaction.CommitAsync();
|
||||||
|
await PartHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//Just re-throw for now, let exception handler deal, but in future may want to deal with this more here
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3330,6 +3379,50 @@ namespace AyaNova.Biz
|
|||||||
private async Task PartBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemPart newObj, WorkOrderItemPart oldObj, IDbContextTransaction transaction)
|
private async Task PartBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemPart newObj, WorkOrderItemPart oldObj, IDbContextTransaction transaction)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//SNAPSHOT PRICING IF NECESSARY
|
||||||
|
if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//SNAPSHOT PRICING
|
||||||
|
bool SnapshotPricing = true;
|
||||||
|
|
||||||
|
//if modifed, see what has changed and should be re-applied
|
||||||
|
if (ayaEvent == AyaEvent.Modified)
|
||||||
|
{
|
||||||
|
//If it wasn't a complete part change there is no need to set pricing
|
||||||
|
if (newObj.PartId == oldObj.PartId)
|
||||||
|
{
|
||||||
|
SnapshotPricing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Pricing
|
||||||
|
if (SnapshotPricing)
|
||||||
|
{
|
||||||
|
//default in case nothing to apply
|
||||||
|
newObj.Cost = 0;
|
||||||
|
newObj.ListPrice = 0;
|
||||||
|
|
||||||
|
|
||||||
|
var s = await ct.Part.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.PartId);
|
||||||
|
if (s != null)
|
||||||
|
{
|
||||||
|
newObj.Cost = s.Cost;
|
||||||
|
newObj.ListPrice = s.Retail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//BIZ ACTIONS
|
||||||
|
//
|
||||||
|
//
|
||||||
|
private async Task PartInventoryAdjustmentAsync(AyaEvent ayaEvent, WorkOrderItemPart newObj, WorkOrderItemPart oldObj, IDbContextTransaction transaction)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
if (AyaNova.Util.ServerGlobalBizSettings.UseInventory)
|
if (AyaNova.Util.ServerGlobalBizSettings.UseInventory)
|
||||||
{
|
{
|
||||||
PartInventoryBiz pib = new PartInventoryBiz(ct, UserId, UserTranslationId, CurrentUserRoles);
|
PartInventoryBiz pib = new PartInventoryBiz(ct, UserId, UserTranslationId, CurrentUserRoles);
|
||||||
@@ -3453,58 +3546,9 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//SNAPSHOT PRICING IF NECESSARY
|
|
||||||
if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//SNAPSHOT PRICING
|
|
||||||
bool SnapshotPricing = true;
|
|
||||||
|
|
||||||
//if modifed, see what has changed and should be re-applied
|
|
||||||
if (ayaEvent == AyaEvent.Modified)
|
|
||||||
{
|
|
||||||
//If it wasn't a complete part change there is no need to set pricing
|
|
||||||
if (newObj.PartId == oldObj.PartId)
|
|
||||||
{
|
|
||||||
SnapshotPricing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Pricing
|
|
||||||
if (SnapshotPricing)
|
|
||||||
{
|
|
||||||
//default in case nothing to apply
|
|
||||||
newObj.Cost = 0;
|
|
||||||
newObj.ListPrice = 0;
|
|
||||||
|
|
||||||
|
|
||||||
var s = await ct.Part.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.PartId);
|
|
||||||
if (s != null)
|
|
||||||
{
|
|
||||||
newObj.Cost = s.Cost;
|
|
||||||
newObj.ListPrice = s.Retail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// // 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
|
//VALIDATION
|
||||||
|
|||||||
Reference in New Issue
Block a user