diff --git a/server/AyaNova/Controllers/WorkOrderController.cs b/server/AyaNova/Controllers/WorkOrderController.cs index b860bd0f..ab93b353 100644 --- a/server/AyaNova/Controllers/WorkOrderController.cs +++ b/server/AyaNova/Controllers/WorkOrderController.cs @@ -145,6 +145,7 @@ namespace AyaNova.Api.Controllers // NOTE: HERE would be the second check of biz rules before returning the object // in cases where there is also a business rule to affect retrieval on top of basic rights + //NO, NOT HERE, in biz object surely? return Ok(ApiOkResponse.Response(o, !Authorized.HasModifyRole(HttpContext.Items, biz.BizType))); } @@ -177,6 +178,7 @@ namespace AyaNova.Api.Controllers if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); + biz.PutAsync(id, updatedObject); //todo: handle concurrency in biz object, what to do? // var o = await biz.PutAsync(id, updatedObject); diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 11fa6df9..0027d350 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -272,88 +272,270 @@ namespace AyaNova.Biz // } #endregion workorder level - #region WorkOrderItem level + //////////////////////////////////////////////////////////////////////////////////////////////// + //EXISTS + internal async Task ItemExistsAsync(long id) + { + return await ct.WorkOrderItem.AnyAsync(e => e.Id == id); + } //////////////////////////////////////////////////////////////////////////////////////////////// //CREATE // - internal async Task CreateItemAsync(WorkOrderItem newObject) + internal async Task CreateItemAsync(WorkOrderItem newObject) { - await ValidateAsync(newObject, null); + await ItemValidateAsync(newObject, null); if (HasErrors) return null; else { - newObject.Serial = ServerBootConfig.WORKORDER_SERIAL.GetNext(); newObject.Tags = TagUtil.NormalizeTags(newObject.Tags); newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); - await ct.WorkOrder.AddAsync(newObject); + await ct.WorkOrderItem.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); - await SearchIndexAsync(newObject, true); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItem, AyaEvent.Created), ct); + await ItemSearchIndexAsync(newObject, true); await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); return newObject; } } - //////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION - // - - //Can save or update? - private async Task ValidateItemAsync(WorkOrderItem proposedObj, WorkOrderItem currentObj) + // + private async Task ItemValidateAsync(WorkOrderItem proposedObj, WorkOrderItem currentObj) { - //run validation and biz rules bool isNew = currentObj == null; - // //Name required - // if (string.IsNullOrWhiteSpace(proposedObj.Name)) - // AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name"); - - // //Name must be less than 255 characters - // if (proposedObj.Name.Length > 255) - // AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 max"); - - // //If name is otherwise OK, check that name is unique - // if (!PropertyHasErrors("Name")) - // { - // //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false - // if (await ct.WorkOrder.AnyAsync(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id)) - // { - // AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name"); - // } - // } - + //does it have a valid workorder id + if (proposedObj.WorkorderId == 0) + AddError(ApiErrorCode.VALIDATION_REQUIRED, "WorkorderId"); + else if (!await WorkOrderExistsAsync(proposedObj.WorkorderId)) + { + AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkorderId"); + } //Any form customizations to validate? - var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(x => x.FormKey == AyaType.WorkOrder.ToString()); + var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(x => x.FormKey == AyaType.WorkOrderItem.ToString()); if (FormCustomization != null) { //Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required //validate users choices for required non custom fields - RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj); + RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors //validate custom fields CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); } - } - - //Can delete? - // private void ValidateCanDelete(WorkOrder inObj) + // //Can delete? + // private void ValidateCanDeleteItem(WorkOrderItem inObj) // { // //whatever needs to be check to delete this object // } + + + private async Task ItemSearchIndexAsync(WorkOrderItem obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItem); + SearchParams.AddText(obj.Notes).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + + if (isNew) + await Search.ProcessNewObjectKeywordsAsync(SearchParams); + else + await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); + } + + public async Task ItemGetSearchResultSummary(long id) + { + var obj = await ct.WorkOrderItem.SingleOrDefaultAsync(m => m.Id == id); + var SearchParams = new Search.SearchIndexProcessObjectParameters(); + if (obj != null) + SearchParams.AddText(obj.Notes).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + return SearchParams; + } #endregion work order item level + #region WorkOrderItemLabor level + //////////////////////////////////////////////////////////////////////////////////////////////// + //EXISTS + internal async Task LaborExistsAsync(long id) + { + return await ct.WorkOrderItemLabor.AnyAsync(e => e.Id == id); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + //CREATE + // + internal async Task LaborCreateAsync(WorkOrderItemLabor newObject) + { + await LaborValidateAsync(newObject, null); + if (HasErrors) + return null; + else + { + newObject.Tags = TagUtil.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, AyaType.WorkOrderItemLabor, AyaEvent.Created), ct); + await LaborSearchIndexAsync(newObject, true); + await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + return newObject; + } + } + //////////////////////////////////////////////////////////////////////////////////////////////// + //VALIDATION + // + private async Task LaborValidateAsync(WorkOrderItemLabor proposedObj, WorkOrderItemLabor currentObj) + { + //run validation and biz rules + bool isNew = currentObj == null; + if (proposedObj.WorkorderItemId == 0) + AddError(ApiErrorCode.VALIDATION_REQUIRED, "WorkorderItemId"); + else if (!await ItemExistsAsync(proposedObj.WorkorderItemId)) + { + AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkorderItemId"); + } + + //Any form customizations to validate? + var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(x => x.FormKey == AyaType.WorkOrderItemLabor.ToString()); + if (FormCustomization != null) + { + //Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required + + //validate users choices for required non custom fields + RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors + + //validate custom fields + CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } + } + + // //Can delete? + // private void LaborValidateCanDelete(WorkOrderItemLabor inObj) + // { + // //whatever needs to be check to delete this object + // } + + + private async Task LaborSearchIndexAsync(WorkOrderItemLabor obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItemLabor); + SearchParams.AddText(obj.Notes).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + + if (isNew) + await Search.ProcessNewObjectKeywordsAsync(SearchParams); + else + await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); + } + + public async Task LaborGetSearchResultSummary(long id) + { + var obj = await ct.WorkOrderItemLabor.SingleOrDefaultAsync(m => m.Id == id); + var SearchParams = new Search.SearchIndexProcessObjectParameters(); + if (obj != null) + SearchParams.AddText(obj.Notes).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + return SearchParams; + } + #endregion work order item LABOR level + + #region WorkOrderItemPart level + //////////////////////////////////////////////////////////////////////////////////////////////// + //EXISTS + internal async Task PartExistsAsync(long id) + { + return await ct.WorkOrderItemPart.AnyAsync(e => e.Id == id); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + //CREATE + // + internal async Task PartCreateAsync(WorkOrderItemPart newObject) + { + await PartValidateAsync(newObject, null); + if (HasErrors) + return null; + else + { + newObject.Tags = TagUtil.NormalizeTags(newObject.Tags); + newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); + await ct.WorkOrderItemPart.AddAsync(newObject); + await ct.SaveChangesAsync(); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemPart, AyaEvent.Created), ct); + await PartSearchIndexAsync(newObject, true); + await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + return newObject; + } + } + + + //////////////////////////////////////////////////////////////////////////////////////////////// + //VALIDATION + // + private async Task PartValidateAsync(WorkOrderItemPart proposedObj, WorkOrderItemPart currentObj) + { + //run validation and biz rules + bool isNew = currentObj == null; + + if (proposedObj.WorkorderItemId == 0) + AddError(ApiErrorCode.VALIDATION_REQUIRED, "WorkorderItemId"); + else if (!await ItemExistsAsync(proposedObj.WorkorderItemId)) + { + AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkorderItemId"); + } + + //Any form customizations to validate? + var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(x => x.FormKey == AyaType.WorkOrderItemPart.ToString()); + if (FormCustomization != null) + { + //Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required + + //validate users choices for required non custom fields + RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);//note: this is passed only to add errors + + //validate custom fields + CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); + } + } + + // //Can delete? + // private void PartValidateCanDelete(WorkOrderItemPart inObj) + // { + // //whatever needs to be check to delete this object + // } + + + private async Task PartSearchIndexAsync(WorkOrderItemPart obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItemPart); + SearchParams.AddText(obj.Notes).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + + if (isNew) + await Search.ProcessNewObjectKeywordsAsync(SearchParams); + else + await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); + } + + public async Task PartGetSearchResultSummary(long id) + { + var obj = await ct.WorkOrderItemPart.SingleOrDefaultAsync(m => m.Id == id); + var SearchParams = new Search.SearchIndexProcessObjectParameters(); + if (obj != null) + SearchParams.AddText(obj.Notes).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + return SearchParams; + } + #endregion work order item LABOR level //////////////////////////////////////////////////////////////////////////////////////////////// //JOB / OPERATIONS diff --git a/server/AyaNova/models/AyContext.cs b/server/AyaNova/models/AyContext.cs index fe041a7b..abd4dbe8 100644 --- a/server/AyaNova/models/AyContext.cs +++ b/server/AyaNova/models/AyContext.cs @@ -42,6 +42,8 @@ namespace AyaNova.Models public virtual DbSet Vendor { get; set; } public virtual DbSet WorkOrder { get; set; } public virtual DbSet WorkOrderItem { get; set; } + public virtual DbSet WorkOrderItemLabor { get; set; } + public virtual DbSet WorkOrderItemPart { get; set; } public virtual DbSet WorkOrderTemplate { get; set; } public virtual DbSet WorkOrderTemplateItem { get; set; } @@ -123,7 +125,7 @@ namespace AyaNova.Models .WithOne(i => i.User) .HasForeignKey(b => b.UserId) .OnDelete(DeleteBehavior.NoAction); - + // //Workorder // modelBuilder.Entity() // .HasOne(p => p.WorkOrder)