import { requestCreateEntity, requestUpdateEntity, requestDeleteEntity, rollbackEntity } from '@/api/ADempiere/persistence' import { requestReferencesList } from '@/api/ADempiere/values' import { isEmptyValue, typeValue } from '@/utils/ADempiere/valueUtils.js' import { fieldIsDisplayed } from '@/utils/ADempiere/dictionaryUtils' import { parseContext } from '@/utils/ADempiere/contextUtils' import { showMessage } from '@/utils/ADempiere/notification' import language from '@/lang' import router from '@/router' import { convertObjectToKeyValue } from '@/utils/ADempiere/valueFormat.js' /** * Window Control Vuex Module * Actions to dispatch * @author Edwin Betancourt */ export default { tableActionPerformed({ dispatch, getters }, { field, value }) { if (fieldIsDisplayed(field) && field.isShowedFromUser) { // change action to advanced query on field value is changed in this panel if (router.currentRoute.query.action !== 'advancedQuery') { router.push({ query: { ...router.currentRoute.query, action: 'advancedQuery' } }, () => {}) } const { parentUuid, containerUuid, tabTableName, tabQuery, tabWhereClause } = field let parsedQuery = tabQuery if (!isEmptyValue(parsedQuery) && parsedQuery.includes('@')) { parsedQuery = parseContext({ parentUuid, containerUuid, value: tabQuery, isBooleanToString: true }).value } let parsedWhereClause = tabWhereClause if (!isEmptyValue(parsedWhereClause) && parsedWhereClause.includes('@')) { parsedWhereClause = parseContext({ parentUuid, containerUuid, value: tabWhereClause, isBooleanToString: true }).value } const conditionsList = getters.getParametersToServer({ containerUuid, isEvaluateMandatory: false }) dispatch('getObjectListFromCriteria', { parentUuid, containerUuid, tableName: tabTableName, query: parsedQuery, whereClause: parsedWhereClause, conditionsList }) .catch(error => { console.warn('Error getting Advanced Query (notifyFieldChange):', error.message + '. Code: ', error.code) }) } }, windowActionPerformed({ dispatch, getters }, { field, value }) { const { parentUuid, containerUuid, columnName } = field // get value from store if (isEmptyValue(value)) { value = getters.getValueOfField({ parentUuid, containerUuid, columnName }) } return new Promise((resolve, reject) => { // request callouts dispatch('runCallout', { parentUuid, containerUuid, tableName: field.tableName, columnName, callout: field.callout, oldValue: field.oldValue, valueType: field.valueType, value }) .then(() => { // Context Info dispatch('reloadContextInfo', { field }) // Apply actions for server dispatch('runServerAction', { field, value }) .then(response => resolve(response)) .catch(error => reject(error)) }) }) }, runServerAction({ dispatch, getters, commit }, { field, value }) { return new Promise((resolve, reject) => { // For change options if (fieldIsDisplayed(field)) { commit('addChangeToPersistenceQueue', { ...field, value }) const emptyFields = getters.getFieldsListEmptyMandatory({ containerUuid: field.containerUuid }) if (!isEmptyValue(emptyFields)) { showMessage({ message: language.t('notifications.mandatoryFieldMissing') + emptyFields, type: 'info' }) } else { const recordUuid = getters.getUuidOfContainer(field.containerUuid) dispatch('flushPersistenceQueue', { containerUuid: field.containerUuid, tableName: field.tableName, recordUuid }) .then(response => { resolve(response) if (isEmptyValue(recordUuid)) { const oldRoute = router.app._route router.push({ name: oldRoute.name, params: { ...oldRoute.params }, query: { ...oldRoute.query, action: response.uuid } }, () => {}) } }) .catch(error => reject(error)) } } }) }, reloadContextInfo({ dispatch, getters }, { field }) { // get value from store const value = getters.getValueOfField({ parentUuid: field.parentUuid, containerUuid: field.containerUuid, columnName: field.columnName }) // request context info field if (!isEmptyValue(value) && !isEmptyValue(field.contextInfo) && !isEmptyValue(field.contextInfo.sqlStatement)) { let isSQL = false let sqlStatement = field.contextInfo.sqlStatement if (sqlStatement.includes('@')) { if (sqlStatement.includes('@SQL=')) { isSQL = true } sqlStatement = parseContext({ parentUuid: field.parentUuid, containerUuid: field.containerUuid, columnName: field.columnName, value: sqlStatement, isSQL }).value if (isSQL && typeValue(sqlStatement) === 'OBJECT') { sqlStatement = sqlStatement.query } } const contextInfo = dispatch('getContextInfoValueFromServer', { parentUuid: field.parentUuid, containerUuid: field.containerUuid, contextInfoId: field.contextInfo.id, contextInfoUuid: field.contextInfo.uuid, columnName: field.columnName, sqlStatement }) if (!isEmptyValue(contextInfo) && !isEmptyValue(contextInfo.messageText)) { field.contextInfo.isActive = true field.contextInfo.messageText.msgText = contextInfo.messageText field.contextInfo.messageText.msgTip = contextInfo.messageTip } } }, undoPanelToNew({ dispatch, rootGetters }, { containerUuid }) { const oldAttributes = rootGetters.getColumnNamesAndValues({ containerUuid, propertyName: 'oldValue', isObjectReturn: true, isAddDisplayColumn: true }) dispatch('notifyPanelChange', { containerUuid, newValues: oldAttributes }) }, // createNewEntity({ commit, dispatch, getters, rootGetters }, { // parentUuid, // containerUuid // }) { // return new Promise((resolve, reject) => { // // exists some call to create new record with container uuid // if (getters.getInCreate(containerUuid)) { // return reject({ // error: 0, // message: `In this panel (${containerUuid}) is a create new record in progress` // }) // } // // const { tableName, fieldsList } = rootGetters.getPanel(containerUuid) // // delete key from attributes // const attributesList = rootGetters.getColumnNamesAndValues({ // containerUuid, // propertyName: 'value', // isEvaluateValues: true, // isAddDisplayColumn: false // }) // commit('addInCreate', { // containerUuid, // tableName, // attributesList // }) // requestCreateEntity({ // tableName, // attributesList // }) // .then(createEntityResponse => { // const newValues = createEntityResponse.values // attributesList.forEach(element => { // if (element.columnName.includes('DisplayColumn')) { // newValues[element.columnName] = element.value // } // }) // // showMessage({ // message: language.t('data.createRecordSuccessful'), // type: 'success' // }) // // // update fields with new values // dispatch('notifyPanelChange', { // parentUuid, // containerUuid, // newValues, // isSendToServer: false // }) // dispatch('addNewRow', { // parentUuid, // containerUuid, // isPanelValues: true, // isEdit: false // }) // // // set data log to undo action // const fieldId = fieldsList.find(itemField => itemField.isKey) // dispatch('setDataLog', { // containerUuid, // tableName, // recordId: fieldId.value, // TODO: Verify performance with tableName_ID // recordUuid: newValues.UUID, // eventType: 'INSERT' // }) // // const oldRoute = router.app._route // router.push({ // name: oldRoute.name, // params: { // ...oldRoute.params // }, // query: { // ...oldRoute.query, // action: createEntityResponse.uuid // } // }) // dispatch('tagsView/delView', oldRoute, true) // // resolve({ // data: newValues, // recordUuid: createEntityResponse.uuid, // recordId: createEntityResponse.id, // tableName: createEntityResponse.tableName // }) // }) // .catch(error => { // showMessage({ // message: error.message, // type: 'error' // }) // console.warn(`Create Entity error: ${error.message}.`) // reject(error) // }) // .finally(() => { // commit('deleteInCreate', { // containerUuid, // tableName, // attributesList // }) // }) // }) // }, createEntityFromTable({ commit, dispatch, getters, rootGetters }, { parentUuid, containerUuid, row }) { // exists some call to create new record with container uuid if (getters.getInCreate(containerUuid)) { return { error: 0, message: `In this panel (${containerUuid}) is a create new record in progress.` } } const { tableName, isParentTab } = rootGetters.getPanel(containerUuid) // TODO: Add support to Binary columns (BinaryData) const columnsToDontSend = ['BinaryData', 'isEdit', 'isNew', 'isSendServer'] // TODO: Evaluate peformance without filter using delete(prop) before convert object to array // attributes or fields const fieldsList = getters.getFieldsListFromPanel(containerUuid) const attributesList = [] fieldsList.forEach(itemAttribute => { if (columnsToDontSend.includes(itemAttribute.columnName) || itemAttribute.columnName.includes('DisplayColumn')) { return false } if (isEmptyValue(row[itemAttribute.columnName])) { return false } attributesList.push({ value: row[itemAttribute.columnName], columnName: itemAttribute.columnName, valueType: itemAttribute.valueType }) }) commit('addInCreate', { containerUuid, tableName, attributesList }) let isError = false return requestCreateEntity({ tableName, attributesList }) .then(createEntityResponse => { showMessage({ message: language.t('data.createRecordSuccessful'), type: 'success' }) if (isParentTab) { // redirect to create new record const oldRoute = router.app._route router.push({ name: oldRoute.name, params: { ...oldRoute.params }, query: { ...oldRoute.query, action: createEntityResponse.recordUuid } }, () => {}) } return { data: createEntityResponse.values, ...createEntityResponse } }) .catch(error => { showMessage({ message: error.message, type: 'error' }) console.warn(`Create Entity Table Error ${error.code}: ${error.message}.`) isError = true }) .finally(() => { if (isError) { dispatch('addNewRow', { containerUuid, row }) } else { // refresh record list dispatch('getDataListTab', { parentUuid, containerUuid }) .catch(error => { console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`) }) } commit('deleteInCreate', { containerUuid, tableName, attributesList }) }) }, // updateCurrentEntity({ dispatch, rootGetters }, { // containerUuid, // recordUuid = null // }) { // const panel = rootGetters.getPanel(containerUuid) // if (!recordUuid) { // recordUuid = rootGetters.getUuidOfContainer(containerUuid) // } // // // TODO: Add support to Binary columns (BinaryData) // const columnsToDontSend = ['Account_Acct'] // // // attributes or fields // let finalAttributes = rootGetters.getColumnNamesAndValues({ // containerUuid: containerUuid, // isEvaluatedChangedValue: true // }) // // finalAttributes = finalAttributes.filter(itemAttribute => { // if (columnsToDontSend.includes(itemAttribute.columnName) || itemAttribute.columnName.includes('DisplayColumn')) { // return false // } // const field = panel.fieldsList.find(itemField => itemField.columnName === itemAttribute.columnName) // if (!field || !field.isUpdateable || !field.isDisplayed) { // return false // } // return true // }) // return requestUpdateEntity({ // tableName: panel.tableName, // recordUuid, // attributesList: finalAttributes // }) // .then(updateEntityResponse => { // const newValues = updateEntityResponse.values // // set data log to undo action // // TODO: Verify performance with tableName_ID // let recordId = updateEntityResponse.id // if (isEmptyValue(recordId)) { // recordId = newValues[`${panel.tableName}_ID`] // } // if (isEmptyValue(recordId)) { // const fieldId = panel.fieldsList.find(itemField => itemField.isKey) // recordId = fieldId.value // } // // if (isEmptyValue(recordUuid)) { // recordUuid = updateEntityResponse.uuid // } // if (isEmptyValue(recordUuid)) { // recordUuid = newValues.UUID // } // // dispatch('setDataLog', { // containerUuid, // tableName: panel.tableName, // recordId, // recordUuid, // eventType: 'UPDATE' // }) // if (rootGetters.getShowContainerInfo) { // dispatch('listRecordLogs', { // tableName: panel.tableName, // recordId // }) // } // return newValues // }) // .catch(error => { // showMessage({ // message: error.message, // type: 'error' // }) // console.warn(`Update Entity Error ${error.code}: ${error.message}`) // }) // }, updateCurrentEntityFromTable({ rootGetters }, { containerUuid, row }) { const { tableName, fieldsList } = rootGetters.getPanel(containerUuid) // TODO: Add support to Binary columns (BinaryData) const columnsToDontSend = ['BinaryData', 'isEdit', 'isNew', 'isSendServer'] columnsToDontSend.forEach(appAttribute => { delete row[appAttribute] }) // attributes or fields let finalAttributes = convertObjectToKeyValue({ object: row }) finalAttributes = finalAttributes.filter(itemAttribute => { const { columnName } = itemAttribute if (columnName.includes('DisplayColumn')) { return false } const field = fieldsList.find(itemField => itemField.columnName === columnName) if (!field || !field.isUpdateable || !field.isDisplayed) { return false } return true }) return requestUpdateEntity({ tableName, recordUuid: row.UUID, attributesList: finalAttributes }) .then(response => { return response }) .catch(error => { showMessage({ message: error.message, type: 'error' }) console.warn(`Update Entity Table Error ${error.code}: ${error.message}.`) }) }, /** * Update record after run process associated with window * @param {string} parentUuid * @param {string} containerUuid * @param {object} tab */ updateRecordAfterRunProcess({ dispatch, rootGetters }, { parentUuid, containerUuid, tab }) { const recordUuid = rootGetters.getUuidOfContainer(containerUuid) // get new values dispatch('getEntity', { parentUuid, containerUuid, tableName: tab.tableName, recordUuid }) .then(response => { // update panel if (tab.isParentTab) { dispatch('notifyPanelChange', { parentUuid, containerUuid, newValues: response, isSendCallout: false, isSendToServer: false }) } // update row in table dispatch('notifyRowTableChange', { parentUuid, containerUuid, row: response, isEdit: false }) }) }, deleteEntity({ dispatch, rootGetters }, { parentUuid, containerUuid, recordUuid, recordId, row }) { return new Promise(resolve => { const panel = rootGetters.getPanel(containerUuid) if (!isEmptyValue(row)) { recordUuid = row.UUID recordId = row[`${panel.tableName}_ID`] } requestDeleteEntity({ tableName: panel.tableName, recordUuid, recordId }) .then(responseDeleteEntity => { // refresh record list dispatch('getDataListTab', { parentUuid, containerUuid }) .then(responseDataList => { if (panel.isParentTab) { // if response is void, go to new record if (responseDataList.length <= 0) { dispatch('setDefaultValues', { parentUuid, containerUuid, panelType: 'window', isNewRecord: true }) } else { const oldRoute = router.app._route // else display first record of table in panel router.push({ name: oldRoute.name, params: { ...oldRoute.params }, query: { ...oldRoute.query, action: responseDataList[0].UUID } }, () => {}) } } }) .catch(error => { console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`) }) showMessage({ message: language.t('data.deleteRecordSuccessful'), type: 'success' }) if (isEmptyValue(recordId)) { // TODO: Verify performance with tableName_ID const fieldId = panel.fieldsList.find(itemField => itemField.isKey) recordId = fieldId.value } // set data log to undo action dispatch('setDataLog', { containerUuid, tableName: panel.tableName, recordId, recordUuid, eventType: 'DELETE' }) resolve(responseDeleteEntity) }) .catch(error => { showMessage({ message: language.t('data.deleteRecordError'), type: 'error' }) console.warn(`Delete Entity - Error ${error.message}, Code: ${error.code}.`) }) }) }, /** * Delete selection records in table * @param {string} parentUuid * @param {string} containerUuid * @param {string} tableName * @param {boolean} isParentTab */ deleteSelectionDataList({ dispatch, rootGetters }, { parentUuid, containerUuid, tableName, isParentTab }) { if (isEmptyValue(tableName) || isEmptyValue(isParentTab)) { const tab = rootGetters.getTab(parentUuid, containerUuid) tableName = tab.tableName isParentTab = tab.isParentTab } const allData = rootGetters.getDataRecordAndSelection(containerUuid) let selectionLength = allData.selection.length allData.selection.forEach((record, index) => { // validate if the registry row has no uuid before sending to the server if (isEmptyValue(record.UUID)) { selectionLength = selectionLength - 1 console.warn(`This row does not contain a record with UUID`, record) // refresh record list dispatch('getDataListTab', { parentUuid, containerUuid }) .catch(error => { console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`) }) return } requestDeleteEntity({ tableName, recordUuid: record.UUID }) .then(() => { if (isParentTab) { // redirect to create new record const oldRoute = router.app._route if (record.UUID === oldRoute.query.action) { router.push({ name: oldRoute.name, params: { ...oldRoute.params }, query: { ...oldRoute.query, action: 'create-new' } }, () => {}) // clear fields with default values dispatch('setDefaultValues', { parentUuid, containerUuid }) // delete view with uuid record delete dispatch('tagsView/delView', oldRoute, true) } } if ((index + 1) >= selectionLength) { // refresh record list dispatch('getDataListTab', { parentUuid, containerUuid }) .catch(error => { console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`) }) showMessage({ message: language.t('data.deleteRecordSuccessful'), type: 'success' }) } }) }) }, undoModifyData({ getters }, { containerUuid, recordUuid }) { return rollbackEntity(getters.getDataLog(containerUuid, recordUuid)) .then(response => { return response }) .catch(error => { showMessage({ message: error.message, type: 'error' }) console.warn(`Rollback Entity error: ${error.message}. Code: ${error.code}.`) }) }, setDataLog({ commit }, { containerUuid, tableName, recordId, recordUuid, eventType }) { commit('setDataLog', { containerUuid, tableName, recordId, recordUuid, eventType }) }, /** * Get data to table in tab * @param {string} parentUuid, window to search record data * @param {string} containerUuid, tab to search record data * @param {string} recordUuid, uuid to search * @param {boolean} isRefreshPanel, if main panel is updated with new response data * @param {boolean} isLoadAllRecords, if main panel is updated with new response data */ getDataListTab({ dispatch, rootGetters }, { parentUuid, containerUuid, recordUuid, referenceWhereClause = '', columnName, value, criteria, isAddRecord = false, isLoadAllRecords = false, isRefreshPanel = false, isReference = false, isShowNotification = true }) { const tab = rootGetters.getTab(parentUuid, containerUuid) let parsedQuery = tab.query if (!isEmptyValue(parsedQuery) && parsedQuery.includes('@')) { parsedQuery = parseContext({ parentUuid, containerUuid, value: tab.query, isBooleanToString: true }).value } let parsedWhereClause = tab.whereClause if (!isEmptyValue(parsedWhereClause) && parsedWhereClause.includes('@')) { parsedWhereClause = parseContext({ parentUuid, containerUuid, value: tab.whereClause, isBooleanToString: true }).value } if (isReference) { if (!isEmptyValue(parsedWhereClause)) { parsedWhereClause += ` AND ${referenceWhereClause}` } else { parsedWhereClause += referenceWhereClause } } if (!isEmptyValue(criteria)) { if (!isEmptyValue(parsedWhereClause)) { parsedWhereClause += ` AND ${criteria.whereClause}` } else { parsedWhereClause += criteria.whereClause } } const conditionsList = [] // TODO: evaluate if overwrite values to conditions if (!isLoadAllRecords && tab.isParentTab && !isEmptyValue(tab.tableName) && !isEmptyValue(value)) { conditionsList.push({ columnName, value }) } return dispatch('getObjectListFromCriteria', { parentUuid, containerUuid, tableName: tab.tableName, query: parsedQuery, whereClause: parsedWhereClause, orderByClause: tab.orderByClause, conditionsList, isParentTab: tab.isParentTab, isAddRecord, isShowNotification }) .then(response => { if (isRefreshPanel && !isEmptyValue(recordUuid) && recordUuid !== 'create-new') { const newValues = response.find(itemData => itemData.UUID === recordUuid) if (newValues) { // update fields with values obtained from the server dispatch('notifyPanelChange', { parentUuid, containerUuid, newValues, isSendCallout: false, isSendToServer: false }) } else { // this record is missing (Deleted or the query does not include it) dispatch('setDefaultValues', { parentUuid, containerUuid }) } } return response }) .catch(error => { return error }) .finally(() => { const currentData = rootGetters.getDataRecordAndSelection(containerUuid) const { originalNextPageToken, pageNumber, recordCount } = currentData let nextPage = pageNumber const isAdd = isAddRecord if (originalNextPageToken && isAddRecord) { const pageInToken = originalNextPageToken.substring(originalNextPageToken.length - 2) if (pageInToken === '-1') { isAddRecord = false } if (pageNumber === 1 && recordCount > 50) { nextPage = nextPage + 1 isAddRecord = true } } else { isAddRecord = false } if (recordCount <= 50) { isAddRecord = false } if (isAddRecord) { dispatch('setPageNumber', { parentUuid, containerUuid, pageNumber: nextPage, panelType: 'window', isAddRecord, isShowNotification: false }) } if (isAdd && isAdd !== isAddRecord) { if (tab.isSortTab) { const record = rootGetters.getDataRecordsList(containerUuid) const recordToTab = record .map(itemRecord => { return { ...itemRecord } }) .sort((itemA, itemB) => { return itemA[tab.sortOrderColumnName] - itemB[tab.sortOrderColumnName] }) dispatch('setTabSequenceRecord', recordToTab) } } }) }, /** * Get references asociate to record * @param {string} parentUuid as windowUuid * @param {string} containerUuid * @param {string} tableName * @param {string} recordUuid */ getReferencesListFromServer({ commit, rootGetters }, { parentUuid: windowUuid, containerUuid, tableName, recordUuid }) { if (isEmptyValue(tableName)) { tableName = rootGetters.getTab(windowUuid, containerUuid).tableName } return new Promise(resolve => { requestReferencesList({ windowUuid, tableName, recordUuid }) .then(referenceResponse => { const referencesList = referenceResponse.referencesList.map(item => { return { ...item, recordUuid, type: 'reference' } }) const references = { ...referenceResponse, windowUuid, recordUuid, referencesList } commit('addReferencesList', references) resolve(referenceResponse) }) .catch(error => { console.warn(`References Load Error ${error.code}: ${error.message}.`) }) }) }, setWindowOldRoute({ commit }, oldPath = { path: '', fullPath: '', query: {}}) { commit('setWindowOldRoute', oldPath) }, setTabSequenceRecord({ commit }, record) { commit('setTabSequenceRecord', record) }, /** * Update records in tab sort * @param {string} containerUuid * @param {string} parentUuid */ updateSequence({ state, commit, dispatch, getters, rootGetters }, { parentUuid, containerUuid }) { const { tableName, sortOrderColumnName, sortYesNoColumnName, tabAssociatedUuid } = rootGetters.getTab(parentUuid, containerUuid) const listSequenceToSet = getters.getTabSequenceRecord const recordData = rootGetters.getDataRecordsList(containerUuid) // scrolls through the logs and checks if there is a change to be sent to server recordData.forEach(itemData => { const dataSequence = listSequenceToSet.find(item => item.UUID === itemData.UUID) if (itemData[sortOrderColumnName] === dataSequence[sortOrderColumnName]) { return } const valuesToSend = [{ columnName: sortOrderColumnName, value: dataSequence[sortOrderColumnName] }] if (itemData[sortYesNoColumnName] !== dataSequence[sortYesNoColumnName]) { valuesToSend.push({ columnName: sortYesNoColumnName, value: dataSequence[sortYesNoColumnName] }) } const countRequest = state.totalRequest + 1 commit('setTotalRequest', countRequest) requestUpdateEntity({ tableName, recordUuid: itemData.UUID, attributesList: valuesToSend }) .catch(error => { showMessage({ message: error.message, type: 'error' }) console.warn(`Update Entity Table Error ${error.code}: ${error.message}`) }) .finally(() => { const countResponse = state.totalResponse + 1 commit('setTotalResponse', countResponse) if (state.totalResponse === state.totalRequest) { showMessage({ message: language.t('notifications.updateSuccessfully'), type: 'success' }) dispatch('setShowDialog', { type: 'window', action: undefined }) commit('setTotalRequest', 0) commit('setTotalResponse', 0) dispatch('setRecordSelection', { parentUuid, containerUuid, isLoaded: false }) dispatch('setTabSequenceRecord', []) // refresh record list in table source dispatch('getDataListTab', { parentUuid, containerUuid: tabAssociatedUuid }) .catch(error => { console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`) }) } }) }) } }