From 4c94392ef648fd15584f794569a094f6218c4ce1 Mon Sep 17 00:00:00 2001 From: mzl Date: Tue, 21 Oct 2025 13:34:26 +0800 Subject: [PATCH] ts --- app/common/service/StockOrdersService_bak.php | 1044 +++++++++++++---- app/common/utils/WsEvents.php | 11 +- .../approval/service/ApprovalFlowService.php | 3 +- plugin/webman/gateway/Events.php | 2 +- 4 files changed, 813 insertions(+), 247 deletions(-) diff --git a/app/common/service/StockOrdersService_bak.php b/app/common/service/StockOrdersService_bak.php index 65ef296..5ee03a9 100644 --- a/app/common/service/StockOrdersService_bak.php +++ b/app/common/service/StockOrdersService_bak.php @@ -12,6 +12,10 @@ use app\common\model\SysCurrency; use support\Request; use app\common\model\User; use support\Db; +use support\Model; +use app\common\model\ApprovalInstances; +use app\common\model\ApprovalRecords; +use support\exception\BusinessException; class StockOrdersService_bak { @@ -63,13 +67,13 @@ class StockOrdersService_bak $config['order']['id'] = 'desc'; - // $config['dataLimit']['type'] = 'relation'; - // $config['dataLimit']['userId'] = $request->user->uid; - // $config['dataLimit']['userField'] = 'salesperson_id'; + // $config['where']['salesperson_id'] = $request->user->uid; break; case 'print': + case 'approval': $config['where']['id'] = $p['id']; break; + case 'detail': case 'show': $config['where']['id'] = $p['id']; @@ -93,113 +97,6 @@ class StockOrdersService_bak return $config; } - - public function serviceStore(Request $request, array $data = []) - { - // 关联表较多,增加事务处理 - return Db::transaction(function () use ($request, $data) { - $data = $this->preProcess('Store', $data, $request); - $dl = $this->getDataLimitFromRequest($request); - $created = $this->logicCreate($data, $dl); // 表1 - - // 车辆 - $cifTotalAmount = 0; - $cifTotalAmountRate = 0; - $cifTotalAmountCurrency = 'CNY'; - // $profit = 0; - foreach ($data['veh_list'] as $veh) { - $veh['order_id'] = $created->id; - - // 唯一标识 - $uniqueIdStr = ""; - $uniqueIdStr .= $veh['sku_id']; - $uniqueIdStr .= $veh['model_snapshot']; - $uniqueIdStr .= $veh['color_interior_code']; - $uniqueIdStr .= $veh['color_exterior_code']; - $uniqueIdStr .= $veh['mileage']; - $uniqueIdStr .= json($veh['modify_list']); - $veh['unique_id'] = md5($uniqueIdStr); - $item = StockOrderItems::create($veh); // 表2 - - // 金额 // 表3 - // $item->addMoney('official_price', $veh['official_price']['currency'], $veh['official_price']['amount'], $veh['official_price']['rate'], '官方指导价'); - // $item->addMoney('discount_price', $veh['discount_price']['currency'], $veh['discount_price']['amount'], $veh['discount_price']['rate'], '优惠价'); - if ($veh['unit_price']['amount']) { - $item->addMoney('unit_price', $veh['unit_price']['currency'], $veh['unit_price']['amount'], $veh['unit_price']['rate'], '单价'); - } - if ($veh['total_price']['amount']) { - $item->addMoney('total_price', $veh['total_price']['currency'], $veh['total_price']['amount'], $veh['total_price']['rate'], '总价'); - } - if ($veh['handling_fee']['amount']) { - $item->addMoney('handling_fee', $veh['handling_fee']['currency'], $veh['handling_fee']['amount'], $veh['handling_fee']['rate'], '手续费'); - } - if ($veh['fob_transport_fee']['amount']) { - $item->addMoney('fob_transport_fee', $veh['fob_transport_fee']['currency'], $veh['fob_transport_fee']['amount'], $veh['fob_transport_fee']['rate'], 'FOB运输费'); - } - if ($veh['port_misc_fee']['amount']) { - $item->addMoney('port_misc_fee', $veh['port_misc_fee']['currency'], $veh['port_misc_fee']['amount'], $veh['port_misc_fee']['rate'], '港杂'); - } - if ($veh['retrofit_fee']['amount']) { - $item->addMoney('retrofit_fee', $veh['retrofit_fee']['currency'], $veh['retrofit_fee']['amount'], $veh['retrofit_fee']['rate'], '改装费'); - } - - // 二手车 or 新车 - if ($veh['mileage'] > 0) { - if ($veh['listing_price']['amount']) { - $item->addMoney('listing_price', $veh['listing_price']['currency'], $veh['listing_price']['amount'], $veh['listing_price']['rate'], '二手挂牌价'); - } - if ($veh['reduction_price']['amount']) { - $item->addMoney('reduction_price', $veh['reduction_price']['currency'], $veh['reduction_price']['amount'], $veh['reduction_price']['rate'], '二手减价'); - } - - $ttPrice = ($veh['listing_price']['amount'] / $created->contract_exchange_rate); - $ddPrice = $veh['reduction_price']['amount']; - } else { - if ($veh['official_price']['amount']) { - $item->addMoney('official_price', $veh['official_price']['currency'], $veh['official_price']['amount'], $veh['official_price']['rate'], '官方指导价'); - } - if ($veh['discount_price']['amount'] ) { - $item->addMoney('discount_price', $veh['discount_price']['currency'], $veh['discount_price']['amount'], $veh['discount_price']['rate'], '优惠价'); - } - - $ttPrice = ($veh['official_price']['amount'] / $created->contract_exchange_rate); - $ddPrice = $veh['discount_price']['amount']; - } - - // 利润 - $profit = (float)$veh['unit_price']['amount'] - (float)$ttPrice - (float)$ddPrice - (float)$veh['handling_fee']['amount'] - (float)$veh['fob_transport_fee']['amount'] - (float)$veh['port_misc_fee']['amount'] - (float)$veh['retrofit_fee']['amount']; - $item->addMoney('profit', $veh['unit_price']['currency'], $profit, $veh['unit_price']['rate'], '利润'); - - // cif_total_amount - $cifTotalAmount += $veh['total_price']['amount']; - $cifTotalAmountRate = $veh['retrofit_fee']['rate']; - $cifTotalAmountCurrency = $veh['retrofit_fee']['currency']; - - // 改装 - if (count($veh['modify_list']) > 0) { - foreach ($veh['modify_list'] as $modify) { - $modify['order_item_id'] = $item->id; - StockOrderItemOptions::create($modify); // 表4 - } - } - } - - // 计算&&插入 表1 - $created->addMoney('cif_total_amount', $cifTotalAmountCurrency, $cifTotalAmount, $cifTotalAmountRate, '合计到岸价'); - - // 账户 - if (count($data['account_list']) > 0) { - foreach ($data['account_list'] as $account) { - $account['order_id'] = $created->id; - $account['remit_date'] = strtotime($account['remit_date']); - StockOrderAccounts::create($account); // 表5 - } - } - - return $this->postProcess('Store', $created); - }); - } - public function beforeServiceStore($data, Request $request) { $userId = $request->user->uid; @@ -210,7 +107,30 @@ class StockOrdersService_bak $data['latest_arrival_date'] = strtotime($data['latest_arrival_date']); $data['salesperson_id'] = $userId; $data['salesperson_snapshot'] = User::where('id', $userId)->value('name') ?? ''; + $data['approval_status'] = $data['approval_status'] == 1 ? 1 : 0; + // if ($data['is_final'] == 1) { + $data['pick_up_date'] = $data['pick_up_date'] ? strtotime($data['pick_up_date']) : 0; + $data['collect_all_date'] = $data['collect_all_date'] ? strtotime($data['collect_all_date']) : 0; + // } + + if ($data['is_final'] == 1) { + // 检查是否至少有一个车辆填写了vin + $hasVin = false; + foreach ($data['veh_list'] as $k => $v) { + if ($v['vin'] != '') { + $hasVin = true; + break; + } + } + // 如果没有任何车辆填写vin,则抛出异常 + if (!$hasVin) { + throw new BusinessException('至少需要为一辆车辆填写vin,才能提交审核'); + } + } + + // 检查绑定 + (new UserService())->checkBind($userId); return $data; } @@ -226,16 +146,27 @@ class StockOrdersService_bak } } // 启动审批 - $appro = new \app\common\utils\approval\service\ApprovalFlowService(); - $result = $appro->start('stock_orders', 'stock_orders', $res->id, $res->toArray(), $res->salesperson_id); - var_dump($result); - - // 异步生成pdf文件 - \Webman\RedisQueue\Redis::send('stock-order-pdf', ['id'=>$res->id]); + if ($res->approval_status == 1) { + $this->startApproval($res); + } return $res; } + /** + * 启动审批 + */ + public function startApproval($item) + { + // 启动审批 + $appro = new \app\common\utils\approval\service\ApprovalFlowService(); + $appro->start('stock_orders', 'stock_orders', $item->id, [], $item->salesperson_id); + // 异步生成pdf文件 + \Webman\RedisQueue\Redis::send('stock-order-pdf', ['id'=>$item->id]); + } + /** + * 创建PDF文件 + */ public function createdPdfFile($id) { $config = []; @@ -248,7 +179,7 @@ class StockOrdersService_bak $config['with'][] = 'moneyValues'; $config['with'][] = 'salesperson'; $item = $this->logicShow($config); - $pdfData = $this->pdfData($item); + $pdfData = $this->formatData($item); // 渲染模板为最终HTML $tplPath = app_path('common/utils/pdf/template/stockOrder.stub'); @@ -269,17 +200,6 @@ class StockOrdersService_bak $fileName ); - // // 在线预览 - // return new \support\Response(200, [ - // 'Content-Type' => 'application/pdf', - // 'Content-Disposition' => 'inline; filename="stock-order.pdf"', - // ], $pdfBin); - - // $url = [ - // 'file_name' => $fileName, - // 'file_url' => getenv('MAIN_DOMAIN').'/pdf/'.$fileName - // ]; - // 上传云端 $param = [ 'path' => $dir . $fileName, @@ -287,7 +207,7 @@ class StockOrdersService_bak 'category' => 'pdf', 'original_name' => $fileName ]; - $up = new UploadService(); + $up = new \app\common\service\UploadService(); $res = $up->uploadLocalFile($param); @unlink($dir . $fileName); @@ -299,6 +219,34 @@ class StockOrdersService_bak return $res; } + + /** + * 查询审批 + */ + public function queryAppro($bizId) + { + $instances = ApprovalInstances::where('biz_id', $bizId)->where('biz_type', 'stock_orders')->first(); + if (!$instances) { + return []; + } + + $records = ApprovalRecords::where('instance_id', $instances->id)->where('action', 'approve')->orderBy('step_index', 'asc')->pluck('approver_id')->toArray(); + if (count($records) == 0) { + return []; + } + + $signImgs = []; + foreach ($records as $k => $v) { + $signImg = User::where('id', $v)->value('sign_img'); + $signImgs[$k] = (!empty($signImg))?(new \app\common\service\OssService)->generatePrivateUrl($signImg):''; + } + + return $signImgs; + } + + /** + * 打印数据 + */ public function servicePrint(Request $request) { $config = $this->buildQueryConfig($request, 'show'); @@ -306,130 +254,744 @@ class StockOrdersService_bak return $this->postProcess('Print', $item); } - - public function pdfData($item) + public function serviceDetail(Request $request) { - $vehList = []; - $index = 0; - foreach ($item->items as $k => $v) { - // 存在则数量加1 - if (count($vehList) > 0 && isset($vehList[$v->unique_id])) { - $vehList[$v->unique_id]['num'] += 1; - $vehList[$v->unique_id]['total_price'] += $vehList[$v->unique_id]['unit_price']; - $vehList[$v->unique_id]['total_price_text'] = $vehList[$v->unique_id]['total_price_symbol'].number_format($vehList[$v->unique_id]['total_price'], 2, '.', ','); - continue; - } - $index += 1; - // 处理金额 - $mv = []; - foreach ($v->moneyValues as $money) { - $mv[$money->field] = [ - 'currency' => $money->currency, - 'amount' => $money->amount, - 'rate' => $money->exchange_rate, - 'currency_symbol' => SysCurrency::where('currency_code', $money->currency)->value('currency_symbol'), - ]; - } - // 处理改装 - $mfy = ''; - foreach ($v->options as $my) { - $mfy .= $my->option_name_snapshot.' '; - } - - // 处理结果集 - $vehList[$v->unique_id] = [ - 'index' => $index, - 'model_snapshot' => $v->model_snapshot, - 'color_interior_snapshot' => $v->color_interior_snapshot, - 'color_exterior_snapshot' => $v->color_exterior_snapshot, - 'num' => 1, - 'modify' => $mfy, - 'mileage' => $v->mileage, - 'unit_price' => $mv['unit_price']['amount'], - 'total_price' => $mv['total_price']['amount'], - 'unit_price_symbol' => $mv['unit_price']['currency_symbol'], - 'total_price_symbol' => $mv['total_price']['currency_symbol'], - 'unit_price_text' => $mv['unit_price']['currency_symbol'].number_format($mv['unit_price']['amount'], 2, '.', ','), - 'total_price_text' => $mv['total_price']['currency_symbol'].number_format($mv['total_price']['amount'], 2, '.', ',') - ]; + $config = $this->buildQueryConfig($request, 'detail'); + $item = $this->logicShow($config); + $detail = $this->formatData($item); + return $this->postProcess('Detail', $detail); + } - // 根据里程处理 新车or二手车 - if ($v->mileage > 0) { - if (isset($mv['reduction_price'])) { - $vehList[$v->unique_id]['reduction_price'] = $mv['reduction_price']['amount']; - $vehList[$v->unique_id]['reduction_price_symbol'] = $mv['reduction_price']['currency_symbol']; - $vehList[$v->unique_id]['reduction_price_text'] = $mv['reduction_price']['currency_symbol'].number_format($mv['reduction_price']['amount'], 2, '.', ','); - } - $vehList[$v->unique_id]['listing_price'] = $mv['listing_price']['amount']; - $vehList[$v->unique_id]['listing_price_symbol'] = $mv['listing_price']['currency_symbol']; - $vehList[$v->unique_id]['listing_price_text'] = $mv['listing_price']['currency_symbol'].number_format($mv['listing_price']['amount'], 2, '.', ','); - } else { - if (isset($mv['discount_price'])) { - $vehList[$v->unique_id]['discount_price'] = $mv['discount_price']['amount']; - $vehList[$v->unique_id]['discount_price_symbol'] = $mv['discount_price']['currency_symbol']; - $vehList[$v->unique_id]['discount_price_text'] = $mv['discount_price']['currency_symbol'].number_format($mv['discount_price']['amount'], 2, '.', ','); - } - $vehList[$v->unique_id]['official_price'] = $mv['official_price']['amount']; - $vehList[$v->unique_id]['official_price_symbol'] = $mv['official_price']['currency_symbol']; - $vehList[$v->unique_id]['official_price_text'] = $mv['official_price']['currency_symbol'].number_format($mv['official_price']['amount'], 2, '.', ','); - } - } + /** + * 审批 + */ + public function serviceApproval(Request $request) + { + $config = $this->buildQueryConfig($request, 'approval'); + $this->logicUpdateBy($config, [ + 'approval_status' => 1 + ]); + $item = $this->logicShow($config); + $this->startApproval($item); + return $this->postProcess('Approval', $item); + } + + /** + * 作废审批 + */ + public function serviceApprovalNullify(Request $request) + { + $config = $this->buildQueryConfig($request, 'approval'); + $item = $this->logicShow($config); + $this->approvalNullify($item); + return $this->postProcess('Approval', $item); + } + + /** + * 审批作废 + */ + public function approvalNullify($item) + { + $appro = new \app\common\utils\approval\service\ApprovalFlowService(); + $appro->startNullify('stock_orders_nullify', 'stock_orders', $item->id, [], $item->salesperson_id); + } + + /** + * 撤销审批 + */ + public function serviceApprovalRevoke(Request $request) + { + $config = $this->buildQueryConfig($request, 'approval'); + $item = $this->logicShow($config); + $this->approvalRevoke($item); + return $this->postProcess('Approval', $item); + } + + public function approvalRevoke($item) + { + $instance = \app\common\model\ApprovalInstances::where('biz_id', $item->id)->where('flow_type', 'stock_orders')->first(); + $appro = new \app\common\utils\approval\service\ApprovalFlowService(); + $appro->revoke($instance->id, $item->salesperson_id); + } + + /** + * 创建 + * + * @param Request $request + * @param array $data + * @return mixed + */ + public function serviceStore(Request $request, array $data = []) + { + // 关联表较多,增加事务处理 + return Db::transaction(function () use ($request, $data) { + $data = $this->preProcess('Store', $data, $request); + $dl = $this->getDataLimitFromRequest($request); + $created = $this->logicCreate($data, $dl); + + // 处理车辆和账户信息 + $this->processOrderItems($created, $data); - $accList = []; - $accIndex = 1; - foreach ($item->accounts as $k => $v) { - $accList[] = [ - 'index' => '收款'.$k + 1, - 'remit_country_name_snapshot' => $v->remit_country_name_snapshot, - 'remit_date' => date('Y-m-d', $v->remit_date), - 'currency_name_snapshot' => $v->currency_name_snapshot, - 'account_name_snapshot' => $v->account_name_snapshot, - 'remitter_name' => $v->remitter_name, - 'amount' => $v->amount, - ]; - $accIndex += 1; + return $this->postProcess('Store', $created); + }); + } + + protected function onlyFillableData(Model|string $model, array $data, array $extraWhitelist = []): array + { + // 兼容传类名或实例 + $m = \is_string($model) ? new $model : $model; + // 1) 优先使用 fillable + $keys = $m->getFillable(); + // 2) 若没配置 fillable(常见:用 guarded),回退到完整表字段,避免误伤 + if (empty($keys)) { + $keys = $m->getConnection() + ->getSchemaBuilder() + ->getColumnListing($m->getTable()); + } + // 3) 允许额外白名单(如虚拟字段、JSON映射字段) + if ($extraWhitelist) { + $keys = array_merge($keys, $extraWhitelist); + } + return array_intersect_key($data, array_flip($keys)); + } + + /** + * 更新前处理 + * + * @param array $data + * @param Request $request + * @return array + */ + public function beforeServiceUpdate($data, Request $request) + { + $data['biz_date'] = strtotime($data['biz_date']); + $data['eta_ship_date'] = strtotime($data['eta_ship_date']); + $data['latest_arrival_date'] = strtotime($data['latest_arrival_date']); + $data['approval_status'] = $data['approval_status'] == 1 ? 1 : 0; + + $data['pick_up_date'] = $data['pick_up_date'] ? strtotime($data['pick_up_date']) : 0; + $data['collect_all_date'] = $data['collect_all_date'] ? strtotime($data['collect_all_date']) : 0; + return $data; + } + + /** + * 更新后处理 + * + * @param mixed $res + * @return mixed + */ + protected function afterServiceUpdate($res) + { + // 启动审批 + if ($res->approval_status == 1) { + $this->startApproval($res); + } + return $res; + } + + /** + * 更新 + * + * @param Request $request + * @param array $data + * @return mixed + */ + public function serviceUpdate(Request $request, array $data = []) + { + // 关联表较多,增加事务处理 + return Db::transaction(function () use ($request, $data) { + $data = $this->preProcess('Update', $data, $request); + $config = $this->buildQueryConfig($request, 'update'); + // 过滤掉非库字段 + $dbData = $this->onlyFillableData($config['model'], $data); + // 更新主表 + $updated = $this->logicUpdateBy($config, $dbData); + // 获取更新后的数据 + $order = $this->logicShow($config); + // 处理车辆和账户信息 + $this->processOrderItems($order, $data, true); + return $this->postProcess('Update', $order); + }); + } + + /** + * 处理订单项(车辆和账户) + * @param StockOrders $order 订单对象 + * @param array $data 数据 + * @param bool $isUpdate 是否为更新操作 + */ + private function processOrderItems($order, array $data, bool $isUpdate = false): void + { + // 如果是更新操作,先删除原有的关联数据 + if ($isUpdate) { + $this->clearExistingOrderItems($order->id); } + // 处理车辆项 + $this->processVehicleItems($order, $data['veh_list'] ?? []); + + // 处理账户项 + $this->processAccountItems($order, $data['account_list'] ?? []); + } + + /** + * (更新时)清除已存在的订单项 + * @param int $orderId 订单ID + */ + private function clearExistingOrderItems(int $orderId): void + { + // 删除车辆改装项 + StockOrderItemOptions::whereHas('item', function ($query) use ($orderId) { + $query->where('order_id', $orderId); + })->delete(); + + // 删除车辆项及其相关金额记录 + $orderItems = StockOrderItems::where('order_id', $orderId)->get(); + foreach ($orderItems as $item) { + // 删除车辆项的金额记录 + Db::table('veh_money_value') + ->where('object_scene', 'stock_order_items') + ->where('object_id', $item->id) + ->delete(); + } + + // 删除车辆项 + StockOrderItems::where('order_id', $orderId)->delete(); + + // 删除订单本身的金额记录 + Db::table('veh_money_value') + ->where('object_scene', 'stock_orders') + ->where('object_id', $orderId) + ->delete(); + + // 删除账户项 + StockOrderAccounts::where('order_id', $orderId)->delete(); + } + + /** + * 处理车辆项 + */ + private function processVehicleItems($order, array $vehList): void + { $cifTotalAmount = 0.00; - if ($item->moneyValues) { - $cifTotalAmountSysboml = SysCurrency::where('currency_code', $item->moneyValues->currency)->value('currency_symbol'); - $cifTotalAmount = $cifTotalAmountSysboml.sprintf("%.2f", $item->moneyValues->amount, $item->moneyValues->exchange_rate); + $profitTotalAmount = 0.00; + foreach ($vehList as $veh) { + $veh['order_id'] = $order->id; + $veh['unique_id'] = $this->generateVehicleUniqueId($veh); + + $item = StockOrderItems::create($veh); + + // 处理金额信息 + $this->processVehiclePrices($item, $veh); + + // 计算利润 + // $profit = $this->calculateProfit($veh, $item->mileage, $order); + // $item->addMoney('profit', $order->settlement_currency, $profit, $order->contract_exchange_rate, '利润'); + + // 累计到岸价 + $cifTotalAmount += $veh['total_price']['amount'] ?? 0; + $profitTotalAmount += $veh['profit']['amount'] ?? 0; + + // 处理改装项 + $this->processModificationItems($item->id, $veh['modify_list'] ?? []); } + // 保存合计到岸价 + $order->addMoney('cif_total_amount', $order->settlement_currency, $cifTotalAmount, $order->contract_exchange_rate, '合计到岸价'); + // 利润 + $order->addMoney('profit_total', $order->settlement_currency, $profitTotalAmount, $order->contract_exchange_rate, '总利润'); + } + + /** + * 生成车辆唯一标识 + */ + private function generateVehicleUniqueId(array $veh): string + { + // $uniqueIdStr = ""; + // $uniqueIdStr .= $veh['sku_id'] ?? ''; + // $uniqueIdStr .= $veh['model_snapshot'] ?? ''; + // $uniqueIdStr .= $veh['color_interior_code'] ?? ''; + // $uniqueIdStr .= $veh['color_exterior_code'] ?? ''; + // $uniqueIdStr .= $veh['mileage'] ?? ''; + // $uniqueIdStr .= json_encode($veh['modify_list'] ?? []); + + $keysToRemove = ['vin', 'remark', 'modify_list', 'order_id']; + $array = array_diff_key($veh, array_flip($keysToRemove)); + $uniqueIdStr = json_encode($array); + + return md5($uniqueIdStr); + } + + /** + * 处理车辆价格信息 + */ + private function processVehiclePrices($item, array $veh): void + { + // unit_price 单价/成交价/收款价 + // total_price 总价 + // handling_fee 手续费 + // fob_transport_fee FOB运输费 + // port_misc_fee 港杂 + // retrofit_fee 改装费 + // ocean_freight 海运费 + // commission 佣金 + // purchase_tax 购置税 + // tax_refund 预估退税 + // clearance_price 报关价 + // profit 利润 + // official_price 官方指导价 + // discount_price 优惠价 + // listing_price 二手挂牌价 + // reduction_price 二手减价/优惠价 + // retention_price 留款/挂账 + // car_price 车价 + // modify_price 改装价 + + // 基础费用 + $priceFields = [ + 'unit_price' => '收款价', + 'total_price' => '总价', + 'handling_fee' => '手续费', + 'fob_transport_fee' => 'FOB运输费', + 'port_misc_fee' => '港杂', + 'retrofit_fee' => '改装费', + 'ocean_freight' => '海运费', + 'commission' => '佣金', + 'purchase_tax' => '购置税', + 'tax_refund' => '预估退税', + 'clearance_price' => '报关价', + 'profit' => '利润', + 'retention_price' => '挂账', + 'car_price' => '车价', + 'modify_price' => '改装价' + ]; + + foreach ($priceFields as $field => $description) { + $item->addMoney( + $field, + $veh[$field]['currency'], + (float)$veh[$field]['amount'], + $veh[$field]['rate'], + $description + ); + } + + // 根据里程处理新车或二手车价格 + if (!empty($veh['mileage']) && $veh['mileage'] > 0) { + // 二手车 + $item->addMoney( + 'listing_price', + $veh['listing_price']['currency'], + (float)$veh['listing_price']['amount'], + $veh['listing_price']['rate'], + '二手挂牌价' + ); + $item->addMoney( + 'reduction_price', + $veh['reduction_price']['currency'], + (float)$veh['reduction_price']['amount'], + $veh['reduction_price']['rate'], + '优惠价' + ); + } else { + // 新车 + $item->addMoney( + 'official_price', + $veh['official_price']['currency'], + (float)$veh['official_price']['amount'], + $veh['official_price']['rate'], + '官方指导价' + ); + $item->addMoney( + 'discount_price', + $veh['discount_price']['currency'], + (float)$veh['discount_price']['amount'], + $veh['discount_price']['rate'], + '优惠价' + ); + } + } + + /** + * 计算利润 + */ + private function calculateProfit(array $veh, int $mileage, $order): float + { + $contractExchangeRate = $order->contract_exchange_rate ?: 1; + + // 提取单价并进行汇率转换(如果需要) + $unitPriceRate = $veh['unit_price']['rate'] ?: 1; + if ($unitPriceRate != $contractExchangeRate) { + $unitPrice = (float)($veh['unit_price']['amount'] ?? 0) / $contractExchangeRate; + } else { + $unitPrice = (float)($veh['unit_price']['amount'] ?? 0); + } + + // 处理主要价格字段,根据是否需要汇率转换来计算 + if ($mileage > 0) { + // 二手车 + $listingPriceRate = $veh['listing_price']['rate'] ?: 1; + if ($listingPriceRate != $contractExchangeRate) { + $ttPrice = ($veh['listing_price']['amount'] ?? 0) / $contractExchangeRate; + } else { + $ttPrice = $veh['listing_price']['amount'] ?? 0; + } + + $reductionPriceRate = $veh['reduction_price']['rate'] ?: 1; + if ($reductionPriceRate != $contractExchangeRate) { + $ddPrice = ($veh['reduction_price']['amount'] ?? 0) / $contractExchangeRate; + } else { + $ddPrice = $veh['reduction_price']['amount'] ?? 0; + } + } else { + // 新车 + $officialPriceRate = $veh['official_price']['rate'] ?: 1; + if ($officialPriceRate != $contractExchangeRate) { + $ttPrice = ($veh['official_price']['amount'] ?? 0) / $contractExchangeRate; + } else { + $ttPrice = $veh['official_price']['amount'] ?? 0; + } + + $discountPriceRate = $veh['discount_price']['rate'] ?: 1; + if ($discountPriceRate != $contractExchangeRate) { + $ddPrice = ($veh['discount_price']['amount'] ?? 0) / $contractExchangeRate; + } else { + $ddPrice = $veh['discount_price']['amount'] ?? 0; + } + } + + // 处理其他费用字段,根据是否需要汇率转换来计算 + $handlingFeeRate = $veh['handling_fee']['rate'] ?: 1; + if ($handlingFeeRate != $contractExchangeRate) { + $handlingFee = (float)($veh['handling_fee']['amount'] ?? 0) / $contractExchangeRate; + } else { + $handlingFee = (float)($veh['handling_fee']['amount'] ?? 0); + } + + $fobTransportFeeRate = $veh['fob_transport_fee']['rate'] ?: 1; + if ($fobTransportFeeRate != $contractExchangeRate) { + $fobTransportFee = (float)($veh['fob_transport_fee']['amount'] ?? 0) / $contractExchangeRate; + } else { + $fobTransportFee = (float)($veh['fob_transport_fee']['amount'] ?? 0); + } + + $portMiscFeeRate = $veh['port_misc_fee']['rate'] ?: 1; + if ($portMiscFeeRate != $contractExchangeRate) { + $portMiscFee = (float)($veh['port_misc_fee']['amount'] ?? 0) / $contractExchangeRate; + } else { + $portMiscFee = (float)($veh['port_misc_fee']['amount'] ?? 0); + } + + $retrofitFeeRate = $veh['retrofit_fee']['rate'] ?: 1; + if ($retrofitFeeRate != $contractExchangeRate) { + $retrofitFee = (float)($veh['retrofit_fee']['amount'] ?? 0) / $contractExchangeRate; + } else { + $retrofitFee = (float)($veh['retrofit_fee']['amount'] ?? 0); + } + + $oceanFreightRate = $veh['ocean_freight']['rate'] ?: 1; + if ($oceanFreightRate != $contractExchangeRate) { + $oceanFreight = (float)($veh['ocean_freight']['amount'] ?? 0) / $contractExchangeRate; + } else { + $oceanFreight = (float)($veh['ocean_freight']['amount'] ?? 0); + } + + $commissionRate = $veh['commission']['rate'] ?: 1; + if ($commissionRate != $contractExchangeRate) { + $commission = (float)($veh['commission']['amount'] ?? 0) / $contractExchangeRate; + } else { + $commission = (float)($veh['commission']['amount'] ?? 0); + } + + $purchaseTaxRate = $veh['purchase_tax']['rate'] ?: 1; + if ($purchaseTaxRate != $contractExchangeRate) { + $purchaseTax = (float)($veh['purchase_tax']['amount'] ?? 0) / $contractExchangeRate; + } else { + $purchaseTax = (float)($veh['purchase_tax']['amount'] ?? 0); + } + + // 预估退税不需要参与汇率转换计算,前端已经计算过了 + $taxRefund = (float)($veh['tax_refund']['amount'] ?? 0); + + // 退税额 是增加利润 + return $unitPrice - $ttPrice + $ddPrice - $handlingFee - $fobTransportFee - $portMiscFee - $retrofitFee - $oceanFreight - $commission - $purchaseTax + $taxRefund; + } + + /** + * 处理改装项 + */ + private function processModificationItems(int $orderItemId, array $modifyList): void + { + if (empty($modifyList)) { + return; + } + + foreach ($modifyList as $modify) { + $modify['order_item_id'] = $orderItemId; + StockOrderItemOptions::create($modify); + } + } + + /** + * 处理账户项 + */ + private function processAccountItems($order, array $accountList): void + { + if (empty($accountList)) { + return; + } + + foreach ($accountList as $account) { + $account['order_id'] = $order->id; + if (!empty($account['remit_date'])) { + $account['remit_date'] = strtotime($account['remit_date']); + } + StockOrderAccounts::create($account); + } + } + + + // ====== ======= ====== ======= ====== 信息处理 ======= ====== ======= ====== ======= + + // PDF数据 + public function formatData($item) + { + // 提取车辆列表信息 + $vehListData = $this->prepareVehicleListData($item); + + // 提取订单金额信息 + $moneyValues = $this->prepareOrderMoneyValues($item); + + // 提取账户列表信息 + $accountList = $this->prepareAccountList($item); + + // 构建返回数据 $veh = [ - 'order_no' => $item->order_no, - 'salesperson_snapshot' => $item->salesperson_snapshot, - // 'sign_img' => $item->salesperson->sign_img, - 'sign_img_url' => (!empty($item->salesperson->sign_img))?(new \app\common\service\OssService)->generatePrivateUrl($item->salesperson->sign_img):'', - 'created_at' => date('Y-m-d', strtotime($item->created_at)), - - 'pi_no' => $item->pi_no, - 'biz_date' => date('Y-m-d', $item->biz_date), - 'clearance_country_snapshot' => $item->clearance_country_snapshot, - 'customer_source_snapshot' => $item->customer_source_snapshot, - 'customer_snapshot' => $item->customer_snapshot, - 'customer_country_snapshot' => $item->customer_country_snapshot, - + // 基本信息 + 'order_no' => $item->order_no, + 'salesperson_snapshot' => $item->salesperson_snapshot, + 'sign_img_url' => $this->getSignatureImageUrl($item->salesperson->sign_img ?? null), + 'created_at' => date('Y-m-d', strtotime($item->created_at)), + + 'pi_no' => $item->pi_no, + 'biz_date' => date('Y-m-d', $item->biz_date), + 'clearance_country_snapshot' => $item->clearance_country_snapshot, + 'customer_source_snapshot' => $item->customer_source_snapshot, + 'customer_snapshot' => $item->customer_snapshot, + 'customer_country_snapshot' => $item->customer_country_snapshot, + // 订单项 - 'veh_list' => $vehList, - - 'contract_exchange_rate' => $item->contract_exchange_rate, - 'cif_total_amount' => $item->cif_total_amount, - - 'declarant_name' => $item->declarant_name, - 'eta_ship_date' => date('Y-m-d', $item->eta_ship_date), - 'shipping_method_snapshot' => $item->shipping_method_snapshot, - 'domestic_port_snapshot' => $item->domestic_port_snapshot, - 'trade_term_snapshot' => $item->trade_term_snapshot, - 'clearance_port_snapshot' => $item->clearance_port_snapshot, - 'latest_arrival_date' => date('Y-m-d', $item->latest_arrival_date), - - // 账户 - 'account_list' => $accList, - 'acc_index' => $accIndex, - 'cif_total_amount' => $cifTotalAmount + 'veh_list' => array_values($vehListData['list']), + 'contract_exchange_rate' => $item->contract_exchange_rate, + 'cif_total_amount' => $moneyValues['cif_total_amount'] ?? [], + 'profit_total' => $moneyValues['profit_total'] ?? [], + + // 运输和交付信息 + 'declarant_name' => $item->declarant_name, + 'eta_ship_date' => date('Y-m-d', $item->eta_ship_date), + 'shipping_method_snapshot' => $item->shipping_method_snapshot, + 'domestic_port_snapshot' => $item->domestic_port_snapshot, + 'trade_term_snapshot' => $item->trade_term_snapshot, + 'clearance_port_snapshot' => $item->clearance_port_snapshot, + 'latest_arrival_date' => date('Y-m-d', $item->latest_arrival_date), + 'pick_up_date' => date('Y-m-d', $item->pick_up_date), + 'collect_all_date' => date('Y-m-d', $item->collect_all_date), + 'is_final' => $item->is_final, + + // 账户信息 + 'account_list' => $accountList, + 'acc_index' => count($accountList) + 1, + 'currency_symbol' => $item->settlement_currency, + 'sign_imgs' => $this->queryAppro($item->id), + 'contract_url' => $this->getContractUrl($item->contract ?? null) ]; return $veh; } + + /** + * 准备车辆列表数据 + */ + private function prepareVehicleListData($item): array + { + $vehList = []; + $index = 0; + $currencyInfo = $this->getCurrencyInfo($item->settlement_currency); + + foreach ($item->items as $v) { + // 如果已存在相同车辆,增加数量 + if (isset($vehList[$v->unique_id])) { + $this->incrementVehicleCount($vehList[$v->unique_id], $currencyInfo); + // 拼接 remark 值 + if (!empty($v->remark)) { + if (!empty($vehList[$v->unique_id]['remark'])) { + $vehList[$v->unique_id]['remark'] .= "; " . $v->remark; + } else { + $vehList[$v->unique_id]['remark'] = $v->remark; + } + } + continue; + } + + $index++; + // 处理金额信息 + $moneyValues = $this->processItemMoneyValues($v); + + // 处理改装信息 + $modificationText = $this->getModificationText($v->options); + + // 计算单项利润 + // $itemProfit = $this->calculateProfit($moneyValues, $v->mileage, $item); + // var_dump($moneyValues); + $itemProfit = empty($moneyValues['profit']['amount']) ? 0 : $moneyValues['profit']['amount']; + + // 构建车辆信息 + $vehList[$v->unique_id] = [ + 'index' => $index, + 'model_snapshot' => $v->model_snapshot, + 'color_interior_snapshot' => $v->color_interior_snapshot, + 'color_exterior_snapshot' => $v->color_exterior_snapshot, + 'num' => 1, + 'modify' => $modificationText, + 'mileage' => $v->mileage, + 'remark' => $v->remark, + ] + $moneyValues; + + // 添加利润信息 + $vehList[$v->unique_id]['profit'] = [ + 'currency' => $item->settlement_currency, + 'amount' => $itemProfit, + 'currency_info' => $currencyInfo['currency_symbol'] . number_format($itemProfit, 2, '.', ',') + ]; + } + + return ['list' => $vehList]; + } + + /** + * 处理单项金额值 + */ + private function processItemMoneyValues($item): array + { + $moneyValues = []; + foreach ($item->moneyValues as $money) { + $moneyValues[$money->field] = [ + 'currency' => $money->currency, + 'amount' => $money->amount, + 'rate' => $money->exchange_rate, + 'currency_info' => $this->formatCurrency($money->amount, $money->currency) + ]; + } + return $moneyValues; + } + + /** + * 获取改装文本 + */ + private function getModificationText($options): string + { + $modificationText = ''; + foreach ($options as $option) { + $modificationText .= $option->option_name_snapshot . ' '; + } + return trim($modificationText); + } + + /** + * 增加车辆数量并更新相关金额显示 + */ + private function incrementVehicleCount(array &$vehicleData, array $currencyInfo): void + { + $vehicleData['num'] += 1; + + // 更新总价显示 + if (isset($vehicleData['total_price']['amount'])) { + $totalAmount = $vehicleData['total_price']['amount'] * $vehicleData['num']; + $vehicleData['total_price']['currency_info'] = $currencyInfo['currency_symbol'] . number_format($totalAmount, 2, '.', ','); + } + + // 更新利润显示 + if (isset($vehicleData['profit']['amount'])) { + $profitAmount = $vehicleData['profit']['amount'] * $vehicleData['num']; + $vehicleData['profit']['currency_info'] = $currencyInfo['currency_symbol'] . number_format($profitAmount, 2, '.', ','); + } + } + + /** + * 准备订单金额值 + */ + private function prepareOrderMoneyValues($item): array + { + $moneyValues = []; + foreach ($item->moneyValues as $money) { + $moneyValues[$money->field] = [ + 'currency' => $money->currency, + 'amount' => $money->amount, + 'rate' => $money->exchange_rate, + 'currency_info' => $this->formatCurrency($money->amount, $money->currency) + ]; + } + return $moneyValues; + } + + /** + * 准备账户列表 + */ + private function prepareAccountList($item): array + { + $accountList = []; + foreach ($item->accounts as $k => $account) { + $accountList[] = [ + 'index' => '收款' . ($k + 1), + 'remit_country_name_snapshot' => $account->remit_country_name_snapshot, + 'remit_date' => date('Y-m-d', $account->remit_date), + 'currency_name_snapshot' => $account->currency_name_snapshot, + 'account_name_snapshot' => $account->account_name_snapshot, + 'remitter_name' => $account->remitter_name, + 'amount' => $account->amount, + ]; + } + return $accountList; + } + + /** + * 获取货币信息 + */ + private function getCurrencyInfo(string $currencyCode): array + { + return SysCurrency::where('currency_code', $currencyCode) + ->first(['currency_symbol', 'currency_name']) + ->toArray(); + } + + /** + * 格式化货币显示 + */ + private function formatCurrency(float $amount, string $currencyCode): string + { + $currencySymbol = SysCurrency::where('currency_code', $currencyCode)->value('currency_symbol'); + return $currencySymbol . number_format($amount, 2, '.', ','); + } + + /** + * 获取签名图片URL + */ + private function getSignatureImageUrl(?string $signImg): string + { + if (empty($signImg)) { + return ''; + } + return (new \app\common\service\OssService)->generatePrivateUrl($signImg); + } + + /** + * 获取合同URL + */ + private function getContractUrl(?string $contract): string + { + if (empty($contract)) { + return ''; + } + return (new \app\common\service\OssService)->generatePrivateUrl($contract); + } } \ No newline at end of file diff --git a/app/common/utils/WsEvents.php b/app/common/utils/WsEvents.php index 5bf4792..b02eb90 100644 --- a/app/common/utils/WsEvents.php +++ b/app/common/utils/WsEvents.php @@ -117,7 +117,7 @@ class WsEvents // 绑定SESSION $_SESSION['uid'] = $user->uid; - $_SESSION['name'] = $user->uname; + // $_SESSION['name'] = $user->uname; // 响应 Gateway::sendToClient($client_id, WsResponse::success( @@ -138,9 +138,12 @@ class WsEvents public function logout(string $client_id) { - if ($_SESSION !== null) { - var_dump($_SESSION); - } + // var_dump('====== ====== ====== start ====== ====== ======'); + // var_dump('关闭客户端ID:'.$client_id); + // if ($_SESSION !== null) { + // var_dump($_SESSION); + // } + // var_dump('====== ====== ====== end ====== ====== ======'); } /** diff --git a/app/common/utils/approval/service/ApprovalFlowService.php b/app/common/utils/approval/service/ApprovalFlowService.php index 6eae8d8..60957f0 100644 --- a/app/common/utils/approval/service/ApprovalFlowService.php +++ b/app/common/utils/approval/service/ApprovalFlowService.php @@ -146,7 +146,8 @@ class ApprovalFlowService 'initiator_id' => $instance->initiator_id, 'status' => $action ]; - \Webman\RedisQueue\Redis::send('approval-callback', $approvalcallback); + $xx = \Webman\RedisQueue\Redis::send('approval-callback', $approvalcallback); + var_dump($xx); // 2) 聚合本步结论(any / all) $typeRaw = strtolower($step['type'] ?? 'all'); diff --git a/plugin/webman/gateway/Events.php b/plugin/webman/gateway/Events.php index 9c6573b..72848ce 100644 --- a/plugin/webman/gateway/Events.php +++ b/plugin/webman/gateway/Events.php @@ -33,7 +33,7 @@ class Events public static function onClose($client_id) { self::$wsEvents->logout($client_id); - var_dump('关闭客户端ID:'.$client_id); + // var_dump('关闭客户端ID:'.$client_id); } } \ No newline at end of file