瀏覽代碼

合并代码

dongxiaoqin 1 年之前
父節點
當前提交
e254db70dc

+ 45 - 0
app/adminapi/controller/third/ThirdGoodsController.php

@@ -20,6 +20,8 @@ use app\adminapi\controller\BaseAdminController;
 use app\adminapi\lists\third\ThirdGoodsLists;
 use app\adminapi\logic\third\ThirdGoodsLogic;
 use app\adminapi\validate\third\ThirdGoodsValidate;
+use app\common\logic\ThirdOrderLogic;
+use app\common\model\third\ThirdGoods;
 
 
 /**
@@ -104,5 +106,48 @@ class ThirdGoodsController extends BaseAdminController
         return $this->data($result);
     }
 
+    /**
+     * 获取美团商品
+     * @return \think\response\Json
+     */
+    public function getMeituanGoods()
+    {
+        $data = [];
+        $i = 1;
+        for ($i; $i < 100; $i++){
+            $result = ThirdOrderLogic::queryshopdeal($i);
+            if(empty($result['data']['result'])){
+                break;
+            }
+            foreach ($result['data']['result'] as $item){
+                $data[] = $item;
+            }
+        }
+
+        if(!empty($data)){
+            $good_data = [];
+            $dealGroupIds = array_column($data, 'dealGroupId');
+            $product_ids = ThirdGoods::whereIn('product_id', $dealGroupIds)->column('product_id');
+            foreach ($data as $key=>$items){
+                if(in_array($items['dealGroupId'], $product_ids)){
+                    unset($data[$key]);
+                }else{
+                    $good_data[] = [
+                        'third_type' => 1,
+                        'goods_id' => 0,
+                        'product_id' => $items['dealGroupId'],
+                        'product_name' => $items['title'],
+                        'product_price' => $items['price'],
+                    ];
+                }
+            }
+
+            if(!empty($good_data)){
+                ThirdGoodsLogic::addMeituanGoods($good_data);
+            }
+        }
+        return $this->success('同步成功', [], 1, 1);
+    }
+
 
 }

+ 2 - 0
app/adminapi/controller/works/ServiceWorkController.php

@@ -18,6 +18,7 @@ namespace app\adminapi\controller\works;
 
 use app\adminapi\controller\BaseAdminController;
 use app\adminapi\lists\works\ServiceWorkLists;
+use app\adminapi\logic\equity\UserEquityLogic;
 use app\adminapi\logic\master_worker\MasterWorkerLogic;
 use app\adminapi\logic\works\ServiceWorkLogic;
 use app\adminapi\validate\works\ServiceWorkValidate;
@@ -138,6 +139,7 @@ class ServiceWorkController extends BaseAdminController
         $params = (new ServiceWorkValidate())->post()->goCheck('detail');
         $result = ServiceWorkLogic::cancel($params);
         if (true === $result) {
+            UserEquityLogic::cancelServiceWorkRestoredNumber($params);
             return $this->success('取消工单成功!', [], 1, 1);
         }
         return $this->fail(ServiceWorkLogic::getError());

+ 1 - 1
app/adminapi/lists/goods/GoodsLists.php

@@ -42,7 +42,7 @@ class GoodsLists extends BaseAdminDataLists implements ListsSearchInterface
     public function setSearch(): array
     {
         return [
-            '=' => ['goods_status','is_agent','is_activity','goods_payment_type'],
+            '=' => ['goods_status','is_agent','is_activity','goods_payment_type','platform_value'],
             '%like%' => ['goods_name','goods_brand'],
             'between' => ['service_total', 'service_fee'],
         ];

+ 4 - 1
app/adminapi/lists/master_worker/MasterWorkerLists.php

@@ -36,6 +36,7 @@ class MasterWorkerLists extends BaseAdminDataLists implements ListsSearchInterfa
     public $range = 0;
     public $lon = 0;
     public $lat = 0;
+    public $service_area_id = 0;
     //所有派单限制条件: 工程师保护期  工程师可用金额限制(除去保护期工程师)     工程师接单状态   订单产品分类  订单坐标筛选    订单坐标距离排序
     /**
      * @notes 设置搜索条件
@@ -128,9 +129,10 @@ class MasterWorkerLists extends BaseAdminDataLists implements ListsSearchInterfa
             $where[] =[ 'mw.work_total','<= ',$this->params['max_work_number']];
         }
         if(isset($this->params['order_id']) && $this->params['order_id']){
-            $lon_lat = (ServiceWork::where('id',$this->params['order_id'])->column("lon,lat,goods_category_id"))[0];
+            $lon_lat = (ServiceWork::where('id',$this->params['order_id'])->column("lon,lat,goods_category_id,service_area_id"))[0];
             $this->lon = $lon_lat['lon'];
             $this->lat = $lon_lat['lat'];
+            $this->service_area_id = $lon_lat['service_area_id'];
             $goods_category_id = $lon_lat['goods_category_id'];
             // 派单搜索条件 - 工程师保护期  工程师可用金额限制(除去保护期工程师)  订单产品分类  订单坐标筛选(暂不按距离筛选只按距离排序)
             $ids = DistributeLeafletsService::getIntersection($goods_category_id??0);
@@ -165,6 +167,7 @@ class MasterWorkerLists extends BaseAdminDataLists implements ListsSearchInterfa
             if($this->range){
                 $distanceWhereSql = '('.$user_distance.' <= '.$this->range;
             }
+            $distanceWhereSql .= ' and is_disable=0  AND work_status=0  AND accept_order_status=1 and service_area_id = '.$this->service_area_id;
         }
         $list = MasterWorker::alias('mw')
             ->join('master_worker_register mwr', 'mwr.worker_id = mw.id')

+ 2 - 2
app/adminapi/lists/master_worker_register/MasterWorkerRegisterLists.php

@@ -38,7 +38,7 @@ class MasterWorkerRegisterLists extends BaseAdminDataLists implements ListsSearc
     public function setSearch(): array
     {
         return [
-            '=' => ['maintain_exp_type', 'other_exp_type', 'city', 'vehicle_type', 'status','is_credential'],
+            '=' => ['maintain_exp_type', 'other_exp_type', 'city', 'vehicle_type', 'status','is_credential','sale_id'],
             '%like%' => ['name', 'mobile'],
             '<=' => ['age'],
         ];
@@ -78,7 +78,7 @@ class MasterWorkerRegisterLists extends BaseAdminDataLists implements ListsSearc
      */
     public function lists(): array
     {
-        return MasterWorkerRegister::where($this->searchWhere)->where($this->queryWhere())
+        return MasterWorkerRegister::with(['sale'])->where($this->searchWhere)->where($this->queryWhere())
             ->where($this->queryDataWhere())
             ->field(['*'])
             ->limit($this->limitOffset, $this->limitLength)

+ 77 - 76
app/adminapi/lists/third/ThirdOrdersLists.php

@@ -1,77 +1,78 @@
-<?php
-// +----------------------------------------------------------------------
-// | likeadmin快速开发前后端分离管理后台(PHP版)
-// +----------------------------------------------------------------------
-// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
-// | 开源版本可自由商用,可去除界面版权logo
-// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
-// | github下载:https://github.com/likeshop-github/likeadmin
-// | 访问官网:https://www.likeadmin.cn
-// | likeadmin团队 版权所有 拥有最终解释权
-// +----------------------------------------------------------------------
-// | author: likeadminTeam
-// +----------------------------------------------------------------------
-
-namespace app\adminapi\lists\third;
-
-
-use app\adminapi\lists\BaseAdminDataLists;
-use app\common\model\third\ThirdOrders;
-use app\common\lists\ListsSearchInterface;
-
-
-/**
- * ThirdOrders列表
- * Class ThirdOrdersLists
- * @package app\adminapi\liststhird
- */
-class ThirdOrdersLists extends BaseAdminDataLists implements ListsSearchInterface
-{
-
-
-    /**
-     * @notes 设置搜索条件
-     * @return \string[][]
-     * @author likeadmin
-     * @date 2025/03/06 16:57
-     */
-    public function setSearch(): array
-    {
-        return [
-            '=' => ['orderId', 'productId', 'productName', 'third_type', 'request_msg'],

-        ];
-    }
-
-
-    /**
-     * @notes 获取列表
-     * @return array
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\DbException
-     * @throws \think\db\exception\ModelNotFoundException
-     * @author likeadmin
-     * @date 2025/03/06 16:57
-     */
-    public function lists(): array
-    {
-        return ThirdOrders::where($this->searchWhere)
-            ->field(['id', 'orderId', 'productId', 'productName', 'third_type', 'request_msg'])
-            ->limit($this->limitOffset, $this->limitLength)
-            ->order(['id' => 'desc'])
-            ->select()
-            ->toArray();
-    }
-
-
-    /**
-     * @notes 获取数量
-     * @return int
-     * @author likeadmin
-     * @date 2025/03/06 16:57
-     */
-    public function count(): int
-    {
-        return ThirdOrders::where($this->searchWhere)->count();
-    }
-
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\lists\third;
+
+
+use app\adminapi\lists\BaseAdminDataLists;
+use app\common\model\third\ThirdOrders;
+use app\common\lists\ListsSearchInterface;
+
+
+/**
+ * ThirdOrders列表
+ * Class ThirdOrdersLists
+ * @package app\adminapi\liststhird
+ */
+class ThirdOrdersLists extends BaseAdminDataLists implements ListsSearchInterface
+{
+
+
+    /**
+     * @notes 设置搜索条件
+     * @return \string[][]
+     * @author likeadmin
+     * @date 2025/03/06 16:57
+     */
+    public function setSearch(): array
+    {
+        return [
+            '=' => ['orderId', 'productId', 'productName', 'third_type', 'request_msg'],
+
+        ];
+    }
+
+
+    /**
+     * @notes 获取列表
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author likeadmin
+     * @date 2025/03/06 16:57
+     */
+    public function lists(): array
+    {
+        return ThirdOrders::where($this->searchWhere)
+            ->field(['id', 'orderId', 'productId', 'productName', 'third_type', 'request_msg','uni_order_id','work_id','create_time'])
+            ->limit($this->limitOffset, $this->limitLength)
+            ->order(['id' => 'desc'])
+            ->select()
+            ->toArray();
+    }
+
+
+    /**
+     * @notes 获取数量
+     * @return int
+     * @author likeadmin
+     * @date 2025/03/06 16:57
+     */
+    public function count(): int
+    {
+        return ThirdOrders::where($this->searchWhere)->count();
+    }
+
 }

+ 1 - 0
app/adminapi/logic/effective/OrderEffectiveLogLogic.php

@@ -27,6 +27,7 @@ use app\common\model\master_worker\MasterWorkerAccountLog;
 use app\common\model\master_worker\MasterWorkerRetentionMoneyLog;
 use app\common\model\orders\RechargeOrder;
 use app\common\model\recharge\OrderGoods;
+use app\common\model\service_area\ServiceArea;
 use app\common\model\works\ServiceWork;
 use think\facade\Db;
 

+ 34 - 0
app/adminapi/logic/equity/UserEquityLogic.php

@@ -21,7 +21,9 @@ use app\common\model\equity\UserEquity;
 use app\common\logic\BaseLogic;
 use app\common\model\user\User;
 use app\common\model\works\ServiceWork;
+use app\common\model\works\ServiceWorkLog;
 use think\facade\Db;
+use think\facade\Log;
 use think\facade\Validate;
 
 
@@ -146,4 +148,36 @@ class UserEquityLogic extends BaseLogic
         return ServiceWork::where('user_equity_id',$params['user_equity_id'])->append(['work_status_text'])->select()->toArray();
     }
 
+
+    /**
+     * 取消工单操作-恢复权益次数
+     * @param array $params
+     * @return bool
+     */
+    public static function cancelServiceWorkRestoredNumber(array $params): bool
+    {
+        Db::startTrans();
+        try {
+            $serviceWorkInfo = ServiceWork::find($params['id']);
+            if(empty($serviceWorkInfo['user_equity_id'])){
+                throw new \Exception('该工单非权益卡工单!!!');
+            }
+
+            if((int)$serviceWorkInfo['service_status'] == 4){
+                // 恢复权益次数
+                UserEquity::where('id', $serviceWorkInfo['user_equity_id'])->inc('number')->save();
+            }else{
+                throw new \Exception('该工单非权益卡工单!!!');
+            }
+
+            Db::commit();
+            Log::info('权益卡取消工单'.json_encode([$serviceWorkInfo]));
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            Log::info('权益卡取消工单-Error'.json_encode([$e->getMessage()]));
+            return false;
+        }
+    }
+
 }

+ 20 - 0
app/adminapi/logic/third/ThirdGoodsLogic.php

@@ -57,6 +57,26 @@ class ThirdGoodsLogic extends BaseLogic
         }
     }
 
+    /**
+     * 批量新增
+     * @param $data
+     * @return bool
+     */
+    public static function addMeituanGoods($data)
+    {
+        Db::startTrans();
+        try {
+            $ThirdGoods = new ThirdGoods();
+            $ThirdGoods->saveAll($data);
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
 
     /**
      * @notes 编辑

+ 47 - 2
app/adminapi/logic/works/ServiceWorkLogic.php

@@ -14,7 +14,7 @@
 
 namespace app\adminapi\logic\works;
 
-use app\api\logic\ThirdOrderLogic;
+use app\common\logic\ThirdOrderLogic;
 use app\common\model\third\ThirdOrders;
 use think\Exception;
 use think\db\Query;
@@ -178,6 +178,23 @@ class ServiceWorkLogic extends BaseLogic
             $work->work_status = 4;//已上门
             $work->save();
 
+            //如果是美团订单,且上门时间小于预约时间,则修改预约时间
+            if($work->third_type==1 and $work->finally_door_time<$work->appointment_time){
+                $third_order = ThirdOrders::where('work_id',$work->id)->order('id desc')->findOrEmpty();
+                if(!$third_order->isEmpty()){
+                    ThirdOrderLogic::merchantmodify([
+                        'reserveOrderId'=>$third_order['orderId'],
+                        'reserveUserName'=>$work['real_name'],
+                        "reservePhone"=>$work['mobile'],
+                        "reserveAddress"=>$work['address'],
+                        "bookStartTime"=>$work->finally_door_time*1000,
+                        "bookEndTime"=>($work->finally_door_time+2*3600)*1000,
+                        'request_msg'=>$third_order['request_msg']
+                    ]);
+                }
+            }
+
+
             //添加变更日志
             $work_log = [
                 'work_id'=>$work->id,
@@ -278,7 +295,15 @@ class ServiceWorkLogic extends BaseLogic
             $work->work_total = $work->service_fee+$spare_total;
             $work->work_images = $params['work_images'];
             $work->explanation = $params['explanation']??'';
-            $work->user_confirm_status = 1;//待确认报价
+
+            //判断是否是第三个订单,如果是美团订单直接滤过用户确认环节
+            if($work->third_type==1){
+                $work->work_status = 5;
+                $work->user_confirm_status = 2;
+            }else{
+                $work->user_confirm_status = 1;//待确认报价
+            }
+
             $work->price_approval = 0;
             $work->save();
 
@@ -994,4 +1019,24 @@ class ServiceWorkLogic extends BaseLogic
             return false;
         }
     }
+
+    /**
+     * 上门码和完成码
+     * @param $params
+     * @return false|array
+     */
+    public static function confirmDoorCode($params)
+    {
+        try {
+            $work = ServiceWork::where(['master_worker_id'=>$params['user_id'],'work_sn'=>$params['work_sn']])->findOrEmpty();
+            if($work->isEmpty()){
+                throw new Exception('工单不存在');
+            }
+            $encryptedData = encrypt($params['work_sn'], \think\facade\Config::get('project.work_sn_key'));
+            return ['url'=>\think\facade\Config::get('project.user_website').'?code='.$encryptedData];
+        }catch  (\Exception $e) {
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
 }

+ 10 - 2
app/api/controller/notify/MeiTuanNotifyController.php

@@ -55,11 +55,18 @@ class MeiTuanNotifyController extends BaseApiController
     //到店综合
     /**
      * 取消预订
-     * @return void
+     * @return \think\response\Json
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function cancellation()
     {
         Log::write('取消预订:'.json_encode($this->request->param(),JSON_UNESCAPED_UNICODE));
+        $order = $this->request->param();
+        $order = json_decode('{"opBizCode":"AE7MKOJAV67338LIC3UD0K5TGIO","msgType":"5810001","developerId":"114657","businessId":"58","sign":"82db3112e2603fc65c9165c8c6f63ef2ff9d8f70","msgId":"4531348325686354394","message":"{\"cancelType\":\"1\",\"orderId\":\"61702316\",\"auditChannel\":\"2\",\"type\":\"2\"}","timestamp":"1741940681"}',true);
+        ThirdOrderLogic::cancelOrderHandle($order);
+        return $this->success('取消预订成功');
     }
 
     /**
@@ -256,7 +263,7 @@ class MeiTuanNotifyController extends BaseApiController
         //尾款结算1        //尾款结算3
         //获取工单信息
         $request = $this->request->param();
-//        $request = json_decode('{"opBizCode":"AE7MKOJAV67338LIC3UD0K5TGIO","msgType":"5810031","developerId":"114657","businessId":"58","sign":"1cd993779d2e835ef3582c5e424d52b1d580b2da","msgId":"6219413406543364268","message":"{\"orderId\":\"61374467\",\"verifyStatus\":\"2\",\"verifyChannel\":\"1\",\"type\":\"2\",\"serialNumber\":\"5831711557\"}","timestamp":"1741600285"}',true);
+//        $request = json_decode('{"opBizCode":"AE7MKOJAV67338LIC3UD0K5TGIO","msgType":"5810031","developerId":"114657","businessId":"58","sign":"d43ab164d41859ce7df2894e3e8f086d0c3182cb","msgId":"-1355174693375827369","message":"{\"orderId\":\"61659141\",\"verifyStatus\":\"2\",\"verifyChannel\":\"1\",\"type\":\"2\",\"serialNumber\":\"7843863751\"}","timestamp":"1741927727"}',true);
         Log::write('预订核销同步:'.json_encode($this->request->param(),JSON_UNESCAPED_UNICODE));
         if(!empty($request['message'])){
             Db::startTrans();
@@ -272,6 +279,7 @@ class MeiTuanNotifyController extends BaseApiController
                         $work = ServiceWork::where('id',$order['work_id'])->findOrEmpty();
                         $order->verifyStatus = 2;
                         $order->save();
+
                         if(!$work->isEmpty()){
                             $work->work_pay_status = WorkEnum::IS_PAY_STATUS;
                             $orders = \app\common\model\orders\RechargeOrder::where(['work_id'=>$order->work_id])->select()->toArray();

+ 44 - 0
app/api/controller/notify/UserConfirmController.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace app\api\controller\notify;
+
+use app\adminapi\logic\works\ServiceWorkLogic;
+use app\api\controller\BaseApiController;
+use app\api\validate\UserConfirmValidate;
+use app\common\model\master_worker\MasterWorker;
+use app\common\model\works\ServiceWork;
+use think\Exception;
+
+/**
+ *
+ * Class UserConfirmController
+ * @package app\api\controller\notify
+ */
+class UserConfirmController extends BaseApiController
+{
+
+    public array $notNeedLogin = ['confirmDoor'];
+
+    public function confirmDoor()
+    {
+        $params = (new UserConfirmValidate())->post()->goCheck('confirmDoor');
+        try {
+            $work_sn = decrypt($params['code'], \think\facade\Config::get('project.work_sn_key'));
+            $work = ServiceWork::where(['work_sn'=>$work_sn,'mobile'=>$params['phone']])->findOrEmpty();
+            if($work->isEmpty()){
+                throw new Exception('工单不存在');
+            }
+            $params['user_id'] = $work['master_worker_id'];//工程师信息
+            $params['user_info'] = MasterWorker::where('id',$work['master_worker_id'])->field('worker_number,real_name')->findOrEmpty();//工程师信息
+            $params['work_sn'] = $work_sn;
+            $result = ServiceWorkLogic::confirmDoor($params);
+            if (false === $result) {
+                throw new Exception(ServiceWorkLogic::getError());
+            }
+        }catch (\Exception $e){
+            return $this->fail($e->getMessage());
+        }
+        return $this->success('已确认上门');
+    }
+
+}

+ 8 - 4
app/api/logic/ServiceOrderLogic.php

@@ -181,7 +181,6 @@ class ServiceOrderLogic extends BaseLogic
                 $work_data['data_type'] = 1;
             }
 
-
             $service_work = ServiceWork::create($work_data);
 
 
@@ -1124,6 +1123,8 @@ class ServiceOrderLogic extends BaseLogic
     {
         Db::startTrans();
         try {
+            // 订单位置是否在服务区内
+            $areas = self::isService($params);
             $goods = Goods::findOrEmpty($params['goods_id']);
             if($goods->isEmpty()){
                 throw new Exception('产品不存在!');
@@ -1145,7 +1146,7 @@ class ServiceOrderLogic extends BaseLogic
                 $order_total = $goods['base_service_fee'];
                 $order_amount = $goods['service_fee'];
             }
-            
+
             //生成服务工单
             $work_data = [
                 'work_sn' => generate_sn(ServiceWork::class, 'work_sn'),
@@ -1164,9 +1165,12 @@ class ServiceOrderLogic extends BaseLogic
                 'user_id'=>$params['user_id'],
                 'lon'=>!empty($params['lon'])?$params['lon']:0,
                 'lat'=>!empty($params['lat'])?$params['lat']:0,
+
+                'province' => $areas['province']??0,
+                'city' => $areas['city']??0,
+                'area_name' => $areas['area_name']??'',
+                'service_area_id' => $areas['id']??0,
             ];
-            $service_area_id = ServiceArea::getAreaId(['lon' => $work_data['lon'], 'lat' => $work_data['lat']]);
-            $work_data['service_area_id'] = $service_area_id;
             $service_work = ServiceWork::create($work_data);
             //生成服务订单
             $data = [

+ 58 - 0
app/api/validate/UserConfirmValidate.php

@@ -0,0 +1,58 @@
+<?php
+namespace app\api\validate;
+
+
+use app\common\enum\notice\NoticeEnum;
+use app\common\service\sms\SmsDriver;
+use app\common\validate\BaseValidate;
+
+/**
+ * 用户确认验证器
+ * Class UserValidate
+ * @package app\api\validate
+ */
+class UserConfirmValidate extends BaseValidate
+{
+
+    protected $rule = [
+        'code' => 'require',
+        'phone'=>'require',
+        'sms_code'=>'require|checkConfig',
+    ];
+
+    protected $message = [
+        'code.require' => '参数缺失',
+        'phone.require' => '手机号缺失',
+        'sms_code.require' => '验证码缺失',
+    ];
+
+
+    public function sceneConfirmDoor()
+    {
+        return $this->only(['code','phone','sms_code']);
+    }
+
+    /**
+     * @notes 登录场景相关校验
+     * @param $sms_code
+     * @param $rule
+     * @param $data
+     * @return bool|string
+     * @author 段誉
+     * @date 2022/9/15 14:37
+     */
+    public function checkConfig($sms_code, $rule, $data)
+    {
+        if (!isset($sms_code)) {
+            return '请输入手机验证码';
+        }
+        $code = $data['sms_code'];
+        $smsDriver = new SmsDriver();
+        $result = $smsDriver->verify($data['phone'], $code, NoticeEnum::OTHER_CAPTCHA);
+        if ($result) {
+            return true;
+        }
+        return '验证码错误';
+    }
+
+}

+ 36 - 0
app/common.php

@@ -563,4 +563,40 @@ function getOptionDataByTable($table) {
         $lists = TableDataLogic::$table();
     }
     return $lists??[];
+}
+
+
+//加密函数
+function encrypt($data, $key) {
+    // 生成一个初始化向量(iv)
+    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
+    // 使用AES-256-CBC加密模式进行加密
+    $encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, 0, $iv);
+    // 返回加密后的数据与IV的组合,方便解密时使用
+    return rtrim(strtr(base64_encode($encrypted . '::' . $iv), '+/', '-_'), '=');
+}
+
+//解密函数
+function decrypt($data, $key) {
+    try {
+        // 将 URL 安全的 Base64 编码的数据解码
+        $decoded = base64_decode(strtr($data, '-_', '+/'));
+        list($encrypted_data, $iv) = explode('::', $decoded, 2);
+
+        // 检查 IV 长度是否正确
+        $expectedIvLength = openssl_cipher_iv_length('aes-256-cbc');
+        if (strlen($iv) !== $expectedIvLength) {
+            throw new Exception("IV length is incorrect. Expected {$expectedIvLength} bytes, got " . strlen($iv));
+        }
+
+        // 使用相同的密钥和 IV 来解密数据
+        $decrypted = openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
+        if ($decrypted === false) {
+            throw new Exception("Decryption failed.");
+        }
+        return $decrypted;
+    } catch (Exception $e) {
+        // 捕获并处理异常
+        throw new Exception('参数不合规: ' . $e->getMessage());
+    }
 }

+ 8 - 12
app/common/command/AutomaticDispatch.php

@@ -53,6 +53,7 @@ class AutomaticDispatch extends Command
         $fiveMinutesAgo = time() - 120; // 300 秒 = 2 分钟
         $list = ServiceWork::where('work_status',0)
             ->where('service_status',0)
+            ->where('refund_approval',0)
             ->where('work_pay_status',1)
                     ->where(function ($query) use ($fiveMinutesAgo) {
                         $query->where('exec_time', 0)->whereOr('exec_time', '<', $fiveMinutesAgo);
@@ -99,8 +100,8 @@ class AutomaticDispatch extends Command
      */
     protected function platformWorker($item) {
 
-        // 定义地球半径(单位:米)
-        $earthRadius = 6371;
+        // 定义地球半径(单位:米)
+        $earthRadius = 6371000;
 
         // 定义 Haversine 公式计算距离的 SQL 片段
         $distanceCalculation = "{$earthRadius} * 2 * ASIN(SQRT(
@@ -141,6 +142,7 @@ class AutomaticDispatch extends Command
             ->limit(100)
             ->select()
             ->toArray();
+            //echo MasterWorker::getLastSql();die;
         $queue = [];
         foreach($worker as $key => $value) {  
             //过滤已接过此单的师傅
@@ -150,7 +152,7 @@ class AutomaticDispatch extends Command
             }
         
             //计算地理效率得分
-            $realDistance = bcadd($value['real_distance'],0,2);
+            $realDistance = bcdiv($value['real_distance'],1000,2);
             $travelTime = $realDistance * 2;//预计每公里行驶2分钟
             
             $distanceScore = 100 - ($travelTime * 1.5) - ($realDistance * 5);
@@ -206,8 +208,8 @@ class AutomaticDispatch extends Command
      */
     protected function teamWorker($item) {
        
-        // 地球半径,单位:
-        $earthRadius = 6371;
+        // 地球半径,单位:米
+        $earthRadius = 6371000;
 
         // 定义 Haversine 公式计算距离的 SQL 片段
         $distanceCalculation = "{$earthRadius} * 2 * ASIN(SQRT(
@@ -255,6 +257,7 @@ class AutomaticDispatch extends Command
         ->select()
         ->toArray();
 
+            //echo MasterWorkerTeam::getLastSql();die;
         $minQueue = [];
         $queue = [];
         foreach($worker as $key => $value) {  
@@ -264,13 +267,6 @@ class AutomaticDispatch extends Command
                 continue;
             }
             
-            if ( $value['distance'] > 0) {
-                //校验客户的地址是否在工程师的接单区域内
-                $realDistance = haversineDistance($item['lat'],$item['lon'], $value['lat'],$value['lon'],$value['distance']);
-                if ($realDistance > $value['distance']) {
-                    continue;
-                }
-            }
             if ($value['am_order'] + $value['pm_order'] < $value['min_order']) {
                 $minQueue[] = $value;
             } else {

+ 2 - 1
app/common/enum/notice/NoticeEnum.php

@@ -43,6 +43,7 @@ class NoticeEnum
      */
     const ACCOUNT_PASSWORD =107;
     const WORKER_EXAMINE =108;
+
     /**
      * 指定用户的类型 1:工程师,2:用户
      */
@@ -134,7 +135,7 @@ class NoticeEnum
             //其它
             'OTHER' => self::OTHER_CAPTCHA,
             //工程师入住
-            'GCSSJHM' => self::GCSSJHM_CAPTCHA
+            'GCSSJHM' => self::GCSSJHM_CAPTCHA,
         ];
         return $scene[$tag] ?? '';
     }

+ 113 - 16
app/common/logic/ThirdOrderLogic.php

@@ -13,7 +13,8 @@ use app\common\{enum\GoodsEnum,
     model\third\ThirdGoods,
     model\third\ThirdOrders,
     model\user\User,
-    model\works\ServiceWork};
+    model\works\ServiceWork,
+    model\works\ServiceWorkLog};
 use think\facade\Db;
 use app\common\model\service_area\ServiceArea;
 
@@ -92,7 +93,8 @@ class ThirdOrderLogic extends BaseLogic
             'productId'=>$message['productId'],
             'productName'=>$message['productName'],
             'request_msg'=>json_encode($order,JSON_UNESCAPED_UNICODE),
-            'bookStatus'=>1
+            'bookStatus'=>1,
+            'third_type'=>1,//美团
         ];
 
         //判断美团的预约订单是否生成
@@ -114,7 +116,7 @@ class ThirdOrderLogic extends BaseLogic
         if(!$thirdOrders->isEmpty()){
             $orderData['work_id'] = $thirdOrders->work_id;
         }
-        if(empty($orderData['work_id']) and !$product->isEmpty()){
+        if(empty($orderData['work_id']) and !$product->isEmpty() and !empty($product['goods_id'])){
             $goods = Goods::findOrEmpty($product['goods_id']);
             $pattern = '/(?:省|市)([\w\s]+市)/u';
             Db::startTrans();
@@ -138,7 +140,7 @@ class ThirdOrderLogic extends BaseLogic
                     'goods_category_ids' => $goods['goods_category_ids'],
                     'goods_category_id' => $goods['goods_category_id'],
                     'base_service_fee' => $goods['base_service_fee'],
-                    'service_fee' => $message['amount'],
+                    'service_fee' => $product['product_price'],
                     'work_pay_status'=>WorkEnum::IS_PAY_STATUS,
                     'appointment_time' => strtotime($message['begintime']),
                     'user_id'=>$user['id'],
@@ -147,10 +149,10 @@ class ThirdOrderLogic extends BaseLogic
                     'property_activity_id'=>0,
                     'user_equity_id'=>0,
                     'third_type'=>1,
-                    'work_total'=>$goods['base_service_fee'],
-                    'work_amount'=>$goods['base_service_fee']
+                    'work_total'=>$product['product_price'],
+                    'work_amount'=>$product['product_price']
                 ];
-                $service_area_id = ServiceArea::getAreaId(['lon' => $work_data['lon'], 'lat' => $work_data['lat']]);
+                $service_area_id = ServiceArea::serviceAreaId(['lon' => $work_data['lon'], 'lat' => $work_data['lat']]);
                 $work_data['service_area_id'] = $service_area_id;
                 $service_work = ServiceWork::create($work_data);
 
@@ -166,8 +168,8 @@ class ThirdOrderLogic extends BaseLogic
                     'coupon_id'=>0,
                     'coupon_price'=>0,
                     'pay_way' => 4,
-                    'order_total' => $message['amount'],
-                    'order_amount' => $message['amount'],
+                    'order_total' => $product['product_price'],
+                    'order_amount' => $product['product_price'],
                 ];
                 $order = RechargeOrder::create($data);
                 //生成订单服务详情
@@ -189,7 +191,7 @@ class ThirdOrderLogic extends BaseLogic
                     'goods_payment_type'=>$goods['goods_payment_type'],
                     'base_service_fee' => $goods['base_service_fee'],
                     'service_total' => $goods['service_total'],
-                    'service_fee' => $message['amount'],
+                    'service_fee' => $product['product_price'],
                     'service_image' => $goods['service_image'],
                     'warranty_period'=>$goods['warranty_period'],
                     'fee_schedule' => $goods['fee_schedule'],
@@ -197,7 +199,6 @@ class ThirdOrderLogic extends BaseLogic
                 ]);
 
                 //判断是否是一口价预支付订单,支付成功后生成尾款订单
-                $order_goods = OrderGoods::where('sn',$order->sn)->findOrEmpty();
                 if(!$goods->isEmpty() and $goods->goods_payment_type == 3 and bcsub($goods->base_service_fee,$goods->service_fee,2)>=0){
                     //新增待支付尾款
                     $order_weikuan_data = [
@@ -206,8 +207,8 @@ class ThirdOrderLogic extends BaseLogic
                         'work_id'=>$order['work_id'],
                         'user_id'=>$order['user_id'],
                         'payment_type'=>2,
-                        'order_total'=>bcsub($goods->base_service_fee,$message['amount'],2),
-                        'order_amount'=>bcsub($goods->base_service_fee,$message['amount'],2),
+                        'order_total'=>bcsub($goods->base_service_fee,$product['product_price'],2),
+                        'order_amount'=>bcsub($goods->base_service_fee,$product['product_price'],2),
                         'order_terminal'=>$order['order_terminal']
                     ];
                     \app\common\model\recharge\RechargeOrder::create($order_weikuan_data);
@@ -215,6 +216,8 @@ class ThirdOrderLogic extends BaseLogic
 
                 $thirdOrders->work_id = $service_work->id;
                 $thirdOrders->save();
+
+                self::bookresultcallback($order['opBizCode'],$message['orderId'],2);
                 Db::commit();
             } catch (\Exception $e) {
                 Db::rollback();
@@ -277,7 +280,7 @@ class ThirdOrderLogic extends BaseLogic
                 'work_total'=>$goods['base_service_fee'],
                 'work_amount'=>$goods['base_service_fee']
             ];
-            $service_area_id = ServiceArea::getAreaId(['lon' => $work_data['lon'], 'lat' => $work_data['lat']]);
+            $service_area_id = ServiceArea::serviceAreaId(['lon' => $work_data['lon'], 'lat' => $work_data['lat']]);
             $work_data['service_area_id'] = $service_area_id;
             $service_work = ServiceWork::create($work_data);
 
@@ -374,13 +377,14 @@ class ThirdOrderLogic extends BaseLogic
      * @param $bookStatus
      * @return string
      */
-    public static function bookresultcallback($orderId,$bookStatus=2)
+    public static function bookresultcallback($opBizCode,$orderId,$bookStatus=2)
     {
         //预订结果,2-预订成功,3-预订失败
         $url = 'https://api-open-cater.meituan.com/ddzh/yuding/bookresultcallback';
+        $accessToken = $opBizCode == 'AE7MKOJAV67338LIC3UD0K5TGIO' ? self::shop_token2['accessToken'] : self::shop_token1['accessToken'];
         $data = [
             'timestamp'=>time(),
-            'appAuthToken'=>self::shop_token2['accessToken'],
+            'appAuthToken'=>$accessToken,
             'charset'=>'utf-8',
             'version'=>'2',
             'developerId'=>self::developerId,
@@ -397,4 +401,97 @@ class ThirdOrderLogic extends BaseLogic
         return http_request($url,http_build_query($data));
     }
 
+    /**
+     * 取消预订
+     * @param array
+     * $order
+     * @return bool
+     */
+    public static function cancelOrderHandle(array $order)
+    {
+        $message = json_decode($order['message'], true);
+        $thirdOrders = ThirdOrders::where('orderId',$message['orderId'])->findOrEmpty();
+        Db::startTrans();
+        try {
+            // 04-11-12 不做任何限制强制取消,已支付的费用给工程师余额
+            $serviceWorkInfo = ServiceWork::find($thirdOrders->work_id);
+
+            ServiceWork::where('id', $thirdOrders->work_id)->update([
+                //'work_status' => 9,
+                'service_status' => 4,
+                'remark' => '美团取消预约订单'
+            ]);
+
+            ServiceWorkLog::create([
+                'work_id' => $thirdOrders->work_id,
+                'master_worker_id' => $serviceWorkInfo['master_worker_id'],
+                'opera_log' => "工单:{$serviceWorkInfo['work_sn']}已取消"
+            ]);
+
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 获取美团商品信息
+     * @param $offset
+     * @return string
+     */
+    public static function queryshopdeal($offset=1)
+    {
+        $url = 'https://api-open-cater.meituan.com/ddzh/tuangou/deal/queryshopdeal';
+        $data = [
+            'timestamp'=>time(),
+            'appAuthToken'=>self::shop_token2['accessToken'],
+            'charset'=>'utf-8',
+            'version'=>'2',
+            'developerId'=>self::developerId,
+            'businessId'=>58,
+            'biz'=>json_encode([
+                'offset'=>$offset,
+                'limit'=>100,
+                "source"=>2,
+            ],JSON_UNESCAPED_UNICODE)
+        ];
+        $sign_data = self::get_sign(self::assessKey, $data);
+        $data['sign'] = $sign_data;
+        return http_request($url,http_build_query($data));
+    }
+
+    /**
+     * 商家改约
+     * @param $offset
+     * @return string
+     */
+    public static function merchantmodify($data)
+    {
+        $url = 'https://api-open-cater.meituan.com/ddzh/yuding/lifereserve/merchantmodify';
+        $opBizCode = !empty($data['request_msg'])?json_decode($data['request_msg'],true)['opBizCode']:'';
+        $accessToken = $opBizCode == 'AE7MKOJAV67338LIC3UD0K5TGIO' ? self::shop_token2['accessToken'] : self::shop_token1['accessToken'];
+        $data = [
+            'timestamp'=>time(),
+            'appAuthToken'=>$accessToken,
+            'charset'=>'utf-8',
+            'version'=>'2',
+            'developerId'=>self::developerId,
+            'businessId'=>58,
+            'biz'=>json_encode([
+                'reserveOrderId'=>$data['reserveOrderId'],
+                'reserveUserName'=>$data['reserveUserName'],
+                "reservePhone"=>$data['reservePhone'],
+                "reserveAddress"=>$data['reserveAddress'],
+                "bookStartTime"=>$data['bookStartTime'],
+                "bookEndTime"=>$data['bookEndTime'],
+            ],JSON_UNESCAPED_UNICODE)
+        ];
+        $sign_data = self::get_sign(self::assessKey, $data);
+        $data['sign'] = $sign_data;
+        return http_request($url,http_build_query($data));
+    }
+
 }

+ 5 - 1
app/common/model/master_worker_register/MasterWorkerRegister.php

@@ -17,6 +17,7 @@ namespace app\common\model\master_worker_register;
 
 use app\common\model\BaseModel;
 use app\common\model\dict\DictData;
+use app\common\model\sale\Sale;
 use think\facade\Cache;
 
 
@@ -78,7 +79,10 @@ class MasterWorkerRegister extends BaseModel
         return $status[$data['vehicle_type']] ?? '';
     }
 
-
+    public function sale()
+    {
+        return $this->hasOne(Sale::class, 'id', 'sale_id');
+    }
 
 
 }

+ 1 - 1
app/tenantapi/logic/effective/OrderEffectiveLogLogic.php

@@ -15,6 +15,7 @@
 namespace app\tenantapi\logic\effective;
 
 
+use app\common\model\service_area\ServiceArea;
 use app\tenantapi\logic\works\ServiceWorkLogic;
 use app\common\enum\GoodsEnum;
 use app\common\enum\PayEnum;
@@ -218,7 +219,6 @@ class OrderEffectiveLogLogic extends BaseLogic
                 'work_total'=>0,
                 'work_amount'=>0,
             ];
-
             $service_work = ServiceWork::create($work_data);
 
             //生成支付订单

+ 3 - 0
app/workerapi/controller/InterviewController.php

@@ -4,6 +4,7 @@ namespace app\workerapi\controller;
 
 use think\Request;
 use think\facade\Db;
+use think\facade\Log;
 use app\workerapi\logic\MasterWorkerLogic;
 use app\workerapi\logic\MasterWorkerRegisterLogic;
 use app\common\model\master_worker\MasterWorkerQuestion;
@@ -107,6 +108,7 @@ class InterviewController extends BaseApiController
         $step = $request->post('step');
         // 获取所有 POST 参数
         $data = $request->post('data');
+        Log::write('工程师面试请求: step='.$step.";data=".json_encode($data));
         if ( !in_array($step, [1,2,3,4,5])) {
             return $this->fail('参数错误');
         }
@@ -114,6 +116,7 @@ class InterviewController extends BaseApiController
             return $this->fail('答案不可为空');
         }
          
+        Log::write('工程师面试请求: step='.$step.";data=".json_encode($data));
         $worker_register_id = MasterWorkerRegister::where('id',$worker_register_id)->value('id');
         if (!$worker_register_id) {
             return $this->fail('ID有误');

+ 17 - 0
app/workerapi/controller/WorksController.php

@@ -350,5 +350,22 @@ class WorksController extends BaseApiController
         return $this->success('成功', [], 1, 1);
     }
 
+    /**
+     * 上门码和完成码
+     * @return \think\response\Json
+     */
+    public function showDoorCode(): \think\response\Json
+    {
+        $params = (new ServiceWorkValidate())->get()->goCheck('door', [
+            'user_id' => $this->userId,
+            'user_info' => $this->userInfo
+        ]);
+        $result = ServiceWorkLogic::confirmDoorCode($params);
+        if (false === $result) {
+            return $this->fail(ServiceWorkLogic::getError());
+        }
+        return $this->success('操作成功,工程师已上门,请用户扫码确认', $result, 1, 1);
+    }
+
 
 }

+ 5 - 2
app/workerapi/logic/MasterWorkerRegisterLogic.php

@@ -11,6 +11,7 @@ use app\common\logic\BaseLogic;
 use app\common\model\sale\Sale;
 use app\common\service\ConfigService;
 use think\facade\Config;
+use think\facade\Log;
 
 /**
  * MasterWorkerRegister逻辑
@@ -30,6 +31,7 @@ class MasterWorkerRegisterLogic extends BaseLogic
 
     public static function createMasterWorker(array $params)
     {
+        Log::info('面试创建工程师-101:'.json_encode($params));
         $masterWorkerRegister = MasterWorkerRegister::where('id', $params['worker_register_id'])->findOrEmpty();
         if ($masterWorkerRegister->isEmpty()) {
             return 0;
@@ -47,7 +49,7 @@ class MasterWorkerRegisterLogic extends BaseLogic
             $password = create_password($masterWorkerRegister['mobile'], $passwordSalt);
             $avatar = ConfigService::get('default_image', 'user_avatar');
             
-            $service_area_id = ServiceArea::serviceAreaId(['lon' => $params['lon'], 'lat' => $params['lat']]);
+            $service_area_id = ServiceArea::serviceAreaId(['lon' => $masterWorkerRegister['lon'], 'lat' => $masterWorkerRegister['lat']]);
 
             /*系统自动填写工程师入驻信息(除身份证、银行卡外,代招人、时间段默认全选、合作形式默认全日接单、工作状态默认正常工作、
             结算类型是半月、半径默认5公里、服务类目为空、质保金比例默认15%、质保金缴纳方式分期抵扣、
@@ -85,7 +87,8 @@ class MasterWorkerRegisterLogic extends BaseLogic
             MasterWorkerScore::create([
                 'worker_id' => $masterWorker->id
             ]);
-            MasterWorkerRegister::where('id', $params['worker_register_id'])->update(['worker_id' => $masterWorker->id]);
+            Log::info('面试创建工程师-102:'.$masterWorker->id);
+            MasterWorkerRegister::where('id', $params['worker_register_id'])->update(['worker_id' => $masterWorker->id,'status'=>1]);
             $block_setting = TrainingBlockConfigLogic::getBlockConfig(1);
             TrainingWorkerTaskLogic::add([
                 'master_worker_id' => $masterWorker->id,

+ 3 - 0
config/project.php

@@ -129,4 +129,7 @@ return [
         'be_expire_duration' => 3600,//管理后台token临时过期前时长,自动续期
     ],
 
+    'user_website' => 'https://user.kyjlkj.com/#/',//用户扫码域名
+    'work_sn_key' => 'sdfas4546',//工单key
+
 ];