瀏覽代碼

新质保金 逻辑

liugc 1 年之前
父節點
當前提交
24fbdbfb9d

+ 2 - 2
app/adminapi/controller/master_worker/RetentionMoneyLogController.php

@@ -3,8 +3,8 @@
 namespace app\adminapi\controller\master_worker;
 
 use app\adminapi\controller\BaseAdminController;
-use app\adminapi\logic\master_worker\RetentionMoneyLogic;
 use app\adminapi\validate\master_worker\MasterWorkerRetentionMoneyLogValidate;
+use app\common\logic\RetentionMoneyLogic;
 use app\workerapi\lists\MasterWorkerRetentionMoneyLogLists;
 
 class RetentionMoneyLogController extends BaseAdminController
@@ -28,7 +28,7 @@ class RetentionMoneyLogController extends BaseAdminController
     public function add()
     {
         $params = (new MasterWorkerRetentionMoneyLogValidate())->post()->goCheck('add');
-        $result = RetentionMoneyLogic::add($params);
+        $result = RetentionMoneyLogic::addDeduct($params);
         if (true === $result) {
             return $this->success('添加成功', [], 1, 1);
         }

+ 8 - 2
app/adminapi/logic/master_worker/RetentionMoneyLogic.php

@@ -98,7 +98,7 @@ class RetentionMoneyLogic extends BaseLogic
             return false;
         }
     }
-    public static function refundRetention($params)
+    public static function refundRetention($params,$to_freeze = true)
     {
         Db::startTrans();
         try {
@@ -125,9 +125,15 @@ class RetentionMoneyLogic extends BaseLogic
                 throw new \Exception('退可用质保金不足');
             }
             $masterWorkerInfo->earnest_money_usable = $earnest_money_usable;
-            $masterWorkerInfo->earnest_money_freeze += $params['amount'];
+            // 是否要扣到 冻结 里面?
+            $to_freeze && $masterWorkerInfo->earnest_money_freeze += $params['amount'];
             $masterWorkerInfo->save();
 
+            // 记录冻结金额日志
+            if($to_freeze){
+
+            }
+
             Db::commit();
             return true;
         } catch (\Exception $e) {

+ 61 - 3
app/adminapi/logic/works/IssueWorkLogic.php

@@ -15,9 +15,15 @@
 namespace app\adminapi\logic\works;
 
 
+use app\common\enum\worker\WorkerAccountLogEnum;
+use app\common\logic\RetentionMoneyLogic;
+use app\common\logic\WorkerAccountLogLogic;
+use app\common\model\master_worker\MasterWorkerAccountLog;
+use app\common\model\master_worker\MasterWorkerFreezeAmountLog;
 use app\common\model\works\IssueWork;
 use app\common\logic\BaseLogic;
 use app\common\model\works\ReturnWork;
+use app\common\model\works\ServiceWork;
 use think\facade\Db;
 
 
@@ -76,14 +82,14 @@ class IssueWorkLogic extends BaseLogic
     {
         Db::startTrans();
         try {
+            //查询是否完成返修
+            $returnModel = ReturnWork::where('issue_work_id', $params['id'])->findOrEmpty();
             if($params['issue_approval'] == 4) {
-                //查询是否完成返修
-                $returnModel = ReturnWork::where('issue_work_id', $params['id'])->findOrEmpty();
                 if(!$returnModel->isEmpty() && $returnModel->return_work_status != 2){
                     throw new \Exception("返修工单编号:".$returnModel->work_sn.'未返修完成');
                 }
             }
-            IssueWork::where('id', $params['id'])->update([
+            $issueWork = IssueWork::where('id', $params['id'])->update([
                 'work_sn' => $params['work_sn'],
                 'service_work_id' => $params['service_work_id'],
                 'master_worker_id' => $params['master_worker_id'],
@@ -97,6 +103,58 @@ class IssueWorkLogic extends BaseLogic
                 'approval_time' => time(),
             ]);
 
+            // ******** 投诉- 非完成状态时工程师的质保金可用金额 被冻结 ********
+            if($issueWork->is_refunded_payment == 0 && !in_array($issueWork->issue_approval,[5,4])){
+                if(RetentionMoneyLogic::warrantyDepositFreeze($issueWork,($returnModel->isEmpty()?0:$returnModel->id))){
+                    // 原工程师返修收成款是否被冻结 is_refunded_payment
+                    $issueWork->is_refunded_payment = 1;
+                    $issueWork->save();
+                }
+            }
+
+            // 投诉完成-质保金可用金额 解冻
+            if($issueWork->is_refunded_payment == 1 && $issueWork->issue_approval == 4){
+                $serviceWork = ServiceWork::where('id',$issueWork->service_work_id)->findOrEmpty();
+                if(!$serviceWork->isEmpty()){
+                    $is_zero = false;
+                    // 查询出该投诉的冻结金额 master_worker_freeze_amount_log  issue_work_id master_worker_id
+                    $amount = MasterWorkerFreezeAmountLog::where([
+                        'action'=>WorkerAccountLogEnum::INC,
+                        'issue_work_id'=>$issueWork->id,'master_worker_id'=>$issueWork->master_worker_id])->value('amount');
+
+                    // 是否存在返修工单?
+                    $work = ReturnWork::where('issue_work_id',$issueWork->id)->findOrEmpty();
+                    if(!$work->isEmpty()){
+                        // 最新师傅
+                        if($issueWork->master_worker_id != $work->master_worker_id){
+                            // 加账户余额 收益
+                            $change_amount = MasterWorkerAccountLog::where([
+                                'change_object'=>WorkerAccountLogEnum::UM,'change_type'=>WorkerAccountLogEnum::UM_INC_ADMIN,
+                                'action'=>WorkerAccountLogEnum::INC,'worker_id'=>$issueWork->master_worker_id,
+                                'work_sn'=>$issueWork->work_sn])->value('change_amount');
+                            // 存在则按返修工单中的最新师傅 计算收益
+                            $extra['ReturnWorkInfo'] = ['id'=>$work->id,'master_worker_id'=>$work->master_worker_id,'service_work_id'=>$work->service_work_id,'issue_work_id'=>$work->issue_work_id];
+                            $remark = '工单号:'.$issueWork->work_sn.',返修单号:'.$work->work_sn.',收益金额:'.$change_amount.',原因:返修工单新工程师收益';
+                            WorkerAccountLogLogic::addAccountLog($serviceWork,$change_amount,WorkerAccountLogEnum::UM_INC_ADMIN,WorkerAccountLogEnum::INC,$remark,$extra);
+                            $is_zero = true;
+                        }
+                    }
+                    /*FreezeAmount              source remark return_work_id issue_work_id work_id amount worker_id retention_money_log_id
+                    RetentionMoney              to_freeze return_work_id source remark work_id amount  worker_id*/
+                    // 对原工程师的 质保金解冻质保金 / 清零
+                    RetentionMoneyLogic::warrantyDepositRelease([
+                        'source'=>1,
+                        'remark'=>'对原工程师的质保金解冻质保金/清零',
+                        'to_freeze'=>2,
+                        'return_work_id'=>$work->id,
+                        'issue_work_id'=>$issueWork->id,
+                        'work_id'=>$work->service_work_id,
+                        'amount'=>$amount,
+                        'worker_id'=>$issueWork->master_worker_id,
+                    ],$is_zero);
+                }
+            }
+
             Db::commit();
             return true;
         } catch (\Exception $e) {

+ 1 - 36
app/adminapi/logic/works/ReturnWorkLogic.php

@@ -15,8 +15,8 @@
 namespace app\adminapi\logic\works;
 
 
-use app\adminapi\logic\master_worker\RetentionMoneyLogic;
 use app\common\enum\worker\WorkerAccountLogEnum;
+use app\common\logic\RetentionMoneyLogic;
 use app\common\logic\WorkerAccountLogLogic;
 use app\common\model\master_worker\MasterWorker;
 use app\common\model\master_worker\MasterWorkerAccountLog;
@@ -168,46 +168,11 @@ class ReturnWorkLogic extends BaseLogic
             if($flag){
                 MasterWorker::setWorktotal('dec',$model->master_worker_id);
             }
-            $isIdentical = false;
-            if(!empty($model->master_worker_id) && $params['master_worker_id'] != $model->master_worker_id){
-                $isIdentical = true;
-            }
             $model->master_worker_id = $params['master_worker_id'];
             MasterWorker::setWorktotal('inc', $params['master_worker_id']);
             $model->user_id = $issueWork->user_id;
             $model->save();
 
-            // ******** 设置返修-工程师的账号余额、质保金可用金额 对应原工单原工程师 扣减
-            if($isIdentical && $issueWork->is_refunded_payment == 0){
-                $work = ServiceWork::where('id',$issueWork->service_work_id)->findOrEmpty();
-                if(!$work->isEmpty()){
-                    // 退余额
-                    $change_amount = MasterWorkerAccountLog::where([
-                        'change_object'=>WorkerAccountLogEnum::UM,'change_type'=>WorkerAccountLogEnum::UM_INC_ADMIN,
-                        'action'=>WorkerAccountLogEnum::INC,'worker_id'=>$issueWork->master_worker_id,
-                        'work_sn'=>$issueWork->work_sn])->value('change_amount');
-                    if($change_amount){
-                        $extra['ReturnWorkInfo'] = ['id'=>$model->id,'master_worker_id'=>$model->master_worker_id,'service_work_id'=>$model->service_work_id,'issue_work_id'=>$model->issue_work_id];
-                        $remark = '工单号:'.$issueWork->work_sn.',返修单号:'.$model->work_sn.',退款金额:'.$change_amount.',退款原因:返修工单退款';
-                        WorkerAccountLogLogic::addAccountLog($work,$change_amount,WorkerAccountLogEnum::UM_DEC_ADMIN,WorkerAccountLogEnum::DEC,$remark,$extra);
-                    }
-
-                    // 退质保金
-                    $retentionAmount = MasterWorkerRetentionMoneyLog::where(['action'=>WorkerAccountLogEnum::INC,
-                        'worker_id'=>$issueWork->master_worker_id,'work_id'=>$issueWork->service_work_id])
-                        ->value('amount');
-                    if($retentionAmount){
-                        $remark = '工单号:'.$issueWork->work_sn.',返修单号:'.$model->work_sn.',退款金额:'.$retentionAmount.',退款原因:返修工单退款';
-                        RetentionMoneyLogic::refundRetention(['work_id'=>$issueWork->service_work_id,'worker_id'=>$issueWork->master_worker_id,
-                            'amount'=>$retentionAmount,'remark'=>$remark,'return_work_id'=>$model->id
-                        ]);
-                    }
-
-                    // 原工程师返修收成款是否已退 is_refunded_payment
-                    $issueWork->is_refunded_payment = 1;
-                    $issueWork->save();
-                }
-            }
             Db::commit();
             return true;
         } catch (\Exception $e) {

+ 2 - 1
app/api/logic/PerformanceLogic.php

@@ -10,6 +10,7 @@ use app\common\model\master_worker\MasterWorker;
 use app\common\model\orders\RechargeOrder;
 use app\common\model\performance\PerformanceRules;
 use app\common\model\recharge\OrderGoods;
+use app\common\logic\RetentionMoneyLogic;
 use think\facade\Db;
 use think\facade\Log;
 
@@ -73,7 +74,7 @@ class PerformanceLogic extends BaseLogic
                 $retentionData['amount'] = $amount;
                 $retentionData['remark'] = "分期缴纳质保金:该单实提成--{$settlement_amount},分期每单缴纳比例--{$masterWorkerInfo['installment_ratio']}%,缴纳金额--{$amount}";
                 $settlement_amount -= (float)$amount;
-                $surplusMoney = RetentionMoneyLogic::add($retentionData);
+                $surplusMoney = RetentionMoneyLogic::retentionPayment($retentionData);
                 if($surplusMoney === false){
                     Log::info('分期缴纳质保金支付失败-'.RetentionMoneyLogic::getError(),$retentionData);
                     $settlement_amount += (float)$amount;

+ 0 - 43
app/api/logic/ReturnWorkLogic.php

@@ -66,47 +66,6 @@ class ReturnWorkLogic extends BaseLogic
             //更新投诉状态
             $issue = IssueWork::where('service_work_id',$work->service_work_id)->findOrEmpty();
             if(!$issue->isEmpty()){
-
-                // 返修完成-工程师的账号余额、质保金可用金额 对应原工单 增加
-                if($issue->is_refunded_payment == 1 && $issue->issue_approval != 4){
-                    $serviceWork = ServiceWork::where('id',$work->service_work_id)->findOrEmpty();
-                    if(!$serviceWork->isEmpty()){
-                        // 加余额
-                        $change_amount = MasterWorkerAccountLog::where([
-                            'change_object'=>WorkerAccountLogEnum::UM,'change_type'=>WorkerAccountLogEnum::UM_INC_ADMIN,
-                            'action'=>WorkerAccountLogEnum::INC,'worker_id'=>$issue->master_worker_id,
-                            'work_sn'=>$issue->work_sn])->value('change_amount');
-                        /*// 加质保金
-                        $retentionAmount = MasterWorkerRetentionMoneyLog::where(['action'=>WorkerAccountLogEnum::INC,
-                            'worker_id'=>$issue->master_worker_id,'work_id'=>$issue->service_work_id])
-                            ->value('amount');
-                        //$settlement_amount = $change_amount + $retentionAmount;*/
-                        $settlement_amount = $change_amount;
-                        /*// 返修单-新工程师 缴纳质保金 $work->id    $work->master_worker_id
-                        $masterWorkerInfo = MasterWorker::where('id', $work->master_worker_id)->findOrEmpty()->toArray();
-                        if(!empty($masterWorkerInfo) && $masterWorkerInfo['retention_pay_status'] == 2 && ($masterWorkerInfo['earnest_money'] > $masterWorkerInfo['earnest_money_usable'])){
-                            $retentionData['action'] = WorkerAccountLogEnum::INC;
-                            $retentionData['worker_id'] = $work->master_worker_id;
-                            $retentionData['work_id'] = $issue->service_work_id;
-                            $retentionData['return_work_id'] = $work->id;
-                            $amount = bcmul($settlement_amount, bcdiv($masterWorkerInfo['installment_ratio'], 100, 4),2);
-                            $retentionData['amount'] = $amount;
-                            $retentionData['remark'] = "返修单-分期缴纳质保金:该单实提成--{$settlement_amount},分期每单缴纳比例--{$masterWorkerInfo['installment_ratio']}%,缴纳金额--{$amount}";
-                            $settlement_amount -= (float)$amount;
-                            $surplusMoney = RetentionMoneyLogic::add($retentionData);
-                            if($surplusMoney === false){
-                                Log::info('返修单-分期缴纳质保金支付失败-'.RetentionMoneyLogic::getError(),$retentionData);
-                                $settlement_amount += (float)$amount;
-                            }else{
-                                $settlement_amount += (float)$surplusMoney;
-                            }
-                        }*/
-                        $extra['ReturnWorkInfo'] = ['id'=>$work->id,'master_worker_id'=>$work->master_worker_id,'service_work_id'=>$work->service_work_id,'issue_work_id'=>$work->issue_work_id];
-                        $remark = '工单号:'.$issue->work_sn.',返修单号:'.$work->work_sn.',收益金额:'.$settlement_amount.',原因:返修工单新工程师收益';
-                        WorkerAccountLogLogic::addAccountLog($serviceWork,$settlement_amount,WorkerAccountLogEnum::UM_INC_ADMIN,WorkerAccountLogEnum::INC,$remark,$extra);
-                    }
-                }
-
                 $issue->issue_approval = 4;
                 $issue->complaint_status = 2;
                 $issue->responsible = 2;
@@ -114,8 +73,6 @@ class ReturnWorkLogic extends BaseLogic
                 $issue->save();
             }
 
-
-
             Db::commit();
             return true;
         }catch(\Exception $e){

+ 3 - 3
app/common/command/QueryRefund.php

@@ -14,10 +14,10 @@
 
 namespace app\common\command;
 
-use app\adminapi\logic\master_worker\RetentionMoneyLogic;
 use app\common\enum\PayEnum;
 use app\common\enum\RefundEnum;
 use app\common\enum\worker\WorkerAccountLogEnum;
+use app\common\logic\RetentionMoneyLogic;
 use app\common\logic\WorkerAccountLogLogic;
 use app\common\model\master_worker\MasterWorkerAccountLog;
 use app\common\model\master_worker\MasterWorkerRetentionMoneyLog;
@@ -203,11 +203,11 @@ class QueryRefund extends Command
                 $change_amount = MasterWorkerAccountLog::where(['work_sn'=>$work->work_sn,'action'=>1])->value('change_amount');
                 WorkerAccountLogLogic::addAccountLog($work,$change_amount,WorkerAccountLogEnum::UM_DEC_ADMIN,WorkerAccountLogEnum::DEC);
                 //工程师质保金变动 - 退质保金
-                $retentionAmount = MasterWorkerRetentionMoneyLog::where(['action'=>WorkerAccountLogEnum::INC,'worker_id'=>$work->master_worker_id,'work_id'=>$work->id])->value('amount');
+                $retentionAmount = MasterWorkerRetentionMoneyLog::where(['action'=>WorkerAccountLogEnum::INC,'source'=>2,'worker_id'=>$work->master_worker_id,'work_id'=>$work->id])->value('amount');
                 if($retentionAmount){
                     $remark = '工单号:'.$work->work_sn.',退款金额:'.$retentionAmount.',退款原因:工单退款';
                     RetentionMoneyLogic::refundRetention([
-                        'work_id'=>$work->id,'worker_id'=>$work->master_worker_id,'amount'=>$retentionAmount,'remark'=>$remark
+                        'work_id'=>$work->id,'worker_id'=>$work->master_worker_id,'amount'=>$retentionAmount,'remark'=>$remark,'source'=>2
                     ],false);
                 }
                 //物业余额变动

+ 4 - 0
app/common/enum/worker/WorkerAccountLogEnum.php

@@ -24,9 +24,13 @@ class WorkerAccountLogEnum
      * 动作
      * INC 增加
      * DEC 减少
+     * FROZEN 冻结
+     * RELEASE 解冻
      */
     const INC = 1;
     const DEC = 2;
+    const FROZEN = 3;
+    const RELEASE = 4;
 
 
     /**

+ 327 - 0
app/common/logic/RetentionMoneyLogic.php

@@ -0,0 +1,327 @@
+<?php
+namespace app\common\logic;
+
+use app\common\enum\worker\WorkerAccountLogEnum;
+use app\common\model\master_worker\MasterWorker;
+use app\common\model\master_worker\MasterWorkerAccountLog;
+use app\common\model\master_worker\MasterWorkerFreezeAmountLog;
+use app\common\model\master_worker\MasterWorkerRetentionMoneyLog;
+use app\common\model\works\ServiceWork;
+use think\facade\Db;
+use think\facade\Log;
+
+class RetentionMoneyLogic extends BaseLogic
+{
+    public static function totalAmount($params)
+    {
+        try{
+            $model = MasterWorker::findOrEmpty($params['worker_id']);
+            if($model->isEmpty()){
+                throw new \Exception('用户不存在');
+            }
+            $where = [];
+            $where[] = ['worker_id','=',$params['worker_id']] ;
+            $incWhere =$where;
+            $incWhere[] = ['action', '=',WorkerAccountLogEnum::INC];
+            $data = [];
+            //$data['amount_inc_total'] = MasterWorkerRetentionMoneyLog::where($incWhere)->sum('amount');
+            $data['amount_inc_total'] = $model->earnest_money;
+
+            $outWhere = $where;
+            $outWhere[] =['action', '=',WorkerAccountLogEnum::DEC];
+            //$data['amount_dec_total'] = MasterWorkerRetentionMoneyLog::where($outWhere)->sum('amount');
+            $data['amount_dec_total'] = $model->earnest_money_freeze;
+            //$data['amount_available_total'] = $data['amount_inc_total'] - $data['amount_dec_total'];
+            $data['amount_available_total'] = $model->earnest_money_usable;
+            $data['earnest_money_usable'] =  $model->earnest_money_usable;
+            $data['earnest_money_freeze'] = $model->earnest_money_freeze;
+            $data['earnest_money'] = $model->earnest_money;
+            $data['retention_money_status'] = $model->retention_money_status;
+            $data['retention_money_status_text'] = $model->retention_money_status_text;
+            $data['retention_pay_status'] = $model->retention_pay_status;
+            $data['retention_pay_status_text'] = $model->retention_pay_status_text;
+            $data['worker_number'] = $model->worker_number;
+            $data['real_name'] = $model->real_name;
+            $data['worker_id'] = $model->id;
+            $data['installment_ratio'] = $model->installment_ratio;
+            return $data;
+        } catch(\Exception $e){
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+    // 后台添加、扣除、冻结、解冻
+    public static function addDeduct($params)
+    {
+        Db::startTrans();
+        try {
+            if(isset($params['work_id']) && !empty($params['work_id'])){
+                $workModel = ServiceWork::findOrEmpty($params['work_id']);
+                if($workModel->isEmpty()){
+                    throw new \Exception('工单不存在');
+                }
+            }
+
+            // $params['worker_id']
+            $masterWorkerInfo = MasterWorker::where('id', $params['worker_id'])->findOrEmpty();
+            if($params['action'] == WorkerAccountLogEnum::INC){
+                $earnest_money_usable = $masterWorkerInfo->earnest_money_usable + $params['amount'];
+                if($earnest_money_usable > $masterWorkerInfo->earnest_money){
+                    throw new \Exception('可用质保金超过配置质保金');
+                }
+                $masterWorkerInfo->earnest_money_usable = $earnest_money_usable;
+            }
+            if($params['action'] == WorkerAccountLogEnum::DEC){
+                $earnest_money_usable = $masterWorkerInfo->earnest_money_usable - $params['amount'];
+                if($earnest_money_usable < 0){
+                    throw new \Exception('可用质保金不足');
+                }
+                $masterWorkerInfo->earnest_money_usable = $earnest_money_usable;
+            }
+
+            if($params['action'] == WorkerAccountLogEnum::FROZEN){
+                $earnest_money_usable = $masterWorkerInfo->earnest_money_usable - $params['amount'];
+                if($earnest_money_usable < 0){
+                    throw new \Exception('可用质保金不足');
+                }
+                $params['action'] = WorkerAccountLogEnum::DEC;
+                $masterWorkerInfo->earnest_money_usable = $earnest_money_usable;
+                $masterWorkerInfo->earnest_money_freeze += $params['amount'];
+            }
+            if($params['action'] == WorkerAccountLogEnum::RELEASE){
+                $masterWorkerInfo->earnest_money_freeze -= $params['amount'];
+                if($masterWorkerInfo->earnest_money_freeze < 0){
+                    throw new \Exception('冻结质保金不足');
+                }
+                $earnest_money_usable = $masterWorkerInfo->earnest_money_usable + $params['amount'];
+                if($earnest_money_usable > $masterWorkerInfo->earnest_money){
+                    // 多余的部分质保金退回给用户账号余额即可以提现
+                    $surplus = $earnest_money_usable - $masterWorkerInfo->earnest_money;
+
+
+                    $params['amount'] = $params['amount'] - $surplus;
+                    $earnest_money_usable = $masterWorkerInfo->earnest_money;
+                    throw new \Exception('可用质保金超过配置质保金');
+                }
+                $params['action'] = WorkerAccountLogEnum::INC;
+                $masterWorkerInfo->earnest_money_usable = $earnest_money_usable;
+            }
+
+            $masterWorkerInfo->save();
+
+            $retentionMoneyLog = MasterWorkerRetentionMoneyLog::create([
+                'sn' => generate_sn(MasterWorkerRetentionMoneyLog::class,'sn'),
+                'worker_id' => $params['worker_id'],
+                'action' => in_array($params['action'],[WorkerAccountLogEnum::FROZEN,WorkerAccountLogEnum::DEC])?WorkerAccountLogEnum::DEC:WorkerAccountLogEnum::INC,
+                'amount' => $params['amount'],
+                'work_id' => $params['work_id'],
+                'remark' => $params['remark'],
+            ])->getData();
+            // 当为冻结时,冻结金额要记录到日志中 $retentionMoneyLog
+
+
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    // 工单结算缴纳质保金
+    public static function retentionPayment($params)
+    {
+        Db::startTrans();
+        try {
+            $surplus_money = 0;
+            if(isset($params['work_id']) && !empty($params['work_id'])){
+                $workModel = ServiceWork::findOrEmpty($params['work_id']);
+                if($workModel->isEmpty()){
+                    throw new \Exception('工单不存在');
+                }
+            }
+            Log::info('RetentionMoneyLogic-params:'.json_encode($params));
+            // $params['worker_id']
+            $masterWorkerInfo = MasterWorker::where('id', $params['worker_id'])->findOrEmpty();
+            $earnest_money_usable = (float)$masterWorkerInfo->earnest_money_usable + (float)$params['amount'];
+            if($earnest_money_usable > (float)$masterWorkerInfo->earnest_money){
+                $surplus_money = $earnest_money_usable - (float)$masterWorkerInfo->earnest_money;
+                $params['remark'] .= "\n原质保金:{$masterWorkerInfo->earnest_money},原可用质保金:{$masterWorkerInfo->earnest_money_usable},缴纳多余:{$surplus_money},实际缴纳:".((float)$params['amount']-$surplus_money);
+                $masterWorkerInfo->earnest_money_usable += ((float)$params['amount']-$surplus_money);
+            }
+            $masterWorkerInfo->save();
+
+            MasterWorkerRetentionMoneyLog::create([
+                'sn' => generate_sn(MasterWorkerRetentionMoneyLog::class,'sn'),
+                'worker_id' => $params['worker_id'],
+                'action' => $params['action'],
+                'amount' => ((float)$params['amount']-$surplus_money),
+                'work_id' => $params['work_id'],
+                'remark' => $params['remark'],
+                'source' => 2,
+                'return_work_id' => isset($params['return_work_id'])?$params['return_work_id']:0,
+            ]);
+
+            Db::commit();
+            return $surplus_money;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+    // 扣除质保金可用额 (包括工单退款、冻结)
+    public static function refundRetention($params,$to_freeze = true)
+    {
+        Db::startTrans();
+        try {
+
+            // $params['worker_id']
+            $masterWorkerInfo = MasterWorker::where('id', $params['worker_id'])->findOrEmpty();
+            $earnest_money_usable = $masterWorkerInfo->earnest_money_usable - $params['amount'];
+            if($earnest_money_usable < 0){
+                throw new \Exception('退可用质保金不足');
+            }
+            $masterWorkerInfo->earnest_money_usable = $earnest_money_usable;
+            // 是否要扣到 冻结 里面?
+            $to_freeze && $masterWorkerInfo->earnest_money_freeze += $params['amount'];
+            $masterWorkerInfo->save();
+
+            MasterWorkerRetentionMoneyLog::create([
+                'sn' => generate_sn(MasterWorkerRetentionMoneyLog::class,'sn'),
+                'worker_id' => $params['worker_id'],
+                'action' => WorkerAccountLogEnum::DEC,
+                'amount' => $params['amount'],
+                'work_id' => $params['work_id'],
+                'remark' => $params['remark'],
+                'source' => $params['source'],
+                'to_freeze' => isset($params['to_freeze'])?$params['to_freeze']:0,
+                'return_work_id' => isset($params['return_work_id'])?$params['return_work_id']:0,
+            ]);
+            // 记录冻结金额日志 - 增加
+            if($to_freeze){
+                MasterWorkerFreezeAmountLog::create([
+                    'sn' => generate_sn(MasterWorkerFreezeAmountLog::class,'sn'),
+                    'master_worker_id' => $params['worker_id'],
+                    'action' => WorkerAccountLogEnum::INC,
+                    'amount' => $params['amount'],
+                    'work_id' => $params['work_id'],
+                    'issue_work_id' => isset($params['issue_work_id'])?$params['issue_work_id']:0,
+                    'return_work_id' => isset($params['return_work_id'])?$params['return_work_id']:0,
+                    'remark' => $params['remark'],
+                    'source' => $params['source']
+                ]);
+            }
+
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    // 冻结投诉冻结质保金
+    public static function warrantyDepositFreeze($issueWork,$return_work_id = 0)
+    {
+        Db::startTrans();
+        try {
+
+            $work = ServiceWork::where('id',$issueWork->service_work_id)->findOrEmpty();
+            if(!$work->isEmpty()){
+                // 应退余额
+                $change_amount = MasterWorkerAccountLog::where([
+                    'change_object'=>WorkerAccountLogEnum::UM,'change_type'=>WorkerAccountLogEnum::UM_INC_ADMIN,
+                    'action'=>WorkerAccountLogEnum::INC,'worker_id'=>$issueWork->master_worker_id,
+                    'work_sn'=>$issueWork->work_sn])->value('change_amount');
+                // 应退质保金
+                $retentionAmount = MasterWorkerRetentionMoneyLog::where(['action'=>WorkerAccountLogEnum::INC,
+                    'worker_id'=>$issueWork->master_worker_id,'work_id'=>$issueWork->service_work_id])
+                    ->value('amount');
+
+                // 总金额 = 退款金额 + 退质保金
+                $totalAmount = ($change_amount?:0) + ($retentionAmount?:0);
+                $remark = '工单号:'.$issueWork->work_sn.($return_work_id?',返修单号:'.$return_work_id:'').',退款总金额:'.$totalAmount.
+                    ',应退余额:'.($change_amount?:0).
+                    ',应退质保金:'.($retentionAmount?:0).
+                    ',退款原因:返修冻结';
+                self::refundRetention(['work_id'=>$issueWork->service_work_id,'worker_id'=>$issueWork->master_worker_id,
+                    'amount'=>$totalAmount,'remark'=>$remark,'return_work_id'=>$return_work_id,'to_freeze'=>1
+                ]);
+            }
+
+
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    // 解冻投诉冻结质保金
+    /*FreezeAmount              source remark return_work_id issue_work_id work_id amount worker_id retention_money_log_id
+    RetentionMoney              to_freeze return_work_id source remark work_id amount  worker_id*/
+    public static function warrantyDepositRelease($params,$is_zero = false)
+    {
+        Db::startTrans();
+        try {
+            // $params['worker_id']
+            $masterWorkerInfo = MasterWorker::where('id', $params['worker_id'])->findOrEmpty();
+
+            $masterWorkerInfo->earnest_money_freeze -= $params['amount'];
+            if($is_zero){
+                $retention_money_log_id = MasterWorkerFreezeAmountLog::where([
+                    'action'=>WorkerAccountLogEnum::INC,
+                    'issue_work_id'=>$params['issue_work_id'],'master_worker_id'=>$params['worker_id']])->value('retention_money_log_id');
+                MasterWorkerRetentionMoneyLog::where('id',$retention_money_log_id)->update(['to_freeze'=>2]);
+            }else{
+                $masterWorkerInfo->earnest_money_usable += $params['amount'];
+                MasterWorkerRetentionMoneyLog::create([
+                    'sn' => generate_sn(MasterWorkerRetentionMoneyLog::class,'sn'),
+                    'worker_id' => $params['worker_id'],
+                    'action' => WorkerAccountLogEnum::INC,
+                    'amount' => $params['amount'],
+                    'work_id' => $params['work_id'],
+                    'remark' => $params['remark'],
+                    'source' => $params['source'],
+                    'to_freeze' => isset($params['to_freeze'])?$params['to_freeze']:0,
+                    'return_work_id' => isset($params['return_work_id'])?$params['return_work_id']:0,
+                ]);
+            }
+
+            // 记录冻结金额日志 - 扣减
+            MasterWorkerFreezeAmountLog::create([
+                'sn' => generate_sn(MasterWorkerFreezeAmountLog::class,'sn'),
+                'master_worker_id' => $params['worker_id'],
+                'action' => WorkerAccountLogEnum::DEC,
+                'amount' => $params['amount'],
+                'work_id' => $params['work_id'],
+                'retention_money_log_id' => isset($params['retention_money_log_id'])?$params['retention_money_log_id']:0,
+                'issue_work_id' => isset($params['issue_work_id'])?$params['issue_work_id']:0,
+                'return_work_id' => isset($params['return_work_id'])?$params['return_work_id']:0,
+                'remark' => $params['remark'],
+                'source' => $params['source']
+            ]);
+
+            $masterWorkerInfo->save();
+
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+}

+ 13 - 0
app/common/model/master_worker/MasterWorkerFreezeAmountLog.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * @author 林海涛
+ * @date 2024/7/28 上午10:36
+ */
+namespace app\common\model\master_worker;
+
+use app\common\model\BaseModel;
+
+class MasterWorkerFreezeAmountLog extends BaseModel
+{
+    protected $name = 'master_worker_freeze_amount_log';
+}