cqp 1 周之前
父节点
当前提交
d876320e00
共有 3 个文件被更改,包括 181 次插入2 次删除
  1. 66 2
      app/Service/Service.php
  2. 23 0
      app/Service/StatisticsService.php
  3. 92 0
      config/header/77.php

+ 66 - 2
app/Service/Service.php

@@ -791,9 +791,10 @@ class Service
     /**
      * 用 bcmath 安全执行表达式 (支持 + - * /)
      */
-    public function evaluateWithBCMath($expr, $decimals = 2)
+    public function evaluateWithBCMath1($expr, $decimals = 2)
     {
-        preg_match_all('/(\d+(?:\.\d+)?|[+\/*-])/', $expr, $matches);
+//        preg_match_all('/(\d+(?:\.\d+)?|[+\/*-])/', $expr, $matches);
+        preg_match_all('/(-?\d+(?:\.\d+)?|[+\/*-])/', $expr, $matches);
         $tokens = $matches[0] ?? [];
 
         if (empty($tokens)) return 0;
@@ -835,4 +836,67 @@ class Service
 
         return $result;
     }
+
+    public function evaluateWithBCMath($expr, $decimals = 2)
+    {
+        $calcDecimals = 8; // 中间计算用更高精度
+        // 支持负数和小数
+        preg_match_all('/-?\d+(?:\.\d+)?|[+\/*-]/', $expr, $matches);
+        $tokens = $matches[0] ?? [];
+
+        if (empty($tokens)) return '0';
+
+        // Shunting-yard 算法转换为逆波兰表达式 (RPN)
+        $output = [];
+        $ops = [];
+        $precedence = ['+' => 1, '-' => 1, '*' => 2, '/' => 2];
+
+        foreach ($tokens as $token) {
+            if (is_numeric($token)) {
+                $output[] = (string)$token;
+            } elseif (isset($precedence[$token])) {
+                while (!empty($ops) && $precedence[end($ops)] >= $precedence[$token]) {
+                    $output[] = array_pop($ops);
+                }
+                $ops[] = $token;
+            }
+        }
+        while (!empty($ops)) {
+            $output[] = array_pop($ops);
+        }
+
+        // 计算 RPN
+        $stack = [];
+        foreach ($output as $token) {
+            if (is_numeric($token)) {
+                $stack[] = (string)$token;
+            } else {
+                $b = array_pop($stack) ?? '0';
+                $a = array_pop($stack) ?? '0';
+
+                switch ($token) {
+                    case '+':
+                        $stack[] = bcadd($a, $b, $calcDecimals);
+                        break;
+                    case '-':
+                        $stack[] = bcsub($a, $b, $calcDecimals);
+                        break;
+                    case '*':
+                        $stack[] = bcmul($a, $b, $calcDecimals);
+                        break;
+                    case '/':
+                        if (bccomp($b, '0', $calcDecimals) === 0) {
+                            $stack[] = '0';
+                        } else {
+                            $stack[] = bcdiv($a, $b, $calcDecimals);
+                        }
+                        break;
+                }
+            }
+        }
+
+        $result = array_pop($stack) ?? '0';
+        // 最终统一格式化为指定小数位
+        return bcadd($result, '0', $decimals);
+    }
 }

+ 23 - 0
app/Service/StatisticsService.php

@@ -196,6 +196,29 @@ class StatisticsService extends Service
                 'voucher_type_title' => RevenueCost::$voucher_type[$value['voucher_type']] ?? "",
             ];
         }
+        $footer = $this->countTotal($result, $user['header_default']);
+        $footer['profit_rate'] = $footer['profit_rate'] . "%";
+        $footer = array_merge( [
+            'order_number'        => '',
+            'customer_code'       => '',
+            'customer_title'      => '',
+            'channel_finance'     => '',
+            'product_code'        => '',
+            'product_title'       => '',
+            'product_size'        => '',
+            'unit'                => '',
+            'quantity'            => '',
+            'payment_amount'      => '',
+            'price_1'             => '',
+            'price_1_total'       => '',
+            'price_4'             => '',
+            'price_4_total'       => '',
+            'profit'              => '',
+            'profit_rate'         => '',
+            'customer_profit_rate'=> '',
+            'voucher_type_title'  => '',
+        ], $footer);
+        $detail[] = $footer;
 
         $first = $result[0];
         $order = [

+ 92 - 0
config/header/77.php

@@ -0,0 +1,92 @@
+<?php
+/**
+ * '菜单ID' => [
+ *     '字段英文名' =》 '字段中文名'
+ * ]
+ */
+
+return [
+    [
+        'key' =>'order_number',
+        'value' => '关联单据号',
+    ],
+    [
+        'key' =>'voucher_type_title',
+        'value' => '单据类型',
+    ],
+    [
+        'key' =>'customer_code',
+        'value' => '结算客户编码',
+    ],
+    [
+        'key' =>'customer_title',
+        'value' => '结算客户',
+    ],
+    [
+        'key' =>'channel_finance',
+        'value' => '渠道财务',
+    ],
+    [
+        'key' =>'customer_profit_rate',
+        'value' => '客户毛利率',
+    ],
+    [
+        'key' =>'product_code',
+        'value' => '存货编码',
+    ],
+    [
+        'key' =>'product_title',
+        'value' => '存货名称',
+    ],
+    [
+        'key' =>'product_size',
+        'value' => '规格型号',
+    ],
+    [
+        'key' =>'unit',
+        'value' => '计量单位',
+    ],
+    [
+        'key' =>'quantity',
+        'value' => '开票数量',
+        'sum' => 1,
+    ],
+    [
+        'key' =>'price_1',
+        'value' => '单价',
+    ],
+    [
+        'key' =>'payment_amount',
+        'value' => '回款金额',
+        'sum' => 1,
+    ],
+    [
+        'key' =>'price_1_total',
+        'value' => '开票金额',
+        'sum' => 1,
+    ],
+    [
+        'key' =>'price_4',
+        'value' => '业务成本单价',
+        'sum' => 1,
+    ],
+    [
+        'key' =>'price_4_total',
+        'value' => '业务成本金额',
+        'sum' => 1,
+    ],
+    [
+        'key' =>'profit',
+        'value' => '毛利',
+        'value1' => '回款金额 - 业务成本金额',
+        'sum' => 2,
+        'formula' => 'payment_amount - price_4_total',
+    ],
+    [
+        'key' =>'profit_rate',
+        'value' => '毛利率%',
+        'value1' => '毛利 / 回款金额',
+        'sum' => 2,
+        'formula' => 'profit / payment_amount * 100',
+    ],
+];