Procházet zdrojové kódy

✨ ERP:增加金额计算的四舍五入

YunaiV před 1 rokem
rodič
revize
3308a494c7

+ 127 - 17
src/utils/index.ts

@@ -190,6 +190,56 @@ export const copyValueToTarget = (target: any, source: any) => {
   Object.assign(target, newObj)
 }
 
+/**
+ * 获取链接的参数值
+ * @param key 参数键名
+ * @param urlStr 链接地址,默认为当前浏览器的地址
+ */
+export const getUrlValue = (key: string, urlStr: string = location.href): string => {
+  if (!urlStr || !key) return ''
+  const url = new URL(decodeURIComponent(urlStr))
+  return url.searchParams.get(key) ?? ''
+}
+
+/**
+ * 获取链接的参数值(值类型)
+ * @param key 参数键名
+ * @param urlStr 链接地址,默认为当前浏览器的地址
+ */
+export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => {
+  return toNumber(getUrlValue(key, urlStr))
+}
+
+/**
+ * 构建排序字段
+ * @param prop 字段名称
+ * @param order 顺序
+ */
+export const buildSortingField = ({ prop, order }) => {
+  return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' }
+}
+
+// ========== NumberUtils 数字方法 ==========
+
+/**
+ * 数组求和
+ *
+ * @param values 数字数组
+ * @return 求和结果,默认为 0
+ */
+export const getSumValue = (values: number[]): number => {
+  return values.reduce((prev, curr) => {
+    const value = Number(curr)
+    if (!Number.isNaN(value)) {
+      return prev + curr
+    } else {
+      return prev
+    }
+  }, 0)
+}
+
+// ========== 通用金额方法 ==========
+
 /**
  * 将一个整数转换为分数保留两位小数
  * @param num
@@ -206,6 +256,7 @@ export const formatToFraction = (num: number | string | undefined): string => {
  *
  * @param num 整数
  */
+// TODO @芋艿:看看怎么融合掉
 export const floatToFixed2 = (num: number | string | undefined): string => {
   let str = '0.00'
   if (typeof num === 'undefined') {
@@ -232,6 +283,7 @@ export const floatToFixed2 = (num: number | string | undefined): string => {
  * 将一个分数转换为整数
  * @param num
  */
+// TODO @芋艿:看看怎么融合掉
 export const convertToInteger = (num: number | string | undefined): number => {
   if (typeof num === 'undefined') return 0
   const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
@@ -266,31 +318,89 @@ export const calculateRelativeRate = (value?: number, reference?: number) => {
   return ((100 * ((value || 0) - reference)) / reference).toFixed(0)
 }
 
+// ========== ERP 专属方法 ==========
+
+const ERP_COUNT_DIGIT = 3
+const ERP_PRICE_DIGIT = 2
+
 /**
- * 获取链接的参数值
- * @param key 参数键名
- * @param urlStr 链接地址,默认为当前浏览器的地址
+ * 【ERP】格式化 Input 数字
+ *
+ * 例如说:库存数量
+ *
+ * @param num 数量
+ * @return 格式化后的数量
  */
-export const getUrlValue = (key: string, urlStr: string = location.href): string => {
-  if (!urlStr || !key) return ''
-  const url = new URL(decodeURIComponent(urlStr))
-  return url.searchParams.get(key) ?? ''
+export const erpNumberFormatter = (num: number | string | undefined, digit: number) => {
+  if (num === null) {
+    return ''
+  }
+  if (typeof num === 'string') {
+    num = parseFloat(num)
+  }
+  // 如果非 number,则直接返回空串
+  if (isNaN(num)) {
+    return ''
+  }
+  return num.toFixed(digit)
 }
 
 /**
- * 获取链接的参数值(值类型)
- * @param key 参数键名
- * @param urlStr 链接地址,默认为当前浏览器的地址
+ * 【ERP】格式化数量,保留三位小数
+ *
+ * 例如说:库存数量
+ *
+ * @param num 数量
+ * @return 格式化后的数量
  */
-export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => {
-  return toNumber(getUrlValue(key, urlStr))
+export const erpCountInputFormatter = (num: number | string | undefined) => {
+  return erpNumberFormatter(num, ERP_COUNT_DIGIT)
 }
 
+// noinspection JSCommentMatchesSignature
 /**
- * 构建排序字段
- * @param prop 字段名称
- * @param order 顺序
+ * 【ERP】格式化数量,保留三位小数
+ *
+ * @param cellValue 数量
+ * @return 格式化后的数量
  */
-export const buildSortingField = ({ prop, order }) => {
-  return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' }
+export const erpCountTableColumnFormatter = (_, __, cellValue: any, ___) => {
+  return erpNumberFormatter(cellValue, ERP_COUNT_DIGIT)
+}
+
+/**
+ * 【ERP】格式化金额,保留二位小数
+ *
+ * 例如说:库存数量
+ *
+ * @param num 数量
+ * @return 格式化后的数量
+ */
+export const erpPriceInputFormatter = (num: number | string | undefined) => {
+  return erpNumberFormatter(num, ERP_PRICE_DIGIT)
+}
+
+// noinspection JSCommentMatchesSignature
+/**
+ * 【ERP】格式化金额,保留二位小数
+ *
+ * @param cellValue 数量
+ * @return 格式化后的数量
+ */
+export const erpPriceTableColumnFormatter = (_, __, cellValue: any, ___) => {
+  return erpNumberFormatter(cellValue, ERP_PRICE_DIGIT)
+}
+
+/**
+ * 【ERP】价格计算,四舍五入保留两位小数
+ *
+ * @param price 价格
+ * @param count 数量
+ * @return 总价格。如果有任一为空,则返回 undefined
+ */
+export const erpPriceMultiply = (price: number, count: number) => {
+  if (price == null || count == null) {
+    return undefined
+  }
+  return parseFloat((price * count).toFixed(ERP_PRICE_DIGIT))
 }

+ 42 - 12
src/views/erp/stock/in/components/StockInItemForm.vue

@@ -8,7 +8,7 @@
     :inline-message="true"
     :disabled="disabled"
   >
-    <el-table :data="formData" show-summary class="-mt-10px">
+    <el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
       <el-table-column label="序号" type="index" align="center" width="60" />
       <el-table-column label="仓库名称" min-width="125">
         <template #default="{ row, $index }">
@@ -55,7 +55,7 @@
       <el-table-column label="库存" min-width="100">
         <template #default="{ row }">
           <el-form-item class="mb-0px!">
-            <el-input disabled v-model="row.stockCount" />
+            <el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" />
           </el-form-item>
         </template>
       </el-table-column>
@@ -73,13 +73,14 @@
           </el-form-item>
         </template>
       </el-table-column>
-      <el-table-column label="数量" prop="count" fixed="right" min-width="120">
+      <el-table-column label="数量" prop="count" fixed="right" min-width="140">
         <template #default="{ row, $index }">
           <el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
             <el-input-number
               v-model="row.count"
               controls-position="right"
-              :min="1"
+              :min="0.001"
+              :precision="3"
               class="!w-100%"
             />
           </el-form-item>
@@ -92,7 +93,13 @@
             :rules="formRules.productPrice"
             class="mb-0px!"
           >
-            <el-input-number v-model="row.productPrice" controls-position="right" :min="1" />
+            <el-input-number
+              v-model="row.productPrice"
+              controls-position="right"
+              :min="0.01"
+              :precision="2"
+              class="!w-100%"
+            />
           </el-form-item>
         </template>
       </el-table-column>
@@ -103,7 +110,7 @@
             :rules="formRules.totalPrice"
             class="mb-0px!"
           >
-            <el-input disabled v-model="row.totalPrice" />
+            <el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" />
           </el-form-item>
         </template>
       </el-table-column>
@@ -129,6 +136,13 @@
 import { ProductApi, ProductVO } from '@/api/erp/product/product'
 import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
 import { StockApi } from '@/api/erp/stock/stock'
+import {
+  erpCountInputFormatter,
+  erpPriceInputFormatter,
+  erpPriceMultiply,
+  getSumValue
+} from '@/utils'
+import { fenToYuanFormat } from '@/utils/formatter'
 
 const props = defineProps<{
   items: undefined
@@ -166,17 +180,33 @@ watch(
     }
     // 循环处理
     val.forEach((item) => {
-      // TODO 芋艿:后面处理下相乘问题;包括后端的;
-      if (item.productPrice && item.count) {
-        item.totalPrice = item.productPrice * item.count
-      } else {
-        item.totalPrice = undefined
-      }
+      item.totalPrice = erpPriceMultiply(item.productPrice, item.count)
     })
   },
   { deep: true }
 )
 
+/** 合计 */
+const getSummaries = (param: SummaryMethodProps) => {
+  const { columns, data } = param
+  const sums: string[] = []
+  columns.forEach((column, index) => {
+    if (index === 0) {
+      sums[index] = '合计'
+      return
+    }
+    if (['count', 'totalPrice'].includes(column.property)) {
+      const sum = getSumValue(data.map((item) => Number(item[column.property])))
+      sums[index] =
+        column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
+    } else {
+      sums[index] = ''
+    }
+  })
+
+  return sums
+}
+
 /** 新增按钮操作 */
 const handleAdd = () => {
   const row = {

+ 16 - 5
src/views/erp/stock/in/index.vue

@@ -157,12 +157,22 @@
         label="入库时间"
         align="center"
         prop="inTime"
-        :formatter="dateFormatter"
-        width="180px"
+        :formatter="dateFormatter2"
+        width="120px"
       />
       <el-table-column label="创建人" align="center" prop="creatorName" />
-      <el-table-column label="数量" align="center" prop="totalCount" />
-      <el-table-column label="金额" align="center" prop="totalPrice" />
+      <el-table-column
+        label="数量"
+        align="center"
+        prop="totalCount"
+        :formatter="erpCountTableColumnFormatter"
+      />
+      <el-table-column
+        label="金额"
+        align="center"
+        prop="totalPrice"
+        :formatter="erpPriceTableColumnFormatter"
+      />
       <el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
@@ -229,7 +239,7 @@
 
 <script setup lang="ts">
 import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
-import { dateFormatter } from '@/utils/formatTime'
+import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
 import download from '@/utils/download'
 import { StockInApi, StockInVO } from '@/api/erp/stock/in'
 import StockInForm from './StockInForm.vue'
@@ -239,6 +249,7 @@ import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
 import { UserVO } from '@/api/system/user'
 import * as UserApi from '@/api/system/user'
 import * as BusinessApi from '@/api/crm/business'
+import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
 
 /** ERP 其它入库单 列表 */
 defineOptions({ name: 'ErpStockIn' })