chain supermarket create/update to include categories

This commit is contained in:
smilerz
2021-09-27 17:55:58 -05:00
parent 1d983d7310
commit c1a22ea2a6
14 changed files with 101 additions and 62 deletions

View File

@ -237,6 +237,7 @@ export default {
case this.Actions.UPDATE:
update = e.form_data
update.id = this.this_item.id
console.log('form', update)
this.saveThis(update)
break;
case this.Actions.MERGE:
@ -285,11 +286,7 @@ export default {
})
} else {
this.genericAPI(this.this_model, this.Actions.UPDATE, thisItem).then((result) => {
// using form data to refresh the card
// when there are complicated functions (SuperMarket Relations) the actions don't
// always complete first. TODO: wrap all that in a Promise and wait for it to complete before using refreshThis instead
this.refreshCard(thisItem, this.items_left)
this.refreshCard({...thisItem}, this.items_right)
this.refreshThis(thisItem.id)
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_UPDATE)
}).catch((err) => {
console.log(err, err.response)

View File

@ -284,9 +284,14 @@ export class Models {
},
},
'config': {
'category_to_supermarket': {'function': 'handleSuperMarketCategory'}
'function': 'SupermarketWithCategories',
}
},
'partialUpdate': {
'config': {
'function': 'SupermarketWithCategories',
}
}
}
static AUTOMATION = {

View File

@ -176,31 +176,11 @@ export const ApiMixin = {
methods: {
genericAPI: function(model, action, options) {
let setup = getConfig(model, action)
if (setup?.config?.function) {
return specialCases[setup.config.function](action, options, setup)
}
let func = setup.function
let config = setup?.config ?? {}
let params = setup?.params ?? []
let parameters = []
let this_value = undefined
params.forEach(function (item, index) {
if (Array.isArray(item)) {
this_value = {}
// if the value is an array, convert it to a dictionary of key:value
// filtered based on OPTIONS passed
// maybe map/reduce is better?
for (const [k, v] of Object.entries(options)) {
if (item.includes(k)) {
this_value[k] = formatParam(config?.[k], v, options)
}
}
} else {
this_value = formatParam(config?.[item], options?.[item] ?? undefined, options)
}
// if no value is found so far, get the default if it exists
if (this_value === undefined) {
this_value = getDefault(config?.[item], options)
}
parameters.push(this_value)
});
let parameters = buildParams(options, setup)
let apiClient = new ApiApiFactory()
return apiClient[func](...parameters)
},
@ -248,6 +228,33 @@ function formatParam(config, value, options) {
}
return value
}
function buildParams(options, setup) {
let config = setup?.config ?? {}
let params = setup?.params ?? []
let parameters = []
let this_value = undefined
params.forEach(function (item, index) {
if (Array.isArray(item)) {
this_value = {}
// if the value is an array, convert it to a dictionary of key:value
// filtered based on OPTIONS passed
// maybe map/reduce is better?
for (const [k, v] of Object.entries(options)) {
if (item.includes(k)) {
this_value[k] = formatParam(config?.[k], v, options)
}
}
} else {
this_value = formatParam(config?.[item], options?.[item] ?? undefined, options)
}
// if no value is found so far, get the default if it exists
if (this_value === undefined) {
this_value = getDefault(config?.[item], options)
}
parameters.push(this_value)
});
return parameters
}
function getDefault(config, options) {
let value = undefined
value = config?.default ?? undefined
@ -429,29 +436,59 @@ export const CardMixin = {
const specialCases = {
handleSuperMarketCategory: function(updatedRelationships, supermarket) {
let API = ApiMixin.methods.genericAPI
if (updatedRelationships.length === 0) {
return
// the supermarket API requires chaining promises together, instead of trying to make
// this use case generic just treat it as a unique use case
SupermarketWithCategories: function(action, options, setup) {
let API = undefined
let GenericAPI = ApiMixin.methods.genericAPI
let params = []
if (action.function === 'partialUpdate') {
API = GenericAPI
params = [Models.SUPERMARKET, Actions.FETCH, {'id': options.id}]
} else if (action.function === 'create') {
API = new ApiApiFactory()[setup.function]
params = buildParams(options, setup)
}
// get current relationship mappings
API(Models.SUPERMARKET, Actions.FETCH, {'id': supermarket.id}).then((result) => {
let currentRelationships = result.data.category_to_supermarket
let removed = currentRelationships.map(x => x.id).filter(x => !updatedRelationships.map(x => x.id).includes(x))
removed.forEach(x => {
API(Models.SHOPPING_CATEGORY_RELATION, Actions.DELETE, {'id': x})//.then((result)=> console.log('delete', result))
return API(...params).then((result) => {
// either get the supermarket or create the supermarket (but without the category relations)
return result.data
}).then((result) => {
// delete, update or change all of the category/relations
let id = result.id
let existing_categories = result.category_to_supermarket
let updated_categories = options.category_to_supermarket
let promises = []
// if the 'category.name' key does not exist on the updated_categories, the categories were not updated
if (updated_categories?.[0]?.category?.name) {
// list of category relationship ids that are not part of the updated supermarket
let removed_categories = existing_categories.filter(x => !updated_categories.map(x => x.category.id).includes(x.category.id))
let added_categories = updated_categories.filter(x => !existing_categories.map(x => x.category.id).includes(x.category.id))
let changed_categories = updated_categories.filter(x => existing_categories.map(x => x.category.id).includes(x.category.id))
removed_categories.forEach(x => {
promises.push(GenericAPI(Models.SHOPPING_CATEGORY_RELATION, Actions.DELETE, {'id': x.id}))
})
let item = {'supermarket': id}
added_categories.forEach(x => {
item.order = x.order
item.category = {'id': x.category.id, 'name': x.category.name}
promises.push(GenericAPI(Models.SHOPPING_CATEGORY_RELATION, Actions.CREATE, item))
})
changed_categories.forEach(x => {
item.id = x?.id ?? existing_categories.find(y => y.category.id === x.category.id).id;
item.order = x.order
item.category = {'id': x.category.id, 'name': x.category.name}
promises.push(GenericAPI(Models.SHOPPING_CATEGORY_RELATION, Actions.UPDATE, item))
})
}
return Promise.all(promises).then(() => {
// finally get and return the Supermarket which everything downstream is expecting
return GenericAPI(Models.SUPERMARKET, Actions.FETCH, {'id': id})
})
let item = {'supermarket': supermarket.id}
updatedRelationships.forEach(x => {
item.order = x.order
item.category = {'id': x.category.id, 'name': x.category.name}
if (x.id) {
item.id = x.id
API(Models.SHOPPING_CATEGORY_RELATION, Actions.UPDATE, item)//.then((result)=> console.log('update', result))
} else {
API(Models.SHOPPING_CATEGORY_RELATION, Actions.CREATE, item)//.then((result)=> console.log('create', result))
}
})
})
})
}
}