m0_70156489 1 month ago
parent
commit
864f2cebe8

+ 55 - 25
application/admin/controller/Procuremen.php

@@ -11115,12 +11115,23 @@ class Procuremen extends Backend
                 $logSidList[$sid] = true;
             }
         }
+        if ($logSidList === []) {
+            $this->error('未找到有效工序,无法下发');
+        }
+
+        // 防连点/并发:同一批工序加命名锁,已下发则直接拒绝(避免重复短信邮件)
+        $sidKeys = array_keys($logSidList);
+        sort($sidKeys, SORT_NUMERIC);
+        $pickLockName = 'procuremen_pick_submit_' . md5(implode(',', $sidKeys));
+        if (!$this->acquireProcuremenNamedLock($pickLockName, 15)) {
+            $this->error('下发处理中,请勿重复点击');
+        }
 
         $existingBySid = [];
-        if ($logSidList !== []) {
+        try {
             try {
                 $existingRows = Db::table('purchase_order')
-                    ->where('scydgy_id', 'in', array_keys($logSidList))
+                    ->where('scydgy_id', 'in', $sidKeys)
                     ->select();
                 if (is_array($existingRows)) {
                     foreach ($existingRows as $poRow) {
@@ -11136,34 +11147,53 @@ class Procuremen extends Backend
             } catch (\Throwable $e) {
                 $existingBySid = [];
             }
-        }
 
-        Db::startTrans();
-        try {
-            // ---------- 主表 wflow_status=待确认;明细写入 purchase_order_detail,随后向供应商发短信/邮件 ----------
-            foreach ($mergeRows as $row) {
-                if (!is_array($row)) {
+            foreach ($sidKeys as $sid) {
+                $poRow = $existingBySid[$sid] ?? null;
+                if (!is_array($poRow)) {
                     continue;
                 }
-                $sid = $this->extractScydgyRowId($row);
-                $this->upsertPurchaseOrderFromRow(
-                    $row,
-                    $sysRqDb,
-                    ProcuremenStatus::WFLOW_PENDING_CONFIRM,
-                    $issueTime,
-                    $this->isValidScydgyRowId($sid) ? ($existingBySid[$sid] ?? null) : null,
-                    $deliveryDeadlineDb,
-                    $scoreRule
-                );
-            }
-            foreach ($issueCompanies as $c) {
-                $this->issuePersistSupplierDetails($c, $mergeRows, false, true);
+                if ($this->isPurchaseOrderSoftDeleted($poRow['mod_rq'] ?? null)) {
+                    continue;
+                }
+                $label = $this->formatProcuremenRowLabel(['CCYDH' => $poRow['CCYDH'] ?? '', 'CGYMC' => $poRow['CGYMC'] ?? '']);
+                if (ProcuremenStatus::isPoCompleted($poRow['status'] ?? '')) {
+                    $this->error(($label !== '' ? $label : ('工序#' . $sid)) . '已完结,无法再次下发');
+                }
+                if (!ProcuremenStatus::isWflowPendingIssue($poRow['wflow_status'] ?? '')) {
+                    $this->error(($label !== '' ? $label : ('工序#' . $sid)) . '已下发或进入后续流程,请勿重复提交');
+                }
             }
 
-            Db::commit();
-        } catch (\Throwable $e) {
-            Db::rollback();
-            $this->error($e->getMessage());
+            Db::startTrans();
+            try {
+                // ---------- 主表 wflow_status=待确认;明细写入 purchase_order_detail,随后向供应商发短信/邮件 ----------
+                foreach ($mergeRows as $row) {
+                    if (!is_array($row)) {
+                        continue;
+                    }
+                    $sid = $this->extractScydgyRowId($row);
+                    $this->upsertPurchaseOrderFromRow(
+                        $row,
+                        $sysRqDb,
+                        ProcuremenStatus::WFLOW_PENDING_CONFIRM,
+                        $issueTime,
+                        $this->isValidScydgyRowId($sid) ? ($existingBySid[$sid] ?? null) : null,
+                        $deliveryDeadlineDb,
+                        $scoreRule
+                    );
+                }
+                foreach ($issueCompanies as $c) {
+                    $this->issuePersistSupplierDetails($c, $mergeRows, false, true);
+                }
+
+                Db::commit();
+            } catch (\Throwable $e) {
+                Db::rollback();
+                $this->error($e->getMessage());
+            }
+        } finally {
+            $this->releaseProcuremenNamedLock($pickLockName);
         }
 
         $poIdBySid = [];

+ 1 - 1
application/admin/view/procuremen/audit_issue.html

@@ -552,7 +552,7 @@
                 <th class="text-center" style="width:88px;">质量得分</th>
                 <th class="text-center" style="width:80px;" title="价格得分=(最低单价合计/本供应商单价合计)×价格权重%×100">价格得分</th>
                 {if !empty($showServiceLeadScore)}
-                <th class="text-center" style="width:80px;" title="交货得分取月度评审(当月按上月起往前查,无则默认50)">交货得分</th>
+                <th class="text-center" style="width:80px;" title="交货得分取月度评审(当月按上月起往前查,无则默认40)">交货得分</th>
                 {/if}
                 <th class="text-center" style="width:72px;">总分</th>
                 <th style="width:130px;">工序名称</th>

+ 1 - 1
application/admin/view/procuremen/details_fragment.html

@@ -556,7 +556,7 @@
                 <th class="text-center" style="width:88px;">质量得分</th>
                 <th class="text-center" style="width:80px;" title="价格得分=(最低单价合计/本供应商单价合计)×价格权重%×100">价格得分</th>
                 {if !empty($showServiceLeadScore)}
-                <th class="text-center" style="width:80px;" title="交货得分取月度评审(当月按上月起往前查,无则默认50)">交货得分</th>
+                <th class="text-center" style="width:80px;" title="交货得分取月度评审(当月按上月起往前查,无则默认40)">交货得分</th>
                 {/if}
                 <th class="text-center" style="width:72px;">总分</th>
                 <th style="width:100px;">工序名称</th>

+ 1 - 1
application/admin/view/procuremen/outward_detail.html

@@ -504,7 +504,7 @@
                 <th class="text-center" style="width:88px;">质量得分</th>
                 <th class="text-center" style="width:80px;" title="价格得分=(最低单价合计/本供应商单价合计)×价格权重%×100">价格得分</th>
                 {if !empty($showServiceLeadScore)}
-                <th class="text-center" style="width:80px;" title="交货得分取月度评审(当月按上月起往前查,无则默认50)">交货得分</th>
+                <th class="text-center" style="width:80px;" title="交货得分取月度评审(当月按上月起往前查,无则默认40)">交货得分</th>
                 {/if}
                 <th class="text-center" style="width:72px;">总分</th>
                 <th style="width:120px;">工序名称</th>

+ 7 - 7
application/common/library/ProcuremenSupplierScore.php

@@ -13,7 +13,7 @@ use think\Log;
  * - supplier_service_final_score:月度评审表(四项自动统计,满分 105;qp_manual=1 手工锁定不覆盖)
  *
  * 开标单笔总分 = 质量得分×质量% + 价格得分 [+ 交货得分×交货%]
- * 开标质量/交货得分:均取月度评审表(当月按上月起往前查,无则默认 50)
+ * 开标质量/交货得分:均取月度评审表(当月按上月起往前查,无则默认 40)
  * 开标价格得分 = (本单最低单价合计 / 本供应商单价合计) × 价格权重% × 100
  *
  * 月度评审(与开标单笔分离):
@@ -2276,7 +2276,7 @@ class ProcuremenSupplierScore
     }
 
     /**
-     * 从月度评审表取指定分项:当月按上月起往前查,都没有则默认 50
+     * 从月度评审表取指定分项:当月按上月起往前查,都没有则默认 40(与月度质量/交货满分一致)
      *
      * @param array<int, string> $companyNames
      * @param 'quality_score'|'delivery_score' $field
@@ -2285,7 +2285,7 @@ class ProcuremenSupplierScore
     protected static function loadReviewFieldScoreMap(array $companyNames, string $field, ?string $asOfYm = null): array
     {
         $asOfYm = self::normalizeYm($asOfYm);
-        $default = 50.0;
+        $default = 40.0;
         $map = [];
         $names = [];
         foreach ($companyNames as $n) {
@@ -2335,7 +2335,7 @@ class ProcuremenSupplierScore
     }
 
     /**
-     * 从月度评审表取质量得分:当月按上月起往前查,都没有则默认 50
+     * 从月度评审表取质量得分:当月按上月起往前查,都没有则默认 40
      *
      * @param array<int, string> $companyNames
      * @return array<string, float> company_name => quality_score
@@ -2346,7 +2346,7 @@ class ProcuremenSupplierScore
     }
 
     /**
-     * 从月度评审表取交货得分:当月按上月起往前查,都没有则默认 50(与质量得分口径一致)
+     * 从月度评审表取交货得分:当月按上月起往前查,都没有则默认 40(与质量得分口径一致)
      *
      * @param array<int, string> $companyNames
      * @return array<string, float> company_name => delivery_score
@@ -2487,7 +2487,7 @@ class ProcuremenSupplierScore
                     }
                 }
             }
-            // 质量/交货得分:月度评审表,当月按上月起往前,默认 50
+            // 质量/交货得分:月度评审表,当月按上月起往前,默认 40
             $quality = (float)($reviewMap[$cn] ?? 50);
             $deliveryScore = (float)($deliveryMap[$cn] ?? 50);
             $psum = $hasPrice ? round($priceSum, 2) : 0;
@@ -2684,7 +2684,7 @@ class ProcuremenSupplierScore
         $formula = $parts === []
             ? '(总分)=(质量得分×50%)+(价格得分)'
             : '(总分)=' . implode('+', $parts);
-        $formula .= ';质量得分、交货得分取月度评审(当月按上月起往前查,无则默认50)';
+        $formula .= ';质量得分、交货得分取月度评审(当月按上月起往前查,无则默认40)';
         if ($pw > 0) {
             $formula .= ';价格得分=(最低单价合计/本供应商单价合计)×'
                 . self::formatWeightPercent($pw) . '%×100';