feat: Add number format value (#519)
* feat: First change, add country and currency * add support to currency prefix or sufix. * fixpull/3759/head
							parent
							
								
									0800511177
								
							
						
					
					
						commit
						e5fa066938
					
				| 
						 | 
				
			
			@ -1,6 +1,13 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <el-tooltip v-model="isShowed" :manual="true" :content="valueToDisplay" placement="top" effect="light">
 | 
			
		||||
  <el-tooltip
 | 
			
		||||
    v-model="isShowed"
 | 
			
		||||
    manual
 | 
			
		||||
    :content="valueToDisplay"
 | 
			
		||||
    placement="top"
 | 
			
		||||
    effect="light"
 | 
			
		||||
  >
 | 
			
		||||
    <el-input-number
 | 
			
		||||
      v-if="isFocus"
 | 
			
		||||
      :ref="metadata.columnName"
 | 
			
		||||
      v-model="value"
 | 
			
		||||
      type="number"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,17 +20,31 @@
 | 
			
		|||
      :controls-position="controlsPosition"
 | 
			
		||||
      :class="cssClassStyle"
 | 
			
		||||
      @change="preHandleChange"
 | 
			
		||||
      @blur="focusLost"
 | 
			
		||||
      @blur="customFocusLost"
 | 
			
		||||
      @focus="focusGained"
 | 
			
		||||
      @keydown.native="keyPressed"
 | 
			
		||||
      @keyup.native="keyReleased"
 | 
			
		||||
    />
 | 
			
		||||
    <el-input
 | 
			
		||||
      v-else
 | 
			
		||||
      :ref="metadata.columnName"
 | 
			
		||||
      v-model="displayedValue"
 | 
			
		||||
      :placeholder="metadata.help"
 | 
			
		||||
      :disabled="isDisabled"
 | 
			
		||||
      :precision="precision"
 | 
			
		||||
      :class="'display-type-amount ' + metadata.cssClassName"
 | 
			
		||||
      readonly
 | 
			
		||||
      @blur="customFocusLost"
 | 
			
		||||
      @focus="customFocusGained"
 | 
			
		||||
      @keydown.native="keyPressed"
 | 
			
		||||
      @keyup.native="keyReleased"
 | 
			
		||||
    />
 | 
			
		||||
  </el-tooltip>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
 | 
			
		||||
import { FIELDS_DECIMALS } from '@/utils/ADempiere/references'
 | 
			
		||||
import { FIELDS_CURRENCY, FIELDS_DECIMALS } from '@/utils/ADempiere/references'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'FieldNumber',
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +52,7 @@ export default {
 | 
			
		|||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      showControls: true,
 | 
			
		||||
      isFocus: false,
 | 
			
		||||
      operation: '',
 | 
			
		||||
      expression: /[\d\/.()%\*\+\-]/gim,
 | 
			
		||||
      valueToDisplay: '',
 | 
			
		||||
| 
						 | 
				
			
			@ -55,8 +77,8 @@ export default {
 | 
			
		|||
    },
 | 
			
		||||
    precision() {
 | 
			
		||||
      // Amount, Costs+Prices, Number
 | 
			
		||||
      if (FIELDS_DECIMALS.includes(this.metadata.displayType)) {
 | 
			
		||||
        return 2
 | 
			
		||||
      if (this.isDecimal) {
 | 
			
		||||
        return this.currencyDefinition.stdPrecision
 | 
			
		||||
      }
 | 
			
		||||
      return undefined
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +99,61 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
      // show right controls
 | 
			
		||||
      return 'right'
 | 
			
		||||
    },
 | 
			
		||||
    isDecimal() {
 | 
			
		||||
      return FIELDS_DECIMALS.includes(this.metadata.displayType)
 | 
			
		||||
    },
 | 
			
		||||
    isCurrency() {
 | 
			
		||||
      return FIELDS_CURRENCY.includes(this.metadata.displayType)
 | 
			
		||||
    },
 | 
			
		||||
    displayedValue() {
 | 
			
		||||
      let value = this.value
 | 
			
		||||
      if (this.isEmptyValue(value)) {
 | 
			
		||||
        value = 0
 | 
			
		||||
      }
 | 
			
		||||
      if (!this.isDecimal) {
 | 
			
		||||
        return value
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      let options = {
 | 
			
		||||
        useGrouping: true,
 | 
			
		||||
        minimumIntegerDigits: 1,
 | 
			
		||||
        minimumFractionDigits: this.precision,
 | 
			
		||||
        maximumFractionDigits: this.precision
 | 
			
		||||
      }
 | 
			
		||||
      let lang
 | 
			
		||||
      if (this.isCurrency) {
 | 
			
		||||
        lang = this.countryLanguage
 | 
			
		||||
        options = {
 | 
			
		||||
          ...options,
 | 
			
		||||
          style: 'currency',
 | 
			
		||||
          currency: this.currencyCode
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // TODO: Check the grouping of thousands
 | 
			
		||||
      const formatterInstance = new Intl.NumberFormat(lang, options)
 | 
			
		||||
      return formatterInstance.format(value)
 | 
			
		||||
    },
 | 
			
		||||
    countryLanguage() {
 | 
			
		||||
      return this.$store.getters['user/getCountryLanguage']
 | 
			
		||||
    },
 | 
			
		||||
    currencyCode() {
 | 
			
		||||
      return this.currencyDefinition.iSOCode
 | 
			
		||||
    },
 | 
			
		||||
    currencyDefinition() {
 | 
			
		||||
      return this.$store.getters['user/getCurrency']
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    isFocus(value) {
 | 
			
		||||
      if (value) {
 | 
			
		||||
        // focus into input number
 | 
			
		||||
        this.$nextTick()
 | 
			
		||||
          .then(() => {
 | 
			
		||||
            this.$refs[this.metadata.columnName].$el.children[2].firstElementChild.focus()
 | 
			
		||||
          })
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +163,14 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
      return Number(value)
 | 
			
		||||
    },
 | 
			
		||||
    customFocusGained(event) {
 | 
			
		||||
      this.isFocus = true
 | 
			
		||||
      // this.focusGained(event)
 | 
			
		||||
    },
 | 
			
		||||
    customFocusLost(event) {
 | 
			
		||||
      this.isFocus = false
 | 
			
		||||
      // this.focusLost(event)
 | 
			
		||||
    },
 | 
			
		||||
    calculateValue(event) {
 | 
			
		||||
      const isAllowed = event.key.match(this.expression)
 | 
			
		||||
      if (isAllowed) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,17 @@
 | 
			
		|||
import { getEntity, getEntitiesList } from '@/api/ADempiere/persistence'
 | 
			
		||||
import { getDefaultValueFromServer, getContextInfoValueFromServer } from '@/api/ADempiere/values'
 | 
			
		||||
import { getPrivateAccessFromServer, lockPrivateAccessFromServer, unlockPrivateAccessFromServer } from '@/api/ADempiere/private-access'
 | 
			
		||||
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
 | 
			
		||||
import {
 | 
			
		||||
  getDefaultValueFromServer,
 | 
			
		||||
  getContextInfoValueFromServer
 | 
			
		||||
} from '@/api/ADempiere/values'
 | 
			
		||||
import {
 | 
			
		||||
  getPrivateAccessFromServer,
 | 
			
		||||
  lockPrivateAccessFromServer,
 | 
			
		||||
  unlockPrivateAccessFromServer
 | 
			
		||||
} from '@/api/ADempiere/private-access'
 | 
			
		||||
import {
 | 
			
		||||
  isEmptyValue,
 | 
			
		||||
  convertArrayPairsToObject
 | 
			
		||||
} from '@/utils/ADempiere/valueUtils.js'
 | 
			
		||||
import { parseContext } from '@/utils/ADempiere/contextUtils'
 | 
			
		||||
import { showMessage } from '@/utils/ADempiere/notification'
 | 
			
		||||
import { TABLE, TABLE_DIRECT } from '@/utils/ADempiere/references'
 | 
			
		||||
| 
						 | 
				
			
			@ -634,11 +644,11 @@ const data = {
 | 
			
		|||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * TODO: Add support to tab children
 | 
			
		||||
     * @param {object} objectParams
 | 
			
		||||
     * @param {string} objectParams.containerUuid
 | 
			
		||||
     * @param {objec}  objectParams.row, new data to change
 | 
			
		||||
     * @param {objec}  objectParams.isEdit, if the row displayed to edit mode
 | 
			
		||||
     * @param {objec}  objectParams.isNew, if insert data to new row
 | 
			
		||||
     * @param {string} parentUuid
 | 
			
		||||
     * @param {string} containerUuid
 | 
			
		||||
     * @param {boolean}  isEdit, if the row displayed to edit mode
 | 
			
		||||
     * @param {boolean}  isNew, if insert data to new row
 | 
			
		||||
     * @param {objec}  row, new data to change
 | 
			
		||||
     */
 | 
			
		||||
    notifyRowTableChange({ commit, getters, rootGetters }, {
 | 
			
		||||
      parentUuid,
 | 
			
		||||
| 
						 | 
				
			
			@ -659,12 +669,16 @@ const data = {
 | 
			
		|||
          isAddDisplayColumn: true
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
      if (Array.isArray(values)) {
 | 
			
		||||
        values = convertArrayPairsToObject({
 | 
			
		||||
          arrayToConvert: values
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const currentRow = getters.getRowData(containerUuid, values.UUID)
 | 
			
		||||
 | 
			
		||||
      const newRow = {
 | 
			
		||||
        ...values,
 | 
			
		||||
        // ...objectParams.row,
 | 
			
		||||
        isEdit
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,12 @@ import {
 | 
			
		|||
  removeCurrentWarehouse,
 | 
			
		||||
  removeCurrentOrganization
 | 
			
		||||
} from '@/utils/auth'
 | 
			
		||||
import { getOrganizationsList, getWarehousesList, listLanguages } from '@/api/ADempiere/system-core'
 | 
			
		||||
import {
 | 
			
		||||
  getCountryDefinition,
 | 
			
		||||
  getOrganizationsList,
 | 
			
		||||
  getWarehousesList,
 | 
			
		||||
  listLanguages
 | 
			
		||||
} from '@/api/ADempiere/system-core'
 | 
			
		||||
import router, { resetRouter } from '@/router'
 | 
			
		||||
import { showMessage } from '@/utils/ADempiere/notification'
 | 
			
		||||
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +40,8 @@ const state = {
 | 
			
		|||
  languagesList: [],
 | 
			
		||||
  warehouse: {},
 | 
			
		||||
  isSession: false,
 | 
			
		||||
  sessionInfo: {}
 | 
			
		||||
  sessionInfo: {},
 | 
			
		||||
  country: {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const mutations = {
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +87,9 @@ const mutations = {
 | 
			
		|||
  setSessionInfo(state, payload) {
 | 
			
		||||
    state.sessionInfo = payload
 | 
			
		||||
  },
 | 
			
		||||
  setCountry(state, payload) {
 | 
			
		||||
    state.country = payload
 | 
			
		||||
  },
 | 
			
		||||
  setLanguagesList: (state, payload) => {
 | 
			
		||||
    state.languagesList = Object.freeze(payload.map(language => {
 | 
			
		||||
      const languageDefinition = {
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +115,22 @@ const actions = {
 | 
			
		|||
        })
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  getCountryFormServer({ commit }, {
 | 
			
		||||
    countryId,
 | 
			
		||||
    countryUuid
 | 
			
		||||
  }) {
 | 
			
		||||
    return new Promise(resolve => {
 | 
			
		||||
      getCountryDefinition({
 | 
			
		||||
        countryId,
 | 
			
		||||
        countryUuid
 | 
			
		||||
      })
 | 
			
		||||
        .then(responseCountry => {
 | 
			
		||||
          commit('setCountry', responseCountry)
 | 
			
		||||
 | 
			
		||||
          resolve(responseCountry)
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  // user login
 | 
			
		||||
  login({ commit }, {
 | 
			
		||||
    userName,
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +200,15 @@ const actions = {
 | 
			
		|||
 | 
			
		||||
          dispatch('getOrganizationsList', role.uuid)
 | 
			
		||||
 | 
			
		||||
          const countryId = parseInt(
 | 
			
		||||
            responseGetInfo.defaultContextMap.get('#C_Country_ID'),
 | 
			
		||||
            10
 | 
			
		||||
          )
 | 
			
		||||
          // get country and currency
 | 
			
		||||
          dispatch('getCountryFormServer', {
 | 
			
		||||
            countryId
 | 
			
		||||
          })
 | 
			
		||||
 | 
			
		||||
          dispatch('getUserInfoFromSession', sessionUuid)
 | 
			
		||||
            .catch(error => {
 | 
			
		||||
              console.warn(`Error ${error.code} getting user info value: ${error.message}.`)
 | 
			
		||||
| 
						 | 
				
			
			@ -410,6 +444,15 @@ const actions = {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
const getters = {
 | 
			
		||||
  getCountry: (state) => {
 | 
			
		||||
    return state.country
 | 
			
		||||
  },
 | 
			
		||||
  getCurrency: (state) => {
 | 
			
		||||
    return state.country.currency
 | 
			
		||||
  },
 | 
			
		||||
  getCountryLanguage(state) {
 | 
			
		||||
    return state.country.language.replace('_', '-')
 | 
			
		||||
  },
 | 
			
		||||
  getLanguagesList: (state) => {
 | 
			
		||||
    return state.languagesList
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,8 @@ export const ACCOUNT_ELEMENT = {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Number
 | 
			
		||||
export const NUMBER = {
 | 
			
		||||
// Amount (Number with 4 decimals)
 | 
			
		||||
export const AMOUNT = {
 | 
			
		||||
  id: 12,
 | 
			
		||||
  isSupported: true,
 | 
			
		||||
  valueType: 'DECIMAL',
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ export const RESOURCE_ASSIGNMENT = {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Binary Data
 | 
			
		||||
// Binary Data (display type BLOB)
 | 
			
		||||
export const BINARY_DATA = {
 | 
			
		||||
  id: 23,
 | 
			
		||||
  isSupported: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -220,7 +220,7 @@ export const ID = {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Binary Image Data
 | 
			
		||||
export const BINARY = {
 | 
			
		||||
export const IMAGE = {
 | 
			
		||||
  id: 32,
 | 
			
		||||
  isSupported: true,
 | 
			
		||||
  valueType: 'INTEGER',
 | 
			
		||||
| 
						 | 
				
			
			@ -310,7 +310,7 @@ export const MEMO = {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Float Number
 | 
			
		||||
export const FLOAT = {
 | 
			
		||||
export const NUMBER = {
 | 
			
		||||
  id: 22,
 | 
			
		||||
  isSupported: true,
 | 
			
		||||
  valueType: 'DECIMAL',
 | 
			
		||||
| 
						 | 
				
			
			@ -525,7 +525,7 @@ export function isLookup(displayType) {
 | 
			
		|||
 */
 | 
			
		||||
const REFERENCES = [
 | 
			
		||||
  ACCOUNT_ELEMENT,
 | 
			
		||||
  NUMBER,
 | 
			
		||||
  AMOUNT,
 | 
			
		||||
  RESOURCE_ASSIGNMENT,
 | 
			
		||||
  BINARY_DATA,
 | 
			
		||||
  BUTTON,
 | 
			
		||||
| 
						 | 
				
			
			@ -538,13 +538,13 @@ const REFERENCES = [
 | 
			
		|||
  LOCAL_FILE_PATH,
 | 
			
		||||
  LOCAL_FILE_PATH_OR_NAME,
 | 
			
		||||
  ID,
 | 
			
		||||
  BINARY,
 | 
			
		||||
  IMAGE,
 | 
			
		||||
  INTEGER,
 | 
			
		||||
  LIST,
 | 
			
		||||
  LOCATION_ADDRESS,
 | 
			
		||||
  LOCATOR_WAREHOUSE,
 | 
			
		||||
  MEMO,
 | 
			
		||||
  FLOAT,
 | 
			
		||||
  NUMBER,
 | 
			
		||||
  PRINTER_NAME,
 | 
			
		||||
  PRODUCT_ATTRIBUTE,
 | 
			
		||||
  QUANTITY,
 | 
			
		||||
| 
						 | 
				
			
			@ -562,15 +562,16 @@ const REFERENCES = [
 | 
			
		|||
export default REFERENCES
 | 
			
		||||
 | 
			
		||||
export const FIELDS_RANGE = [
 | 
			
		||||
  NUMBER,
 | 
			
		||||
  AMOUNT,
 | 
			
		||||
  COSTS_PLUS_PRICES,
 | 
			
		||||
  DATE,
 | 
			
		||||
  DATE_PLUS_TIME,
 | 
			
		||||
  INTEGER,
 | 
			
		||||
  FLOAT,
 | 
			
		||||
  NUMBER,
 | 
			
		||||
  QUANTITY,
 | 
			
		||||
  TIME
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Fields not showed in panel's
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -603,14 +604,24 @@ export const FIELDS_READ_ONLY_FORM = [
 | 
			
		|||
]
 | 
			
		||||
 | 
			
		||||
export const FIELDS_DECIMALS = [
 | 
			
		||||
  AMOUNT.id,
 | 
			
		||||
  COSTS_PLUS_PRICES.id,
 | 
			
		||||
  NUMBER.id,
 | 
			
		||||
  QUANTITY.id
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
export const FIELDS_QUANTITY = [
 | 
			
		||||
  AMOUNT.id,
 | 
			
		||||
  COSTS_PLUS_PRICES.id,
 | 
			
		||||
  INTEGER.id,
 | 
			
		||||
  NUMBER.id,
 | 
			
		||||
  QUANTITY.id
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Manage the currency prefix/sufix in the format to display
 | 
			
		||||
 */
 | 
			
		||||
export const FIELDS_CURRENCY = [
 | 
			
		||||
  AMOUNT.id,
 | 
			
		||||
  COSTS_PLUS_PRICES.id
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import { URL, TEXT, NUMBER, INTEGER, TEXT_LONG, TABLE_DIRECT } from '@/utils/ADempiere/references'
 | 
			
		||||
import { URL, TEXT, AMOUNT, INTEGER, TEXT_LONG, TABLE_DIRECT } from '@/utils/ADempiere/references.js'
 | 
			
		||||
 | 
			
		||||
export default [
 | 
			
		||||
  // URL
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ export default [
 | 
			
		|||
    columnName: 'Amount',
 | 
			
		||||
    definition: {
 | 
			
		||||
      name: 'Amount for it',
 | 
			
		||||
      displayType: NUMBER.id,
 | 
			
		||||
      displayType: AMOUNT.id,
 | 
			
		||||
      readOnlyLogic: '@C_Currency_ID@<>""',
 | 
			
		||||
      handleActionKeyPerformed: true
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue