| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- <?php
- /** 2026-09-11 今日调度测试;默认检查,--apply 整批事务写入,固定批次防重复。 */
- declare(strict_types=1);
- require dirname(__DIR__).'/vendor/autoload.php';
- \Dotenv\Dotenv::createUnsafeMutable(dirname(__DIR__))->load();
- \support\App::loadAllConfig(['route']);
- date_default_timezone_set('Asia/Shanghai');
- use plugin\saiadmin\app\model\water\WaterModel;
- use plugin\saiadmin\app\model\water\WaterSku;
- use plugin\saiadmin\app\model\water\WaterAccount;
- use plugin\saiadmin\app\model\water\WaterEnterprise;
- use plugin\saiadmin\app\model\water\WaterDelivery;
- use plugin\saiadmin\app\model\water\WaterOrder;
- use plugin\saiadmin\app\model\water\WaterLedger;
- use plugin\saiadmin\app\service\WaterBusiness;
- use plugin\saiadmin\app\service\WaterDispatch;
- $batch = 'TEST-WATER-TODAY-20260911';
- $date = '2026-09-11';
- $apply = in_array('--apply', $argv, true);
- $origin = ['origin_address'=>'深圳市南山区南油第四工业区4栋(测试出发点)',
- 'origin_longitude'=>113.924140, 'origin_latitude'=>22.522806];
- // 复用此前高德实查 GCJ-02 坐标;测试企业为虚构名称,园区坐标不代表具体楼栋。
- $places = [
- ['address'=>'深圳市南山区海德一道中洲控股中心(模拟任务,请勿实际配送)','longitude'=>113.935124,'latitude'=>22.516070],
- ['address'=>'深圳市南山区科技园(园区级测试坐标,请勿实际配送)','longitude'=>113.946040,'latitude'=>22.544610],
- ['address'=>'深圳市南山区深圳湾科技生态园(园区级测试坐标,请勿实际配送)','longitude'=>113.952743,'latitude'=>22.530351],
- ];
- $samples = [
- ['name'=>'【测试0911】晨光办公','quantity'=>4,'place'=>0,'state'=>'pending','time'=>'16:00:00'],
- ['name'=>'【测试0911】青禾研发','quantity'=>6,'place'=>1,'state'=>'pending','time'=>'17:00:00'],
- ['name'=>'【测试0911】星海科技','quantity'=>5,'place'=>1,'state'=>'assigned','time'=>'18:00:00'],
- ['name'=>'【测试0911】云帆商务','quantity'=>7,'place'=>0,'state'=>'assigned','time'=>'15:00:00'],
- ['name'=>'【测试0911】绿洲创意','quantity'=>3,'place'=>2,'state'=>'assigned','time'=>'17:00:00'],
- ['name'=>'【测试0911】远景服务','quantity'=>8,'place'=>2,'state'=>'transit','time'=>'18:00:00'],
- ];
- $dispatch = new WaterDispatch();
- $before = $dispatch->board(['date'=>$date])['summary'];
- $replayed = false;
- if ($apply) {
- $replayed = WaterModel::transaction(function () use ($batch,$date,$origin,$places,$samples,$dispatch) {
- $sku = WaterSku::query()->where('name','【测试0910】18.9L桶装水')->lock(true)->first()?->toArray();
- if (!$sku || (int)$sku['status'] !== 1) throw new RuntimeException('缺少启用的指定测试商品');
- if (WaterLedger::query()->where(['kind'=>'demo_seed','reference'=>$batch])->exists()) return true;
- if (date('Y-m-d') !== $date) throw new RuntimeException('固定日期测试批次仅可在对应日期首次执行');
- $business = new WaterBusiness();
- $skuId = (int)$sku['id'];
- $oldTasks = WaterDelivery::query()->orderBy('id')->get()->toArray();
- $oldOrders = WaterOrder::query()->orderBy('id')->get()->toArray();
- $oldAccounts = WaterAccount::query()->orderBy('id')->get()->toArray();
- $total = array_sum(array_column($samples,'quantity'));
- $business->stock(['sku_id'=>$skuId,'mode'=>'inbound','quantity'=>$total,'reference'=>$batch.'-STOCK',
- 'note'=>'【测试数据】今日调度模拟入库33桶,未发生真实入库'],1);
- $taskIds = [];
- foreach ($samples as $index=>$sample) {
- if (WaterEnterprise::query()->where('name',$sample['name'])->exists()) throw new RuntimeException('测试企业重名,停止避免覆盖');
- $place = $places[$sample['place']];
- $enterpriseId = $business->save('enterprise', $place+[
- 'name'=>$sample['name'],'contact'=>'测试联系人'.($index+1),'phone'=>'TEST-0911-'.($index+1),
- 'region'=>'深圳市南山区','status'=>1,
- ],1)['id'];
- WaterAccount::query()->insert(['enterprise_id'=>$enterpriseId,'sku_id'=>$skuId,
- 'entitlement'=>$sample['quantity'],'threshold_qty'=>2,'updated_at'=>date('Y-m-d H:i:s')]);
- WaterLedger::query()->insert(['kind'=>'demo_seed','enterprise_id'=>$enterpriseId,'sku_id'=>$skuId,
- 'quantity'=>$sample['quantity'],'reference'=>$batch.'-RIGHTS-'.($index+1),
- 'note'=>'【测试数据】仅用于今日配送的模拟权益,无真实收款','created_by'=>1,'created_at'=>date('Y-m-d H:i:s')]);
- $id = $business->createDelivery(['enterprise_id'=>$enterpriseId,'sku_id'=>$skuId,'quantity'=>$sample['quantity'],'date'=>$date],1)['id'];
- $dispatch->schedule($origin+['id'=>$id,'date'=>$date,'deadline_at'=>$date.' '.$sample['time'],
- 'longitude'=>$place['longitude'],'latitude'=>$place['latitude']],1);
- $taskIds[] = $id;
- }
- $driverIds = [];
- foreach (['合单体验','三站优化','签收体验'] as $index=>$name) {
- $id = $dispatch->saveDriver(['name'=>'【测试0911】'.$name.'配送员','phone'=>'TEST-0911-DRIVER-'.($index+1),
- 'region'=>'深圳市南山区','capacity'=>30,'vehicle'=>'测试车辆0911-'.($index+1)],1)['id'];
- $dispatch->shift(['driver_id'=>$id,'date'=>$date,'state'=>'on'],1);
- $driverIds[] = $id;
- }
- $routes = $dispatch->commit(['date'=>$date,'request_key'=>$batch,'routes'=>[
- ['driver_id'=>$driverIds[1],'task_ids'=>array_slice($taskIds,2,3)],
- ['driver_id'=>$driverIds[2],'task_ids'=>[$taskIds[5]]],
- ]],1);
- if (count($routes['route_ids']) !== 2) throw new RuntimeException('路线数量不正确');
- $business->transition(['id'=>$taskIds[5],'action'=>'depart'],1);
- $afterSku = WaterSku::query()->where('id',$skuId)->first()->toArray();
- if ((int)$afterSku['available'] !== (int)$sku['available'] || (int)$afterSku['locked'] !== (int)$sku['locked']+25
- || (int)$afterSku['transit'] !== (int)$sku['transit']+8) throw new RuntimeException('测试库存核对失败');
- if (WaterOrder::query()->orderBy('id')->get()->toArray() !== $oldOrders) throw new RuntimeException('原收款订单发生变化');
- foreach ($oldTasks as $row) {
- if (WaterDelivery::query()->find($row['id'])->toArray() !== $row) throw new RuntimeException('原任务发生变化');
- }
- foreach ($oldAccounts as $row) {
- if (WaterAccount::query()->find($row['id'])->toArray() !== $row) throw new RuntimeException('原账户发生变化');
- }
- foreach ($taskIds as $index=>$id) {
- $task = WaterDelivery::query()->find($id)->toArray();
- $account = WaterAccount::query()->where(['enterprise_id'=>$task['enterprise_id'],'sku_id'=>$skuId])->first()->toArray();
- if ($task['status'] !== $samples[$index]['state'] || $task['scheduled_date'] !== $date
- || (int)$account['frozen'] !== $samples[$index]['quantity']) throw new RuntimeException('任务状态或权益不一致');
- }
- WaterLedger::query()->insert(['kind'=>'demo_seed','sku_id'=>$skuId,'quantity'=>0,'reference'=>$batch,
- 'note'=>'【测试数据】今日6单33桶;任务ID:'.implode(',',$taskIds).';2单待派单、3单同路线已派单、1单配送中,无真实收款',
- 'created_by'=>1,'created_at'=>date('Y-m-d H:i:s')]);
- return false;
- });
- }
- $board = $dispatch->board(['date'=>$date]);
- $rows = array_values(array_filter($board['tasks'],fn($task)=>in_array($task['enterprise_name'],array_column($samples,'name'),true)));
- echo json_encode(['mode'=>$apply?'applied':'inspect','date'=>$date,'batch'=>$batch,'replayed'=>$replayed,
- 'before'=>$before,'after'=>$board['summary'],'added_batch'=>array_map(fn($row)=>array_intersect_key($row,array_flip([
- 'id','enterprise_name','quantity','status','scheduled_date','deadline_at','route_id','stop_order','driver',
- ])),$rows),'plan'=>$samples],JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT).PHP_EOL;
|