diff --git a/docs/8.0/ayanova/docs/ay-customize.md b/docs/8.0/ayanova/docs/ay-customize.md index 90832ed9..0caa3fff 100644 --- a/docs/8.0/ayanova/docs/ay-customize.md +++ b/docs/8.0/ayanova/docs/ay-customize.md @@ -49,7 +49,7 @@ To enforce a rule that a field **must** have data entered into it, put a checkma Some fields by their nature can't be set to required and will not display a Required checkbox: -- many fields are already required internally by AyaNova such as a Customer Name field +- many fields are already required internally by AyaNova such as a Customer Name and many numeric / currency fields which are not optional - some control types such as checkboxes don't support the concept of no entry due to having only two states - logistics reasons apply to other controls such as signature controls on work orders which logically can't be signed until the work is completed diff --git a/server/AyaNova/Controllers/FormCustomController.cs b/server/AyaNova/Controllers/FormCustomController.cs index 701ab8db..8e7e351f 100644 --- a/server/AyaNova/Controllers/FormCustomController.cs +++ b/server/AyaNova/Controllers/FormCustomController.cs @@ -142,10 +142,10 @@ namespace AyaNova.Api.Controllers /// Update FormCustom /// /// - /// + /// /// [HttpPut("{formkey}")] - public async Task PutFormCustom([FromRoute] string formkey, [FromBody] FormCustom inObj) + public async Task PutFormCustom([FromRoute] string formkey, [FromBody] FormCustom updatedObject) { if (!serverState.IsOpen && UserIdFromContext.Id(HttpContext.Items) != 1)//bypass for superuser to fix fundamental problems return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); @@ -156,26 +156,36 @@ namespace AyaNova.Api.Controllers //Instantiate the business object handler FormCustomBiz biz = FormCustomBiz.GetBiz(ct, HttpContext); - var o = await biz.GetAsync(formkey); - if (o == null) - return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); + // var o = await biz.GetAsync(formkey); + // if (o == null) + // return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); - try + var o = await biz.PutAsync(updatedObject); + if (o == null) { - if (!await biz.PutAsync(o, inObj)) + if (biz.Errors.Exists(z => z.Code == ApiErrorCode.CONCURRENCY_CONFLICT)) + return StatusCode(409, new ApiErrorResponse(biz.Errors)); + else return BadRequest(new ApiErrorResponse(biz.Errors)); } - catch (DbUpdateConcurrencyException) - { - if (!await biz.ExistsAsync(formkey)) - return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); - else - return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT)); - } - return Ok(ApiOkResponse.Response(new { Concurrency = o.Concurrency })); + return Ok(ApiOkResponse.Response(new { Concurrency = o.Concurrency })); ; + + // try + // { + // if (!await biz.PutAsync(o, inObj)) + // return BadRequest(new ApiErrorResponse(biz.Errors)); + // } + // catch (DbUpdateConcurrencyException) + // { + // if (!await biz.ExistsAsync(formkey)) + // return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); + // else + // return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT)); + // } + // return Ok(ApiOkResponse.Response(new { Concurrency = o.Concurrency })); } diff --git a/server/AyaNova/biz/FormCustomBiz.cs b/server/AyaNova/biz/FormCustomBiz.cs index 09c0772f..1d146163 100644 --- a/server/AyaNova/biz/FormCustomBiz.cs +++ b/server/AyaNova/biz/FormCustomBiz.cs @@ -111,35 +111,67 @@ namespace AyaNova.Biz - //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // //put - internal async Task PutAsync(FormCustom dbObject, FormCustom inObj) + internal async Task PutAsync(FormCustom putObject) { - //todo: replace with new put methodology - //Replace the db object with the PUT object - CopyObject.Copy(inObj, dbObject, "Id"); - //Set "original" value of concurrency token to input token - //this will allow EF to check it out - ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency; - - await ValidateAsync(dbObject, false); + var dbObject = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == putObject.FormKey); + if (dbObject == null) + { + AddError(ApiErrorCode.NOT_FOUND, "formKey"); + return null; + } + if (dbObject.Concurrency != putObject.Concurrency) + { + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } + dbObject.Template = JsonUtil.CompactJson(putObject.Template); + putObject.Id=dbObject.Id;//weird workaround needed because ID is not sent with the putobject for...reasons 🤷? + await ValidateAsync(putObject, false); if (HasErrors) - return false; - - dbObject.Template = JsonUtil.CompactJson(dbObject.Template); - await ct.SaveChangesAsync(); - + return null; + ct.Replace(dbObject, putObject); + try + { + await ct.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await ExistsAsync(putObject.FormKey)) + AddError(ApiErrorCode.NOT_FOUND); + else + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } //Log modification and save context await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); + return putObject; + // //todo: replace with new put methodology + + // //Replace the db object with the PUT object + // CopyObject.Copy(putObject, dbObject, "Id"); + // //Set "original" value of concurrency token to input token + // //this will allow EF to check it out + // ct.Entry(dbObject).OriginalValues["Concurrency"] = putObject.Concurrency; + + // await ValidateAsync(dbObject, false); + // if (HasErrors) + // return false; + + // dbObject.Template = JsonUtil.CompactJson(dbObject.Template); + // await ct.SaveChangesAsync(); + + // //Log modification and save context + // await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); - return true; + // return true; } diff --git a/server/AyaNova/biz/FormFieldReference.cs b/server/AyaNova/biz/FormFieldReference.cs index e8358b9e..9fb2cc3b 100644 --- a/server/AyaNova/biz/FormFieldReference.cs +++ b/server/AyaNova/biz/FormFieldReference.cs @@ -1013,7 +1013,8 @@ namespace AyaNova.Biz l.Add(new FormField { TKey = "TaxBAmt", FieldKey = "ExpenseTaxBViz", TKeySection = "WorkOrderItemExpense", Requireable = false }); l.Add(new FormField { TKey = "LineTotal", FieldKey = "ExpenseLineTotalViz", TKeySection = "WorkOrderItemExpense", Requireable = false }); - //WORKORDER ITEM LOAN + //WORKORDER ITEM LOAN WorkOrderItemLoanRate ? + l.Add(new FormField { TKey = "WorkOrderItemLoanRate", TKeySection = "WorkOrderItemLoan", ModelProperty = "Rate", Requireable = false }); l.Add(new FormField { TKey = "WorkOrderItemLoanNotes", TKeySection = "WorkOrderItemLoan", ModelProperty = "Notes" }); l.Add(new FormField { TKey = "WorkOrderItemLoanOutDate", TKeySection = "WorkOrderItemLoan", ModelProperty = "OutDate" }); l.Add(new FormField { TKey = "WorkOrderItemLoanDueDate", TKeySection = "WorkOrderItemLoan", ModelProperty = "DueDate" }); @@ -1023,7 +1024,7 @@ namespace AyaNova.Biz l.Add(new FormField { TKey = "ListPrice", FieldKey = "LoanListPrice", TKeySection = "WorkOrderItemLoan", Requireable = false }); l.Add(new FormField { TKey = "Price", FieldKey = "LoanPriceViz", TKeySection = "WorkOrderItemLoan", Requireable = false }); l.Add(new FormField { TKey = "PriceOverride", FieldKey = "LoanPriceOverride", TKeySection = "WorkOrderItemLoan", ModelProperty = "PriceOverride" }); - l.Add(new FormField { TKey = "UnitOfMeasure", FieldKey = "LoanUnitOfMeasureViz", TKeySection = "WorkOrderItemLoan", Requireable = false }); + //l.Add(new FormField { TKey = "UnitOfMeasure", FieldKey = "LoanUnitOfMeasureViz", TKeySection = "WorkOrderItemLoan", Requireable = false }); l.Add(new FormField { TKey = "NetPrice", FieldKey = "LoanNetViz", TKeySection = "WorkOrderItemLoan", Requireable = false }); l.Add(new FormField { TKey = "TaxAAmt", FieldKey = "LoanTaxAViz", TKeySection = "WorkOrderItemLoan", Requireable = false }); l.Add(new FormField { TKey = "TaxBAmt", FieldKey = "LoanTaxBViz", TKeySection = "WorkOrderItemLoan", Requireable = false });