From 95aff8d755a26b6a5b91b4701df1ffb654aba54e Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Tue, 13 Apr 2021 23:18:03 +0000 Subject: [PATCH] --- ayanova/devdocs/todo.txt | 1 - ayanova/src/views/svc-workorder.vue | 161 ++++++++++++++++++---------- 2 files changed, 103 insertions(+), 59 deletions(-) diff --git a/ayanova/devdocs/todo.txt b/ayanova/devdocs/todo.txt index 7a015752..e11e8d6c 100644 --- a/ayanova/devdocs/todo.txt +++ b/ayanova/devdocs/todo.txt @@ -228,7 +228,6 @@ todo: many biz objects are not using new PUT methodology CURRENTLY DOING: OVERALL - - Duplicate test - Partial save even if parts fail?? kind of the point of the new system isn't it? or was that to allow a user to go into a specific section and edit it, not necessarily make willy nilly edits anywhere diff --git a/ayanova/src/views/svc-workorder.vue b/ayanova/src/views/svc-workorder.vue index 17f24b1f..ef46286c 100644 --- a/ayanova/src/views/svc-workorder.vue +++ b/ayanova/src/views/svc-workorder.vue @@ -413,64 +413,92 @@ export default { //walk the tree and save dirty //items in correct order //######################################################## - let noProblem = true; + const isPost = vm.obj.id == 0; + let err = { + fatal: false, //fatal error, further save is pointless, bail early and report + error: false, //true if any error regardless if fatal, set by each save / delete + header: null, //res.error collections exactly as provided by server to be synthesized later + states: [], + items: [], + scheduledUsers: [] + }; + + /* + TODO: collect return errors but continue to try to save unless fatal error then bail + report cumulative errors at end as if a single save + - return object with format: {fatalError:true/false, errors:[collection of errors ]} + + */ + //UNSAVED HEADER MUST BE FIRST //(otherwise there's nothing to hang the other things off of) let headerSaved = false; if (this.obj.concurrency == 0) { - noProblem = await saveHeader(vm); + err = await saveHeader(vm, err); headerSaved = true; } //LOCKED? State must be saved first then (assuming it unlocks) let stateSaved = false; if (this.obj.isLockedAtServer) { - noProblem = await saveState(vm); - stateSaved = true; - //update which areas are available to user - //which may have changed due to state being saved (saveState sets the current islocked value) - updateRights(vm); + err = await saveState(vm, err); + if (!err.fatal) { + stateSaved = true; + //update which areas are available to user + //which may have changed due to state being saved (saveState sets the current islocked value) + updateRights(vm); + } } //############# DELETE GRAPH ############### //NOTE: Plan is delete from bottom up //SCHEDULED USERS - if (noProblem) { - noProblem = await deleteScheduledUsers(vm); + if (!err.fatal) { + err = await deleteScheduledUsers(vm, err); } //todo: other grandchildren //WOITEMS - if (noProblem) { - noProblem = await deleteItems(vm); + if (!err.fatal) { + err = await deleteItems(vm, err); } //############ SAVE GRAPH ############### //NOTE: Plan is save from top down //HEADER - if (noProblem && !headerSaved) { - noProblem = await saveHeader(vm); + if (!err.fata && !headerSaved) { + err = await saveHeader(vm, err); } //WOITEMS - if (noProblem) { + if (!err.fatal) { //This saves all bottom level collections as well - noProblem = await saveItems(vm); + err = await saveItems(vm, err); } //### STATE last normally //in case it locks or is completed - if (!stateSaved && noProblem) { - noProblem = await saveState(vm); - updateRights(vm); + if (!err.fatal && !stateSaved) { + err = await saveState(vm, err); + if (!err.fatal) { + updateRights(vm); + } } - //## ALL PARTIAL UPDATES SUCCEEDED - if (!noProblem) { - //this assumes error is already displayed from save op + //## ALL PARTIAL UPDATES COMPLETED + //todo: walk the err object extract errors and set for display HERE regardless if fatal or not + //todo: how to proceed? + //if it's a post and partially successful then what? + //samesies, if the post partially succeeded that means at least the header succeeded because nothing else would + //so nothing need be done other than route will show weird (0) in address bar, but object is consistent since + //the concurrency and id would be set on the header + //if its' an update easier to just display and bail otu + + if (err.fatal) { + //save failed fataly so just set the state and bail out window.$gz.form.setFormState({ vm: vm, dirty: true, @@ -593,9 +621,9 @@ export default { ///////////////////////////// // HEADER // -async function saveHeader(vm) { +async function saveHeader(vm, err) { if (!vm.obj.isDirty) { - return true; + return err; } const isPost = vm.obj.id == 0; @@ -606,8 +634,12 @@ async function saveHeader(vm) { let res = await window.$gz.api.upsert(`${API_BASE_URL}`, headerOnly); if (res.error) { - displayResError(vm, res); - return false; + if (isPost) { + err.fatal = true; + } + err.header = res.error; + err.error = true; + return err; } else { //update any server changed fields vm.obj.concurrency = res.data.concurrency; @@ -619,18 +651,18 @@ async function saveHeader(vm) { vm.obj.states.forEach(z => (z.workOrderId = vm.obj.id)); vm.obj.items.forEach(z => (z.workOrderId = vm.obj.id)); } - return true; + return err; } } ///////////////////////////// // STATES // -async function saveState(vm) { +async function saveState(vm, err) { //CHANGED? let totalItems = vm.obj.states.length; if (totalItems == 0) { - return true; + return err; } for (let i = 0; i < totalItems; i++) { let o = vm.obj.states[i]; @@ -638,8 +670,8 @@ async function saveState(vm) { //it's new so save it let res = await window.$gz.api.upsert(`${API_BASE_URL}states`, o); if (res.error) { - displayResError(vm, res); - return false; + err.states.push(res.error); + err.error = true; } else { vm.obj.states[i] = res.data; @@ -648,25 +680,29 @@ async function saveState(vm) { } } } - return true; + return err; } ///////////////////////////// // ITEMS // -async function deleteItems(vm) { - while (vm.deletedGraphItems.items.length) { +async function deleteItems(vm, err) { + if (vm.deletedGraphItems.items.length == 0) { + return err; + } + //walk the array backwards as items may or may not be spliced out + for (var i = vm.deletedGraphItems.items.length - 1; i >= 0; i--) { let res = await window.$gz.api.remove( `${API_BASE_URL}items/${vm.deletedGraphItems.items[0]}` ); if (res.error) { - displayResError(vm, res); - return false; + err.items.push(res.error); + err.error = true; } else { - vm.deletedGraphItems.items.splice(0, 1); + vm.deletedGraphItems.items.splice(i, 1); } + return err; } - return true; } async function saveItems(vm) { let totalItems = vm.obj.items.length; @@ -693,10 +729,16 @@ async function saveItems(vm) { const isPost = o.id == 0; let res = await window.$gz.api.upsert(`${API_BASE_URL}items`, o); if (res.error) { - displayResError(vm, res); - return false; + err.items.push(res.error); + err.error = true; + if (isPost) { + //a post error precludes further operations on this item below + //however, an update error doesn't necessarily because it's still a existing workorder item + //so it's children can probably be updated and we want that + continue; + } } else { - //update any server changed fields + //no error so update any server changed fields //put fields vm.obj.items[i].concurrency = res.data.concurrency; vm.obj.items[i].isDirty = false; @@ -717,13 +759,14 @@ async function saveItems(vm) { } //------ //save grandchildren - if (!(await saveScheduledUsers(vm, i))) { - return false; + err = await saveScheduledUsers(vm, i.err); + if (err.fatal) { + return err; } + //todo: other grandchildren //------ - // console.log("Bottom of items loop", { totalItems: totalItems, i: i }); } - return true; //made it through + return err; //made it through } //#################################################################################### //## GRANDCHILDREN @@ -731,19 +774,21 @@ async function saveItems(vm) { ///////////////////////////// // SCHEDULED USERS // -async function deleteScheduledUsers(vm) { - while (vm.deletedGraphItems.scheduledUsers.length) { +async function deleteScheduledUsers(vm, err) { + //walk the array backwards as items may or may not be spliced out + for (var i = vm.deletedGraphItems.scheduledUsers.length - 1; i >= 0; i--) { + // while (vm.deletedGraphItems.scheduledUsers.length) { let res = await window.$gz.api.remove( `${API_BASE_URL}items/scheduledusers/${vm.deletedGraphItems.scheduledUsers[0]}` ); if (res.error) { - displayResError(vm, res); - return false; + err.items.push(res.error); + err.error = true; } else { - vm.deletedGraphItems.scheduledUsers.splice(0, 1); + vm.deletedGraphItems.scheduledUsers.splice(i, 1); } } - return true; + return err; } async function saveScheduledUsers(vm, woitemindex) { @@ -781,14 +826,14 @@ async function saveScheduledUsers(vm, woitemindex) { //todo: other grandchildren -///////////////////////////// -// Error display -// -function displayResError(vm, res) { - console.log("DISPLAY RES ERROR: ", res); - vm.formState.serverError = res.error; - window.$gz.form.setErrorBoxErrors(vm); -} +// ///////////////////////////// +// // Error display +// // +// function displayResError(vm, res) { +// console.log("DISPLAY RES ERROR: ", res); +// vm.formState.serverError = res.error; +// window.$gz.form.setErrorBoxErrors(vm); +// } //######################################### UTILITY METHODS ########################################### /////////////////////////////