diff --git a/server/AyaNova/Controllers/SearchController.cs b/server/AyaNova/Controllers/SearchController.cs index 8c8042f1..bbb2d88c 100644 --- a/server/AyaNova/Controllers/SearchController.cs +++ b/server/AyaNova/Controllers/SearchController.cs @@ -141,7 +141,7 @@ namespace AyaNova.Api.Controllers case AyaType.WorkOrderItemTravel: case AyaType.WorkOrderItemOutsideService: case AyaType.WorkOrderItemUnit: - AyaTypeId TypeId = new AyaTypeId(AyaType.WorkOrder, await WorkOrderBiz.GetWorkOrderIdFromRelativeAsync(ayaType, id, ct)); + AyaTypeId TypeId = new AyaTypeId(AyaType.WorkOrder, (await WorkOrderBiz.GetWorkOrderIdFromRelativeAsync(ayaType, id, ct)).WorkOrderId); return Ok(ApiOkResponse.Response(new { AyaType = TypeId.ATypeAsInt, Id = TypeId.ObjectId })); default: return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, "Only types with ancestors are valid")); diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index d8cd9d90..e608bc61 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -490,16 +490,21 @@ namespace AyaNova.Biz // } + + //////////////////////////////////////////////////////////////////////////////////////////////// //GET WORKORDER ID FROM DESCENDANT TYPE AND ID // - internal static async Task GetWorkOrderIdFromRelativeAsync(AyaType ayaType, long id, AyContext ct) + internal static async Task GetWorkOrderIdFromRelativeAsync(AyaType ayaType, long id, AyContext ct) { + WorkorderAndItemId w = new WorkorderAndItemId(); long woitemid = 0; switch (ayaType) { case AyaType.WorkOrder: - return id; + w.WorkOrderId = id; + w.WorkOrderItemId = 0; + return w; case AyaType.WorkOrderItem: woitemid = id; break; @@ -531,17 +536,24 @@ namespace AyaNova.Biz woitemid = await ct.WorkOrderItemOutsideService.AsNoTracking().Where(z => z.Id == id).Select(z => z.WorkOrderItemId).SingleOrDefaultAsync(); break; case AyaType.WorkOrderStatus: - return await ct.WorkOrderState.AsNoTracking().Where(z => z.Id == id).Select(z => z.WorkOrderId).SingleOrDefaultAsync(); + w.WorkOrderId = await ct.WorkOrderState.AsNoTracking().Where(z => z.Id == id).Select(z => z.WorkOrderId).SingleOrDefaultAsync(); + w.WorkOrderItemId = 0; + return w; case AyaType.WorkOrderItemUnit: woitemid = await ct.WorkOrderItemUnit.AsNoTracking().Where(z => z.Id == id).Select(z => z.WorkOrderItemId).SingleOrDefaultAsync(); break; default: - throw new System.NotSupportedException($"WorkOrderBiz::GetAncestor -> AyaType {ayaType.ToString()} is not supported"); + throw new System.NotSupportedException($"WorkOrderBiz::GetWorkOrderIdFromRelativeAsync -> AyaType {ayaType.ToString()} is not supported"); } - return await ct.WorkOrderItem.AsNoTracking() - .Where(z => z.Id == woitemid) - .Select(z => z.WorkOrderId) - .SingleOrDefaultAsync(); + + w.WorkOrderId = await ct.WorkOrderItem.AsNoTracking() + .Where(z => z.Id == woitemid) + .Select(z => z.WorkOrderId) + .SingleOrDefaultAsync(); + w.WorkOrderItemId = woitemid; + return w; + + } @@ -760,39 +772,104 @@ namespace AyaNova.Biz */ + //////////////////////////////////////////////////////////////////////////////////////////////// + // GET PARTIAL WORKORDER FOR REPORTING + // (returns workorder consisting only of the path from child or grandchild up to header populated + // with display data for reporting) + // + internal async Task WorkOrderGetPartialAsync(AyaType ayaType, long id) + { + //if it's the entire workorder just get, populate and return as normal + if (ayaType == AyaType.WorkOrder) + { + return await WorkOrderGetAsync(id, true, false); + } + + var wid = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); + + //get header only + var ret = await ct.WorkOrder.AsNoTracking().SingleOrDefaultAsync(x => x.Id == wid.WorkOrderId); + + //not found don't bomb, just return null + if (ret == null) return ret; + + //explicit load subitems as required... + + //get the single workorder item required + var woitem = await ct.WorkOrderItem.AsNoTracking().SingleOrDefaultAsync(x => x.Id == wid.WorkOrderItemId); + + switch (ayaType) + { + case AyaType.WorkOrderItemExpense: + woitem.Expenses.Add(await ct.WorkOrderItemExpense.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemLabor: + woitem.Labors.Add(await ct.WorkOrderItemLabor.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemLoan: + woitem.Loans.Add(await ct.WorkOrderItemLoan.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemPart: + woitem.Parts.Add(await ct.WorkOrderItemPart.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemPartRequest: + woitem.PartRequests.Add(await ct.WorkOrderItemPartRequest.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemScheduledUser: + woitem.ScheduledUsers.Add(await ct.WorkOrderItemScheduledUser.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemTask: + woitem.Tasks.Add(await ct.WorkOrderItemTask.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemTravel: + woitem.Travels.Add(await ct.WorkOrderItemTravel.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemOutsideService: + woitem.OutsideServices.Add(await ct.WorkOrderItemOutsideService.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + case AyaType.WorkOrderItemUnit: + woitem.Units.Add(await ct.WorkOrderItemUnit.AsNoTracking().Where(z => z.Id == id).SingleOrDefaultAsync()); + break; + } + + ret.Items.Add(woitem); + + // var goodPosts = context.Entry(blog) + // .Collection(b => b.Posts) + // .Query() + // .Where(p => p.Rating > 3) + // .ToList(); + + + + await WorkOrderPopulateVizFields(ret, false); + return ret; + } + //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest) { + //workorder reports for entire workorder or just sub parts all go through here + //if the ayatype is a descendant of the workorder then only the portion of the workorder from that descendant directly up to the header will be populated and returned var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); + while (idList.Any()) { var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE); idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray(); List batchResults = new List(); foreach (long batchId in batch) - batchResults.Add(await WorkOrderGetAsync(batchId, true, false)); + batchResults.Add(await WorkOrderGetPartialAsync(dataListSelectedRequest.AType, batchId)); //order the results back into original var orderedList = from id in batch join z in batchResults on id equals z.Id select z; - - - //TODO: ##HERE## SEE ContractBiz for example implementation; will need to pre-cache some translation keys for enum lists etc, for example: - // private async Task TaskPopulateVizFields(WorkOrderItemTask o, List taskCompletionTypeEnumList = null) - - - foreach (WorkOrder w in orderedList) { - //populate entire workorder graph - //await WorkOrderPopulateVizFields(w); - //this is done by the initial fetch now - - var jo = JObject.FromObject(w); //WorkOrder header custom fields @@ -2026,8 +2103,8 @@ namespace AyaNova.Biz WorkOrderItem oProposed = (WorkOrderItem)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); //STANDARD EVENTS FOR ALL OBJECTS @@ -2401,8 +2478,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemExpense oProposed = (WorkOrderItemExpense)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -2891,8 +2968,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemLabor oProposed = (WorkOrderItemLabor)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -3270,8 +3347,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemLoan oProposed = (WorkOrderItemLoan)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -3585,8 +3662,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemOutsideService oProposed = (WorkOrderItemOutsideService)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -4316,8 +4393,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemPart oProposed = (WorkOrderItemPart)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -4568,8 +4645,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemPartRequest oProposed = (WorkOrderItemPartRequest)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); proposedObj.Tags = WorkorderInfo.Tags; proposedObj.Name = WorkorderInfo.Serial.ToString(); @@ -4835,8 +4912,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemScheduledUser oProposed = (WorkOrderItemScheduledUser)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -5218,8 +5295,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemTask oProposed = (WorkOrderItemTask)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -5670,8 +5747,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemTravel oProposed = (WorkOrderItemTravel)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); oProposed.Tags = WorkorderInfo.Tags; @@ -5935,8 +6012,8 @@ namespace AyaNova.Biz bool isNew = currentObj == null; WorkOrderItemUnit oProposed = (WorkOrderItemUnit)proposedObj; - var woId = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); - var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == woId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(AyaType.WorkOrderItem, oProposed.WorkOrderItemId, ct); + var WorkorderInfo = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == wid.WorkOrderId).Select(x => new { Serial = x.Serial, Tags = x.Tags }).FirstOrDefaultAsync(); oProposed.Name = WorkorderInfo.Serial.ToString(); //STANDARD EVENTS FOR ALL OBJECTS @@ -6080,8 +6157,8 @@ namespace AyaNova.Biz { if (mFetchedContractAlready == false) { - long WoId = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); - var WoContractId = await ct.WorkOrder.AsNoTracking().Where(z => z.Id == WoId).Select(z => z.ContractId).FirstOrDefaultAsync(); + var wid = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); + var WoContractId = await ct.WorkOrder.AsNoTracking().Where(z => z.Id == wid.WorkOrderId).Select(z => z.ContractId).FirstOrDefaultAsync(); await GetCurrentContractFromContractIdAsync(WoContractId); } return mContractInEffect; @@ -6116,9 +6193,9 @@ namespace AyaNova.Biz internal static async Task GetCurrentWorkOrderStatusFromRelatedAsync(AyaType ayaType, long id, AyContext ct) { //static method - long WoId = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); + var wid = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); var stat = await ct.WorkOrderState.AsNoTracking() - .Where(z => z.WorkOrderId == WoId) + .Where(z => z.WorkOrderId == wid.WorkOrderId) .OrderByDescending(z => z.Created) .Take(1) .FirstOrDefaultAsync(); diff --git a/server/AyaNova/models/dto/WorkorderAndItemId.cs b/server/AyaNova/models/dto/WorkorderAndItemId.cs new file mode 100644 index 00000000..ea66e505 --- /dev/null +++ b/server/AyaNova/models/dto/WorkorderAndItemId.cs @@ -0,0 +1,8 @@ +namespace AyaNova.Models +{ + public class WorkorderAndItemId + { + public long WorkOrderId { get; set; } + public long WorkOrderItemId { get; set; } + } +}