unknown 4 дней назад
Родитель
Сommit
0b8c079b2b
1 измененных файлов с 196 добавлено и 45 удалено
  1. 196 45
      application/api/controller/OrderSuperLoss.php

+ 196 - 45
application/api/controller/OrderSuperLoss.php

@@ -194,16 +194,9 @@ class OrderSuperLoss extends Api
         }
         $data['warehousing_num'] = $cp_data[0]['cp_sl'];
         $data['warehousing_date'] = substr($cp_data[0]['jjcp_sj'],0,10);
-        //查出进入超节损的工序,有上报产量的工序就进入超节损
-        $gxh_sql = "SELECT sczl_gxh FROM
-                        (SELECT sczl_gxh FROM 设备_产量计酬 WHERE sczl_gdbh = '{$order}' AND sczl_yjno = '{$params['yjno']}'
-                        UNION SELECT sczl_gxh FROM db_sczl WHERE sczl_gdbh = '{$order}' AND sczl_yjno = '{$params['yjno']}' AND sczl_gxmc like '%拆片%') AS combined_result";
-        $gxh_arr = Db::query($gxh_sql);
-        $gxh_values = array_column($gxh_arr, 'sczl_gxh');
-        foreach ($gxh_values as $k=>$v){
-            if ((int)$v < 10){
-                $gxh_values[$k] = '0'.$v;
-            }
+        $gxh_values = $this->getSuperLossProcessGxhList($order, $params['yjno']);
+        if (empty($gxh_values)) {
+            $this->error('未查询到报工工序');
         }
         $gy_data =db('工单_工艺资料')
             ->alias('a')
@@ -300,10 +293,7 @@ class OrderSuperLoss extends Api
         $data['外发废'] = array_sum($list);//外发废
         $data['工单质检废'] =  array_sum($quality);//质检废
         $data['机检废品'] = array_sum($jijian);
-        $plan_total =db('工单_工艺资料')
-            ->where(['Gy0_gdbh' => $order,'Gy0_yjno' => $params['yjno'], 'Gy0_gxh' => ['in', $gxh_values]])
-            ->where('Gy0_gxmc','NOT LIKE','%检%')
-            ->value('SUM(Gy0_计划损耗 * Gy0_ls * Gy0_ks)');
+        $plan_total = $this->getIntangiblePlanLossTotal($order, $params['yjno'], $gxh_values);
         if($plan_total == 0){
             $this->error('计划损耗数据为 0,请到工单资料管理页面修改工艺资料中选择正确的工序损耗');
             return;
@@ -1079,22 +1069,9 @@ class OrderSuperLoss extends Api
         $data['warehousing_num'] = $total_number[0];
         //截取工单末版的入仓时间
         $data['warehousing_date'] = substr($workOrderData['jjcp_sj'], 0, 10);
-        //从设备产量计酬和sczl查出进入超节损的工序,有上报产量的工序就进入超节损
-        $gxh_sql = "SELECT sczl_gxh FROM
-                        (SELECT sczl_gxh FROM 设备_产量计酬 WHERE sczl_gdbh = '{$workOrderData['jjcp_gdbh']}' AND sczl_yjno = '{$workOrderData['jjcp_yjno']}'
-                        UNION SELECT sczl_gxh FROM db_sczl WHERE sczl_gdbh = '{$workOrderData['jjcp_gdbh']}' AND sczl_yjno = '{$workOrderData['jjcp_yjno']}') AS combined_result";
-        $gxh_arr = Db::query($gxh_sql);
-        if (empty($gxh_arr)) {
+        $gxh_values = $this->getSuperLossProcessGxhList($workOrderData['jjcp_gdbh'], $workOrderData['jjcp_yjno']);
+        if (empty($gxh_values)) {
             $this->error("工单".$workOrderData['jjcp_gdbh']."-".$workOrderData['jjcp_yjno']."未查询到报工信息,请核查该工单是否已进入超节损");
-
-        }
-        //整理查询处理的工序编号
-        $gxh_values = array_column($gxh_arr, 'sczl_gxh');
-        //将工序号小于10的编号前面加0
-        foreach ($gxh_values as $k => $v) {
-            if ((int)$v < 10) {
-                $gxh_values[$k] = '0' . $v;
-            }
         }
         $feedQty = floatval($data['实际投料']) * 10000;
         $realRateVal = $feedQty > 0 ? (floatval($total_number[0]) / $feedQty * 100) : 0;
@@ -1177,13 +1154,16 @@ class OrderSuperLoss extends Api
         $data['外发废'] = array_sum($list);//外发废
         $data['工单质检废'] = array_sum($quality);//质检废
         $data['机检废'] = array_sum($machine);//机检废
-        //查询计划损耗
-        $plan_total = db('工单_工艺资料')
-            ->where(['Gy0_gdbh' => $workOrderData['jjcp_gdbh'], 'Gy0_yjno' => $workOrderData['jjcp_yjno'], 'Gy0_gxh' => ['in', $gxh_values]])
-            ->value('SUM(Gy0_计划损耗 * Gy0_ls * Gy0_ks)');
-        if ($feedQty > 0) {
-            $targetRateVal = ($feedQty - floatval($plan_total)) / $feedQty * 100;
-        }
+        $plan_total = $this->getIntangiblePlanLossTotal(
+            $workOrderData['jjcp_gdbh'],
+            $workOrderData['jjcp_yjno'],
+            $gxh_values
+        );
+        $targetRateVal = $this->calcSuperLossTargetQualificationRate(
+            $workOrderData['jjcp_gdbh'],
+            $workOrderData['jjcp_yjno'],
+            $gxh_values
+        );
         $data['target_rate'] = number_format($targetRateVal, 2) . '%';
         //单据列表最后统计/数据汇总
         $total = [];
@@ -1201,7 +1181,6 @@ class OrderSuperLoss extends Api
                 'a.Gy0_gdbh' => $workOrderData['jjcp_gdbh'],
                 'a.Gy0_yjno' => $workOrderData['jjcp_yjno'],
                 'a.Gy0_gxh' => ['IN', $gxh_values],
-                'b.sczl_cl|c.sczl_cl' => ['>', 0],
             ])
             ->group('a.Gy0_gxh')
             ->order('a.Gy0_gxh')
@@ -1230,12 +1209,17 @@ class OrderSuperLoss extends Api
                 'a.Gy0_gdbh' => $workOrderData['jjcp_gdbh'],
                 'a.Gy0_yjno' => $workOrderData['jjcp_yjno'],
                 'a.Gy0_gxh' => ['in', $gxh_values],
-                'b.sczl_cl|c.sczl_cl' => ['>', 0],
             ])
             ->group('a.Gy0_gxh,b.sczl_jtbh,b.sczl_bh1, CASE WHEN b.sczl_bh2 = "000000" THEN "" ELSE b.sczl_bh2 END, b.sczl_bh3,
                          b.sczl_bh4, b.sczl_bh5, b.sczl_bh6, b.sczl_bh7, b.sczl_bh8, b.sczl_bh9, c.sczl_bh1')
             ->order('a.Gy0_gxh asc, b.开工时间 asc, c.sczl_rq desc')
             ->select();
+        $gy_data = $this->appendMissingSuperLossProcessRows(
+            $gy_data,
+            $gxh_values,
+            $workOrderData['jjcp_gdbh'],
+            $workOrderData['jjcp_yjno']
+        );
         $sumBz = [];
         foreach ($gy_data as $kk => $vv){
             //每道工序的产量(按班组分)
@@ -1273,9 +1257,14 @@ class OrderSuperLoss extends Api
                     $cl = $v['cl'] * $v['Gy0_ls'];
                 }
                 if ($vv['Gy0_yjno'] == $v['Gy0_yjno'] && $vv['Gy0_gxh'] == $v['Gy0_gxh']) {
-                    $gy_data[$kk]['计划损耗'] = round($gy_data[$kk]['total_cl'] / $cl * $vv['Gy0_计划损耗']);
+                    if ($cl > 0) {
+                        $gy_data[$kk]['计划损耗'] = round($gy_data[$kk]['total_cl'] / $cl * $vv['Gy0_计划损耗']);
+                    }
                 }
             }
+            if (empty($gy_data[$kk]['计划损耗'])) {
+                $gy_data[$kk]['计划损耗'] = (int)$vv['Gy0_计划损耗'];
+            }
             //每道工序的制程废品(按班组分)
             $gy_data[$kk]['sczl_zcfp'] = $vv['sczl_zcfp'] * $vv['Gy0_ls'];
             if (empty($vv['sczl_zcfp'])) {
@@ -1303,13 +1292,21 @@ class OrderSuperLoss extends Api
                     }
                 }
             }
-            $gy_data[$kk]['质检废'] = round($gy_data[$kk]['zjfp']*($gy_data[$kk]['total_cl']/$sumBz[$vv['sczl_bh1'].'-'.$vv['Gy0_gxh']]));
-            //无形损分摊
-            if ($plan_total > 0) {
-                $gy_data[$kk]['无形损分摊'] = round($gy_data[$kk]['计划损耗'] / $plan_total * $data['intangible_loss']);
+            $teamKey = $vv['sczl_bh1'] . '-' . $vv['Gy0_gxh'];
+            $teamTotal = $sumBz[$teamKey] ?? 0;
+            if ($teamTotal > 0) {
+                $gy_data[$kk]['质检废'] = round($gy_data[$kk]['zjfp'] * ($gy_data[$kk]['total_cl'] / $teamTotal));
             } else {
-                $gy_data[$kk]['无形损分摊'] = 0;
-            }
+                $gy_data[$kk]['质检废'] = (int)$gy_data[$kk]['zjfp'];
+            }
+            //无形损分摊(分母与按工序打印一致:非检工序计划损耗合计,并考虑无形损承担比例)
+            $gy_data[$kk]['无形损分摊'] = $this->calcTeamIntangibleLossShare(
+                $vv,
+                $gy_data[$kk]['计划损耗'] ?? 0,
+                $gy_data[$kk]['Gy0_计划损耗'] ?? ($vv['Gy0_计划损耗'] ?? 0),
+                $plan_total,
+                floatval($data['intangible_loss'])
+            );
             //班组成员
             for ($j = 1; $j <= 10; $j++) {
                 $bhKey = "sczl_bh" . $j;
@@ -2247,6 +2244,160 @@ class OrderSuperLoss extends Api
      * @throws \think\db\exception\BindParamException
      * @throws \think\exception\PDOException
      */
+    /**
+     * 进入超节损的工序号(产量计酬 + 拆片报工),与 getOrderSuperLossCount 一致
+     */
+    private function getSuperLossProcessGxhList(string $gdbh, string $yjno): array
+    {
+        $sql = "SELECT sczl_gxh FROM (
+                    SELECT sczl_gxh FROM 设备_产量计酬 WHERE sczl_gdbh = ? AND sczl_yjno = ?
+                    UNION
+                    SELECT sczl_gxh FROM db_sczl WHERE sczl_gdbh = ? AND sczl_yjno = ? AND sczl_gxmc LIKE '%拆片%'
+                ) AS combined_result";
+        $gxhArr = Db::query($sql, [$gdbh, $yjno, $gdbh, $yjno]);
+        $gxhValues = array_column($gxhArr, 'sczl_gxh');
+        foreach ($gxhValues as $k => $v) {
+            if ((int)$v < 10) {
+                $gxhValues[$k] = '0' . $v;
+            }
+        }
+
+        return array_values(array_unique(array_filter($gxhValues)));
+    }
+
+    /**
+     * 无形损分摊分母:参与分摊的计划损耗(排除名称含「检」的工序)
+     */
+    private function getIntangiblePlanLossTotal(string $gdbh, string $yjno, array $gxhValues): float
+    {
+        if (empty($gxhValues)) {
+            return 0.0;
+        }
+
+        return floatval(db('工单_工艺资料')
+            ->where(['Gy0_gdbh' => $gdbh, 'Gy0_yjno' => $yjno, 'Gy0_gxh' => ['in', $gxhValues]])
+            ->where('Gy0_gxmc', 'NOT LIKE', '%检%')
+            ->value('SUM(Gy0_计划损耗 * Gy0_ls * Gy0_ks)'));
+    }
+
+    /**
+     * 目标合格率:1 - Σ(工序计划损耗率),与 getOrderSuperLossCount type=1 一致
+     */
+    private function calcSuperLossTargetQualificationRate(string $gdbh, string $yjno, array $gxhValues): float
+    {
+        if (empty($gxhValues)) {
+            return 100.0;
+        }
+
+        $rows = db('工单_工艺资料')
+            ->alias('a')
+            ->field('a.Gy0_计划损耗, a.Gy0_计划接货数 * a.Gy0_ls as Gy0_计划接货数')
+            ->where(['a.Gy0_gdbh' => $gdbh, 'a.Gy0_yjno' => $yjno, 'a.Gy0_gxh' => ['in', $gxhValues]])
+            ->group('a.Gy0_gxh')
+            ->select();
+
+        $arr = [];
+        foreach ($rows as $row) {
+            $denominator = floatval($row['Gy0_计划接货数']);
+            if ($denominator <= 0) {
+                continue;
+            }
+            $rate = round(floatval($row['Gy0_计划损耗']) / $denominator, 5);
+            $arr[] = floor($rate * 10000) / 10000;
+        }
+
+        return empty($arr) ? 100.0 : (1 - array_sum($arr)) * 100;
+    }
+
+    /**
+     * 班组无形损分摊(对齐 type=1 按工序打印逻辑)
+     */
+    private function calcTeamIntangibleLossShare(
+        array $processRow,
+        float $teamPlanLoss,
+        float $processPlanLoss,
+        float $intangiblePlanTotal,
+        float $intangibleLoss
+    ): int {
+        if ($intangiblePlanTotal <= 0 || $intangibleLoss == 0.0) {
+            return 0;
+        }
+
+        $gxName = (string)($processRow['sczl_gxmc'] ?? $processRow['gxmc'] ?? '');
+        if (strpos($gxName, '机检') !== false) {
+            return 0;
+        }
+
+        $planBase = $teamPlanLoss > 0 ? $teamPlanLoss : $processPlanLoss;
+        $ratio = $planBase / $intangiblePlanTotal;
+        $share = $ratio * $intangibleLoss;
+        if (floatval($processRow['无形损承担比例'] ?? 0) > 0) {
+            $share *= floatval($processRow['无形损承担比例']);
+        }
+
+        return (int)round($share);
+    }
+
+    /**
+     * 补全无产量报工、但应参与核算的工序(如外发、拆片等)的单行汇总
+     */
+    private function appendMissingSuperLossProcessRows(
+        array $gyData,
+        array $gxhValues,
+        string $gdbh,
+        string $yjno
+    ): array {
+        $present = [];
+        foreach ($gyData as $row) {
+            $present[(string)$row['Gy0_gxh']] = true;
+        }
+
+        $missing = array_values(array_diff($gxhValues, array_keys($present)));
+        if (empty($missing)) {
+            return $gyData;
+        }
+
+        $processRows = db('工单_工艺资料')
+            ->alias('a')
+            ->field([
+                'a.Gy0_gdbh', 'a.Gy0_yjno', 'a.Gy0_gxh', 'a.Gy0_ls', 'a.Gy0_ks', 'a.Gy0_计划损耗', 'a.超节损承担比例',
+                'CONCAT(`a`.`Gy0_gxmc`, "【", a.Add_gxmc,"】") AS sczl_gxmc',
+                'SUM(b.sczl_zcfp) as sczl_zcfp', 'SUM(b.sczl_cl) as total_cl',
+                'SUM(c.sczl_cl) as cl', 'SUM(c.sczl_fp) as fp',
+                'a.无形损承担比例', 'a.Gy0_Rate0', 'a.Gy0_Rate1', 'a.损耗系数', 'a.Gy0_ms',
+                'a.Gy0_计划接货数*a.Gy0_ls*a.Gy0_ks as 计划产量',
+                'rtrim(a.Gy0_SITE) as Gy0_SITE', 'rtrim(a.印刷方式) as 印刷方式', 'rtrim(a.版距) as 版距',
+                'e.Gd_客户代号', 'e.Gd_客户名称', 'e.Gd_cpdh', 'e.Gd_cpmc', 'e.销售订单号', 'e.投料大箱', 'e.订单数量', 'e.计量单位',
+            ])
+            ->join('设备_产量计酬 b', 'a.Gy0_gdbh = b.sczl_gdbh AND a.Gy0_yjno = b.sczl_yjno AND a.Gy0_gxh = b.sczl_gxh', 'left')
+            ->join('db_sczl c', 'a.Gy0_gdbh = c.sczl_gdbh AND a.Gy0_yjno = c.sczl_yjno AND a.Gy0_gxh = c.sczl_gxh', 'left')
+            ->join('工单_基本资料 e', 'a.Gy0_gdbh = e.Gd_gdbh AND a.Gy0_yjno = e.行号', 'left')
+            ->where(['a.Gy0_gdbh' => $gdbh, 'a.Gy0_yjno' => $yjno, 'a.Gy0_gxh' => ['in', $missing]])
+            ->group('a.Gy0_gxh')
+            ->select();
+
+        foreach ($processRows as $item) {
+            $item['sczl_bh1'] = '';
+            $item['sczl_jtbh'] = '';
+            $item['sczl_bzdh'] = '';
+            for ($j = 1; $j <= 10; $j++) {
+                $item['sczl_bh' . $j] = '';
+                $item['sczl_rate' . $j] = '';
+            }
+            $item['Gd_客户代号'] = $item['Gd_客户代号'] ?? '';
+            $item['Gd_客户名称'] = $item['Gd_客户名称'] ?? '';
+            $item['Gd_cpdh'] = $item['Gd_cpdh'] ?? '';
+            $item['Gd_cpmc'] = $item['Gd_cpmc'] ?? '';
+            $item['销售订单号'] = $item['销售订单号'] ?? '';
+            $item['投料大箱'] = $item['投料大箱'] ?? '';
+            $item['订单数量'] = $item['订单数量'] ?? '';
+            $item['计量单位'] = $item['计量单位'] ?? '';
+            $gyData[] = $item;
+        }
+
+        return $gyData;
+    }
+
     /**
      * 材料费(张数)未超投料 1.5% 时,按目标/实际合格率偏差确定节损金额倍率(边界向下归档)
      */