load(); \support\App::loadAllConfig(['route']); date_default_timezone_set('Asia/Shanghai'); use support\Db; use plugin\saiadmin\app\model\water\WaterModel; use plugin\saiadmin\app\service\WaterBusiness; use plugin\saiadmin\app\service\WaterDispatch; $batch='TEST-WATER-SZ-ROUTES-20260910'; $apply=in_array('--apply',$argv,true); $origin=['origin_address'=>'深圳市南山区南油第四工业区4栋(测试出发点)','origin_longitude'=>113.924140,'origin_latitude'=>22.522806]; // 项目高德 Geocoder 实查 GCJ-02;生态园结果为园区级,不能声称定位到506室。 $targets=[ ['name'=>'【测试0910】科技园配送测试','address'=>'深圳市南山区科技园(地图测试,请勿实际配送)','longitude'=>113.946040,'latitude'=>22.544610,'quantity'=>4,'suffix'=>'KJY'], ['name'=>'【测试0910】生态园10栋506','address'=>'深圳市南山区深圳湾科技生态园10栋506室(地图测试,坐标暂定位园区,请勿实际配送)','longitude'=>113.952743,'latitude'=>22.530351,'quantity'=>6,'suffix'=>'STY'], ]; $replayed=false; if ($apply) { $replayed=WaterModel::transaction(function () use ($batch,$origin,$targets) { $business=new WaterBusiness(); $dispatch=new WaterDispatch(); $sku=\plugin\saiadmin\app\model\water\WaterSku::query()->where('name','【测试0910】18.9L桶装水')->lock(true)->first()?->toArray(); if (!$sku) throw new RuntimeException('缺少指定测试商品'); if (\plugin\saiadmin\app\model\water\WaterLedger::query()->where(['kind'=>'demo_seed','reference'=>$batch])->first()?->toArray()) return true; if ((int)$sku['available']<10) throw new RuntimeException('测试商品可用库存不足10桶'); $skuId=(int)$sku['id']; $date=date('Y-m-d'); $now=date('Y-m-d H:i:s'); $beforeTasks=\plugin\saiadmin\app\model\water\WaterDelivery::query()->orderBy('id')->get()->toArray(); $beforeOrders=\plugin\saiadmin\app\model\water\WaterOrder::query()->orderBy('id')->get()->toArray(); $groups=[]; $taskIds=[]; foreach ($targets as $target) { if (\plugin\saiadmin\app\model\water\WaterEnterprise::query()->where('name',$target['name'])->count()) throw new RuntimeException('存在同名测试企业,停止避免重复'); $enterprise=$business->save('enterprise',[ 'name'=>$target['name'],'contact'=>'地图测试联系人','phone'=>'TEST-MAP-'.$target['suffix'], 'region'=>'深圳市南山区','address'=>$target['address'],'longitude'=>$target['longitude'],'latitude'=>$target['latitude'], ],1)['id']; // 仅发放本次配送所需的测试权益,不制造收款或购套餐订单。 \plugin\saiadmin\app\model\water\WaterAccount::query()->insert(['enterprise_id'=>$enterprise,'sku_id'=>$skuId, 'entitlement'=>$target['quantity'],'threshold_qty'=>2,'updated_at'=>$now]); \plugin\saiadmin\app\model\water\WaterLedger::query()->insert(['kind'=>'demo_seed','enterprise_id'=>$enterprise,'sku_id'=>$skuId, 'quantity'=>$target['quantity'],'reference'=>$batch.'-'.$target['suffix'].'-RIGHTS', 'note'=>'【测试数据】地图配送测试权益,无真实收款','created_by'=>1,'created_at'=>$now]); $task=$business->createDelivery(['enterprise_id'=>$enterprise,'sku_id'=>$skuId,'quantity'=>$target['quantity'],'date'=>$date],1)['id']; \plugin\saiadmin\app\model\water\WaterDelivery::query()->where('id',$task)->update($origin); $driver=$dispatch->saveDriver(['name'=>'【测试】地图配送员-'.$target['suffix'],'phone'=>'TEST-MAP-DRIVER-'.$target['suffix'], 'region'=>'深圳市南山区','capacity'=>20,'vehicle'=>'测试车辆-'.$target['suffix']],1)['id']; $dispatch->shift(['driver_id'=>$driver,'date'=>$date,'state'=>'on'],1); $groups[]=['driver_id'=>$driver,'task_ids'=>[$task]]; $taskIds[]=$task; } $result=$dispatch->commit(['date'=>$date,'request_key'=>$batch,'routes'=>$groups],1); if (count($result['route_ids'])!==2) throw new RuntimeException('未生成两条独立路线'); $after=\plugin\saiadmin\app\model\water\WaterSku::query()->where('id',$skuId)->first()?->toArray(); if ((int)$after['available']!==(int)$sku['available']-10 || (int)$after['locked']!==(int)$sku['locked']+10 || $after['transit']!==$sku['transit']) throw new RuntimeException('库存冻结校验失败'); if (\plugin\saiadmin\app\model\water\WaterOrder::query()->orderBy('id')->get()->toArray()!==$beforeOrders) throw new RuntimeException('原收款订单意外改变'); foreach ($beforeTasks as $task) { if (\plugin\saiadmin\app\model\water\WaterDelivery::query()->where('id',$task['id'])->first()?->toArray()!==$task) throw new RuntimeException('原配送任务意外改变'); } foreach ($taskIds as $id) { $task=\plugin\saiadmin\app\model\water\WaterDelivery::query()->where('id',$id)->first()?->toArray(); $account=\plugin\saiadmin\app\model\water\WaterAccount::query()->where(['enterprise_id'=>$task['enterprise_id'],'sku_id'=>$skuId])->first()?->toArray(); if ($task['status']!=='assigned' || !$task['route_id'] || (int)$account['frozen']!==(int)$task['quantity']) throw new RuntimeException('路线与权益冻结不一致'); } \plugin\saiadmin\app\model\water\WaterLedger::query()->insert(['kind'=>'demo_seed','sku_id'=>$skuId,'quantity'=>0,'reference'=>$batch, 'note'=>'【测试数据】新增科技园4桶、生态园10栋506室6桶两条已派单路线;任务ID:'.implode(',',$taskIds).';生态园为园区级坐标,无真实收款', 'created_by'=>1,'created_at'=>$now]); return false; }); } $rows=\plugin\saiadmin\app\model\water\WaterDelivery::query()->alias('d')->join('sa_water_enterprise as e','e.id','=','d.enterprise_id') ->leftJoin('sa_water_route as r','r.id','=','d.route_id')->whereIn('e.name',array_column($targets,'name')) ->selectRaw('d.id,e.name,d.quantity,d.status,d.address,d.longitude,d.latitude,d.origin_address,d.origin_longitude,d.origin_latitude,d.driver,d.route_id,r.code AS route_code')->orderBy('d.id')->get()->toArray(); echo json_encode(['mode'=>$apply?'applied':'inspect','replayed'=>$replayed,'plan'=>$targets,'deliveries'=>$rows, 'summary'=>(new WaterDispatch())->board(['date'=>date('Y-m-d')])['summary']],JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT).PHP_EOL;