diff --git a/app/admin/controller/StockOrdersController.php b/app/admin/controller/StockOrdersController.php
index 1d854b1..39806a5 100644
--- a/app/admin/controller/StockOrdersController.php
+++ b/app/admin/controller/StockOrdersController.php
@@ -56,20 +56,60 @@ class StockOrdersController extends BaseController
if (isset($data['created_at'])) $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
if (isset($data['updated_at'])) $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
if (isset($data['eta_ship_date'])) $data['eta_ship_date'] = date('Y-m-d', $data['eta_ship_date']);
- if (isset($data['biz_date'])) $data['biz_date'] = date('Y-m-d', $data['biz_date']);
- if (isset($data['latest_arrival_date'])) $data['latest_arrival_date'] = date('Y-m-d', $data['latest_arrival_date']);
+ if (isset($data['biz_date']) && $data['biz_date'] > 0) $data['biz_date'] = date('Y-m-d', $data['biz_date']);
+ if (isset($data['latest_arrival_date']) && $data['latest_arrival_date'] > 0) $data['latest_arrival_date'] = date('Y-m-d', $data['latest_arrival_date']);
+ if (isset($data['pick_up_date']) && $data['pick_up_date'] > 0) $data['pick_up_date'] = date('Y-m-d', $data['pick_up_date']);
+ if (isset($data['collect_all_date']) && $data['collect_all_date'] > 0) $data['collect_all_date'] = date('Y-m-d', $data['collect_all_date']);
- if (!empty($data['contract'])) {
- $data['contract_url'] = (new \app\common\service\OssService)->generatePrivateUrl($data['contract']);
+ // 处理文件附件
+ $fileTypes = [
+ 'contract' => \app\common\model\StockOrdersFiles::CONTRACT,
+ 'transaction_slip' => \app\common\model\StockOrdersFiles::TRANSACTION_SLIP,
+ 'pi_doc' => \app\common\model\StockOrdersFiles::PI_DOC
+ ];
+
+ // 初始化文件字段
+ foreach (array_keys($fileTypes) as $field) {
+ $data[$field] = [];
+ $data[$field . '_url'] = [];
+ }
+
+ // 按file_code分组文件
+ if (!empty($data['files'])) {
+ $groupedFiles = [];
+ foreach ($data['files'] as $file) {
+ if (!isset($groupedFiles[$file['file_code']])) {
+ $groupedFiles[$file['file_code']] = [];
+ }
+ $groupedFiles[$file['file_code']][] = $file['file_url'];
+ }
+
+ // 映射到对应字段
+ foreach ($fileTypes as $field => $fileCode) {
+ if (isset($groupedFiles[$fileCode])) {
+ // 原始URL数组
+ $data[$field] = $groupedFiles[$fileCode];
+
+ // 完整URL数组
+ $fullUrls = [];
+ foreach ($groupedFiles[$fileCode] as $url) {
+ $fullUrls[] = (new \app\common\service\OssService)->generatePrivateUrl($url);
+ }
+ $data[$field . '_url'] = $fullUrls;
+ }
+ }
+ unset($data['files']);
}
if (count($data['moneyValues']) > 0) {
- $data['cif_total_amount'] = [
- 'exchange_rate' => $data['moneyValues']['exchange_rate'],
- 'amount' => $data['moneyValues']['amount'],
- 'currency' => $data['moneyValues']['currency'],
- 'id' => $data['moneyValues']['id']
- ];
+ foreach ($data['moneyValues'] as $mvs) {
+ $data[$mvs['field']] = [
+ 'exchange_rate' => $mvs['exchange_rate'],
+ 'amount' => $mvs['amount'],
+ 'currency' => $mvs['currency'],
+ 'id' => $mvs['id']
+ ];
+ }
}
foreach ($data['items'] as &$item) {
@@ -153,99 +193,4 @@ class StockOrdersController extends BaseController
return $this->error($e->getMessage());
}
}
-
- public function desc(Request $request)
- {
-
- $data = [
- 'id' => '', //'主键',
- 'order_no' => '', //'备货单编号(业务唯一)',
- 'pi_no' => '', //'PI号'/'阿里订单号',
- 'biz_date' => '', //'单据日期(时间戳)',
- 'salesperson_id' => '', //'业务员ID(关联数据)',
- 'salesperson_snapshot' => '', //'业务员姓名快照',
- 'clearance_country_id' => '', //'清关目的国ID(关联数据)',
- 'clearance_country_snapshot' => '', //'清关目的国名称快照',
- // 'ali_order_no' => '', //'阿里订单号',
- 'customer_source_id' => '', //'客户来源ID(关联数据)',
- 'customer_source_snapshot' => '', //'客户来源名称快照',
- 'customer_id' => '', //'客户ID(关联数据)',
- 'customer_snapshot' => '', //'客户名称快照',
- 'customer_country_id' => '', //'客户所在国ID(关联数据)',
- 'customer_country_snapshot' => '', //'客户所在国名称快照',
- 'declarant_name' => '', //'清关人(文本)',
- 'eta_ship_date' => '', //'预计发运日(时间戳)',
- 'shipping_method' => '', //'出运方式(如海运/空运/铁路等)',
- 'cif_total_amount' => '', //'0.00' COMMENT '合计到岸价(CIF)',
- 'domestic_port_id' => '', //'国内收货港ID(关联数据)',
- 'domestic_port_snapshot' => '', //'国内收货港名称快照',
- 'trade_term_id' => '', //'贸易条款ID(关联数据,EXW/FOB/CIF等)',
- 'trade_term_snapshot' => '', //'贸易条款名称快照',
- 'clearance_port_id' => '', //'清关目的港ID(关联数据)',
- 'clearance_port_snapshot' => '', //'清关目的港名称快照',
- 'latest_arrival_date' => '', //'最迟到港时间(时间戳)',
- 'contract_exchange_rate' => '', //'合同汇率(下单锁定)',
- 'settlement_currency' => '', //'CNY' COMMENT '结算币种',
- 'remark' => '', //'备注',
- // 'real_veh' => '', //'0' COMMENT '实车ID',
- 'is_final' => '', //'0' COMMENT '是否终版1是0否',
- 'status' => '', //'draft' COMMENT '单据状态:draft/submitted/approved/void/reversed等',
- ];
-
- // (?<=\x60 )[^\r\n']*(?=')
-
- $items = [
- // 'id' => '', // '主键',
- // 'order_id' => '', // '所属备货单ID',
- // 'product_code' => '', // '商品编号(可作外部编码)',
- // 'sku_snapshot' => '', // '商品/车型名称快照',
- // 'unit_price_value_id' => '', // '单价',
- // 'handling_fee_value_id' => '', // '操作费',
- // 'fob_transport_fee_value_id' => '', // 'FOB内陆运费',
- // 'port_misc_fee_value_id' => '', // '港杂费',
- // 'retrofit_fee_value_id' => '', // '改装费',
- // 'total_price_value_id' => '', // '合计(按订单结算币计算)',
-
- 'vin' => '', // '车架号',
- 'sku_id' => '', // '商品/车型ID(关联数据)',
- 'model_snapshot' => '', // '车型(若与sku一致可复用;此处为显示快照)',
- 'quantity' => '', // '1.000000' COMMENT '数量',
- 'color_interior_id' => '', // '颜色内饰ID(关联数据)',
- 'color_interior_snapshot' => '', // '颜色内饰名称快照',
- 'color_exterior_id' => '', // '颜色外饰ID(关联数据)',
- 'color_exterior_snapshot' => '', // '颜色外饰名称快照',
- 'remark' => '', // '备注',
- 'unit_price' => '', // '0.000000' COMMENT '单价(含/不含税按业务口径约定)',
- 'handling_fee' => '', // '0.000000' COMMENT '手续费(按单车)',
- 'fob_transport_fee' => '', // '0.000000' COMMENT 'FOB运输费(按单车)',
- 'port_misc_fee' => '', // '0.000000' COMMENT '港杂(按单车)',
- 'retrofit_fee' => '', // '0.000000' COMMENT '改装费(按单车)',
- 'total_price' => '', // '0.000000' COMMENT '总价(quantity*unit_price,写时落地)',
- 'official_price' => '', // 官方指导价
- 'discount_price' => '', // 优惠价
-
-
- 'modify_list' => [
- // 'order_item_id' => '', // '所属明细ID',
- 'option_id' => '', // '配置项ID(关联数据)',
- 'option_name_snapshot' => '', // '配置项名称快照',
- 'option_price' => '', // '配置项价格(可选,写时快照)',
- ]
- ];
-
-
- $account = [
- 'order_id' => '', // '所属备货单ID',
- // 'seq_no' => '', // '1' COMMENT '账户序号(行号)',
- 'remit_country_id' => '', // '汇款国ID(关联数据)',
- 'remit_country_name_snapshot' => '', // '汇款国名称快照',
- 'remit_date' => '', // '汇款日期(时间戳)',
- 'currency_code' => '', // 'USD' COMMENT '币种代码(如USD/CNY/AED等)',
- 'currency_name_snapshot' => '', // '币种名称快照(可选)',
- 'account_id' => '', // '账户ID(关联数据)',
- 'account_name_snapshot' => '', // '账户名称/开户名快照',
- 'remitter_name' => '', // '汇款人',
- 'amount' => '', // '0.00' COMMENT '金额',
- ];
- }
}
\ No newline at end of file
diff --git a/app/common/controller/StockOrdersFilesController.php b/app/common/controller/StockOrdersFilesController.php
new file mode 100644
index 0000000..dfb6a23
--- /dev/null
+++ b/app/common/controller/StockOrdersFilesController.php
@@ -0,0 +1,33 @@
+service = new StockOrdersFilesService();
+ }
+
+ /**
+ * 列表页数据格式化
+ *
+ * @param array $data
+ * @return array
+ */
+ // protected function indexFormat($data)
+ // {
+ // if (isset($data['created_at']))
+ // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
+ // if (isset($data['updated_at']))
+ // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
+ // return $data;
+ // }
+}
\ No newline at end of file
diff --git a/app/common/logic/StockOrdersFilesLogic.php b/app/common/logic/StockOrdersFilesLogic.php
new file mode 100644
index 0000000..3e6c795
--- /dev/null
+++ b/app/common/logic/StockOrdersFilesLogic.php
@@ -0,0 +1,17 @@
+hasMany(VehMoneyValue::class, 'object_id', 'id')->where('object_scene', 'stock_orders');
}
+ /**
+ * 关联订单文件附件
+ */
+ public function files()
+ {
+ return $this->hasMany(StockOrdersFiles::class, 'order_id', 'id');
+ }
+
public function salesperson()
{
diff --git a/app/common/model/StockOrdersFiles.php b/app/common/model/StockOrdersFiles.php
new file mode 100644
index 0000000..98daa3f
--- /dev/null
+++ b/app/common/model/StockOrdersFiles.php
@@ -0,0 +1,60 @@
+ '合同',
+ self::TRANSACTION_SLIP => '水单',
+ self::PI_DOC => 'PI',
+ ];
+}
\ No newline at end of file
diff --git a/app/common/service/StockOrdersFilesService.php b/app/common/service/StockOrdersFilesService.php
new file mode 100644
index 0000000..3b8c91b
--- /dev/null
+++ b/app/common/service/StockOrdersFilesService.php
@@ -0,0 +1,31 @@
+validator;
+ }
+}
\ No newline at end of file
diff --git a/app/common/service/StockOrdersService.php b/app/common/service/StockOrdersService.php
index 730fd02..f243654 100644
--- a/app/common/service/StockOrdersService.php
+++ b/app/common/service/StockOrdersService.php
@@ -15,6 +15,7 @@ use support\Db;
use support\Model;
use app\common\model\ApprovalInstances;
use app\common\model\ApprovalRecords;
+use app\common\model\StockOrdersFiles; // 添加文件附件模型
use support\exception\BusinessException;
class StockOrdersService
@@ -83,6 +84,7 @@ class StockOrdersService
$config['with'][] = 'accounts';
$config['with'][] = 'moneyValues';
$config['with'][] = 'salesperson';
+ $config['with'][] = 'files'; // 添加文件附件关联
break;
case 'store':
break;
@@ -328,10 +330,16 @@ class StockOrdersService
$data = $this->preProcess('Store', $data, $request);
$dl = $this->getDataLimitFromRequest($request);
$created = $this->logicCreate($data, $dl);
+
+ // 添加金额
+ $created->addMoney('cif_total', $data['cif_total']['currency'], $data['cif_total']['amount'], $data['cif_total']['rate'], '合计到岸价');
// 处理车辆和账户信息
$this->processOrderItems($created, $data);
+ // 处理文件附件
+ $this->processOrderFiles($created, $data);
+
return $this->postProcess('Store', $created);
});
}
@@ -410,6 +418,8 @@ class StockOrdersService
$order = $this->logicShow($config);
// 处理车辆和账户信息
$this->processOrderItems($order, $data, true);
+ // 处理文件附件
+ $this->processOrderFiles($order, $data, true);
return $this->postProcess('Update', $order);
});
}
@@ -434,6 +444,62 @@ class StockOrdersService
$this->processAccountItems($order, $data['account_list'] ?? []);
}
+ /**
+ * 处理订单文件附件
+ * @param StockOrders $order 订单对象
+ * @param array $data 数据
+ * @param bool $isUpdate 是否为更新操作
+ */
+ private function processOrderFiles($order, array $data, bool $isUpdate = false): void
+ {
+ // 如果是更新操作,先删除原有的文件附件
+ if ($isUpdate) {
+ $this->clearExistingOrderFiles($order->id);
+ }
+
+ // 处理文件附件项
+ $this->processFileItems($order, $data);
+ }
+
+ /**
+ * (更新时)清除已存在的订单文件附件
+ * @param int $orderId 订单ID
+ */
+ private function clearExistingOrderFiles(int $orderId): void
+ {
+ StockOrdersFiles::where('order_id', $orderId)->delete();
+ }
+
+ /**
+ * 处理文件附件项
+ */
+ private function processFileItems($order, array $data): void
+ {
+ // 定义支持的文件类型
+ $fileTypes = [
+ 'contract' => StockOrdersFiles::CONTRACT,
+ 'transaction_slip' => StockOrdersFiles::TRANSACTION_SLIP,
+ 'pi_doc' => StockOrdersFiles::PI_DOC
+ ];
+
+ // 遍历每种文件类型
+ foreach ($fileTypes as $field => $fileCode) {
+ // 检查数据中是否存在该字段且为数组
+ if (!empty($data[$field]) && is_array($data[$field])) {
+ // 处理该字段下的每个文件
+ foreach ($data[$field] as $fileUrl) {
+ $fileData = [
+ 'order_id' => $order->id,
+ 'file_code' => $fileCode,
+ 'file_url' => $fileUrl,
+ 'file_name' => StockOrdersFiles::FILE_CODE[$fileCode],
+ ];
+ StockOrdersFiles::create($fileData);
+ }
+ }
+ }
+ }
+
/**
* (更新时)清除已存在的订单项
* @param int $orderId 订单ID
@@ -473,8 +539,9 @@ class StockOrdersService
*/
private function processVehicleItems($order, array $vehList): void
{
- $cifTotalAmount = 0.00;
$profitTotalAmount = 0.00;
+ $profitCurrency = '';
+ $profitRate = 0;
foreach ($vehList as $veh) {
$veh['order_id'] = $order->id;
$veh['unique_id'] = $this->generateVehicleUniqueId($veh);
@@ -483,23 +550,18 @@ class StockOrdersService
// 处理金额信息
$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;
+ // $cifTotalAmount += $veh['total_price']['amount'] ?? 0;
+ $profitCurrency === '' ? $profitCurrency = $veh['profit']['currency'] ?? '' : '';
+ $profitRate === 0 ? $profitRate = $veh['profit']['rate'] ?? 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, '总利润');
+ $order->addMoney('profit_total', $profitCurrency, $profitTotalAmount, $profitRate, '总利润');
}
/**
@@ -507,13 +569,9 @@ class StockOrdersService
*/
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);
}
@@ -523,9 +581,29 @@ class StockOrdersService
*/
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 车价
+ // accessory_price 配件费
+
// 基础费用
$priceFields = [
- 'unit_price' => '单价',
+ 'unit_price' => '收款价',
'total_price' => '总价',
'handling_fee' => '手续费',
'fob_transport_fee' => 'FOB运输费',
@@ -536,7 +614,10 @@ class StockOrdersService
'purchase_tax' => '购置税',
'tax_refund' => '预估退税',
'clearance_price' => '报关价',
- 'profit' => '利润'
+ 'profit' => '利润',
+ 'retention_price' => '挂账',
+ 'car_price' => '车价',
+ 'accessory_price' => '配件费'
];
foreach ($priceFields as $field => $description) {
@@ -564,7 +645,7 @@ class StockOrdersService
$veh['reduction_price']['currency'],
(float)$veh['reduction_price']['amount'],
$veh['reduction_price']['rate'],
- '二手减价'
+ '二手优惠价'
);
} else {
// 新车
@@ -585,111 +666,6 @@ class StockOrdersService
}
}
- /**
- * 计算利润
- */
- 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;
- }
-
/**
* 处理改装项
*/
@@ -738,6 +714,9 @@ class StockOrdersService
// 提取账户列表信息
$accountList = $this->prepareAccountList($item);
+ // 提取文件附件列表信息
+ $fileList = $this->prepareFileList($item);
+
// 构建返回数据
$veh = [
// 基本信息
@@ -756,8 +735,8 @@ class StockOrdersService
// 订单项
'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'] ?? [],
+ 'cif_total' => $moneyValues['cif_total'] ?? [],
// 运输和交付信息
'declarant_name' => $item->declarant_name,
@@ -776,7 +755,10 @@ class StockOrdersService
'acc_index' => count($accountList) + 1,
'currency_symbol' => $item->settlement_currency,
'sign_imgs' => $this->queryAppro($item->id),
- 'contract_url' => $this->getContractUrl($item->contract ?? null)
+ 'contract_url' => $this->getContractUrl($item->contract ?? null),
+
+ // 文件附件信息
+ 'file_list' => $fileList
];
return $veh;
@@ -798,7 +780,7 @@ class StockOrdersService
// 拼接 remark 值
if (!empty($v->remark)) {
if (!empty($vehList[$v->unique_id]['remark'])) {
- $vehList[$v->unique_id]['remark'] .= "; " . $v->remark;
+ $vehList[$v->unique_id]['remark'] .= "
" . $v->remark;
} else {
$vehList[$v->unique_id]['remark'] = $v->remark;
}
@@ -811,12 +793,10 @@ class StockOrdersService
$moneyValues = $this->processItemMoneyValues($v);
// 处理改装信息
- $modificationText = $this->getModificationText($v->options);
+ // $modificationText = $this->getModificationText($v->options);
- // 计算单项利润
- // $itemProfit = $this->calculateProfit($moneyValues, $v->mileage, $item);
- // var_dump($moneyValues);
- $itemProfit = empty($moneyValues['profit']['amount']) ? 0 : $moneyValues['profit']['amount'];
+ // 利润
+ // $itemProfit = empty($moneyValues['profit']['amount']) ? 0 : $moneyValues['profit']['amount'];
// 构建车辆信息
$vehList[$v->unique_id] = [
@@ -825,17 +805,17 @@ class StockOrdersService
'color_interior_snapshot' => $v->color_interior_snapshot,
'color_exterior_snapshot' => $v->color_exterior_snapshot,
'num' => 1,
- 'modify' => $modificationText,
+ // 'modify' => $modificationText,
'mileage' => $v->mileage,
'remark' => $v->remark,
] + $moneyValues;
-
+ // var_dump($vehList[$v->unique_id]);
// 添加利润信息
- $vehList[$v->unique_id]['profit'] = [
- 'currency' => $item->settlement_currency,
- 'amount' => $itemProfit,
- 'currency_info' => $currencyInfo['currency_symbol'] . number_format($itemProfit, 2, '.', ',')
- ];
+ // $vehList[$v->unique_id]['profit'] = [
+ // 'currency' => $item->settlement_currency,
+ // 'amount' => $itemProfit,
+ // 'currency_info' => $currencyInfo['currency_symbol'] . number_format($itemProfit, 2, '.', ',')
+ // ];
}
return ['list' => $vehList];
@@ -877,16 +857,38 @@ class StockOrdersService
{
$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['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, '.', ',');
+ // // 更新利润显示
+ // if (isset($vehicleData['profit']['amount'])) {
+ // $profitAmount = $vehicleData['profit']['amount'] * $vehicleData['num'];
+ // $vehicleData['profit']['currency_info'] = $currencyInfo['currency_symbol'] . number_format($profitAmount, 2, '.', ',');
+ // }
+
+ // var_dump($vehicleData);
+
+ $fieldList = [
+ 'fob_transport_fee',
+ 'car_price',
+ 'ocean_freight',
+ 'commission',
+ 'retention_price',
+ 'port_misc_fee',
+ 'total_price',
+ 'clearance_price',
+ 'profit'
+ ];
+
+ foreach ($vehicleData as $field => $value) {
+ if (in_array($field, $fieldList)) {
+ $amount = $vehicleData[$field]['amount'] * $vehicleData['num'];
+ $currencySymbol = SysCurrency::where('currency_code', $vehicleData[$field]['currency'])->value('currency_symbol');
+ $vehicleData[$field]['currency_info'] = $currencySymbol . number_format($amount, 2, '.', ',');
+ }
}
}
@@ -927,6 +929,45 @@ class StockOrdersService
return $accountList;
}
+ /**
+ * 准备文件附件列表
+ */
+ private function prepareFileList($item): array
+ {
+ $fileList = [];
+
+ // 按file_code分组文件
+ $groupedFiles = [];
+ foreach ($item->files as $file) {
+ if (!isset($groupedFiles[$file->file_code])) {
+ $groupedFiles[$file->file_code] = [];
+ }
+ $groupedFiles[$file->file_code][] = [
+ 'id' => $file->id,
+ 'file_url' => $file->file_url,
+ 'file_full_url' => $this->getFileUrl($file->file_url),
+ ];
+ }
+
+ // 定义支持的文件类型
+ $fileTypes = [
+ 'contract' => StockOrdersFiles::CONTRACT,
+ 'transaction_slip' => StockOrdersFiles::TRANSACTION_SLIP,
+ 'pi_doc' => StockOrdersFiles::PI_DOC
+ ];
+
+ // 按前端需要的字段组织数据
+ foreach ($fileTypes as $field => $fileCode) {
+ if (isset($groupedFiles[$fileCode])) {
+ $fileList[$field] = $groupedFiles[$fileCode];
+ } else {
+ $fileList[$field] = [];
+ }
+ }
+
+ return $fileList;
+ }
+
/**
* 获取货币信息
*/
@@ -967,4 +1008,15 @@ class StockOrdersService
}
return (new \app\common\service\OssService)->generatePrivateUrl($contract);
}
+
+ /**
+ * 获取文件URL
+ */
+ private function getFileUrl(?string $fileUrl): string
+ {
+ if (empty($fileUrl)) {
+ return '';
+ }
+ return (new \app\common\service\OssService)->generatePrivateUrl($fileUrl);
+ }
}
\ No newline at end of file
diff --git a/app/common/service/StockOrdersService_bak.php b/app/common/service/StockOrdersService_bak.php
deleted file mode 100644
index 5ee03a9..0000000
--- a/app/common/service/StockOrdersService_bak.php
+++ /dev/null
@@ -1,997 +0,0 @@
-validator;
- }
-
-
- protected function buildQueryConfig(Request $request, string $scene = 'index'): array
- {
- $p = $request->all();
-
- $config = [];
- $config['model'] = $this->modelClass;
- switch ($scene) {
- case 'index':
-
- // ====== ====== 筛选 ====== ======
- // 业务id
- if (isset($p['salesperson_id']) && $p['salesperson_id']) {
- $config['where']['salesperson_id'] = $p['salesperson_id'];
- }
- // 初、终版
- $config['where']['is_final'] = $p['is_final'] ?? 0;
- // 关键字
- if (isset($p['keyword']) && $p['keyword']) {
- $k = '%' . $p['keyword'] . '%';
- foreach (['pi_no', 'order_no', 'customer_snapshot'] as $col) {
- $config['orWhere'][] = [$col, 'like', $k];
- }
- }
-
- $config['order']['id'] = 'desc';
-
- // $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'];
-
- $config['with'][] = 'items';
- $config['with'][] = 'items.options';
- $config['with'][] = 'items.moneyValues';
- $config['with'][] = 'accounts';
- $config['with'][] = 'moneyValues';
- $config['with'][] = 'salesperson';
- break;
- case 'store':
- break;
- case 'update':
- $config['where']['id'] = $p['id'];
- break;
- case 'destroy':
- $config['where']['id'] = $p['id'];
- break;
- }
-
- return $config;
- }
-
- public function beforeServiceStore($data, Request $request)
- {
- $userId = $request->user->uid;
-
- $data['order_no'] = generateStockNo();
- $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['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;
- }
-
- protected function afterServiceStore($res)
- {
- // 处理原单
- if ($res->is_final == 1 && $res->object_id > 0) {
- $order = StockOrders::find($res->object_id);
- $order->is_use = 1;
- $order->object_id = $res->id;
- if (!$order->save()) {
- flg('备货单【'.$order->order_no.'】创建终版成功,但更新原单失败');
- }
- }
- // 启动审批
- 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 = [];
- $config['model'] = $this->modelClass;
- $config['where']['id'] = $id;
- $config['with'][] = 'items';
- $config['with'][] = 'items.options';
- $config['with'][] = 'items.moneyValues';
- $config['with'][] = 'accounts';
- $config['with'][] = 'moneyValues';
- $config['with'][] = 'salesperson';
- $item = $this->logicShow($config);
- $pdfData = $this->formatData($item);
-
- // 渲染模板为最终HTML
- $tplPath = app_path('common/utils/pdf/template/stockOrder.stub');
- $html = \app\common\utils\pdf\service\PdfHelper::render($tplPath, ['data' => $pdfData]);
-
- // 生成PDF
- $driver = new \app\common\utils\pdf\service\MpdfDriver();
- $pdfBin = $driver->htmlToPdf($html);
-
- // 存储
- $dir = public_path('pdf').'/';
- $fileName = ($pdfData['order_no'] ?? date('YmdHis')) . '.pdf';
-
- // 本地保存
- \app\common\utils\pdf\service\PdfStorage::saveBinary(
- $pdfBin,
- $dir,
- $fileName
- );
-
- // 上传云端
- $param = [
- 'path' => $dir . $fileName,
- 'scene' => 'stock_orders',
- 'category' => 'pdf',
- 'original_name' => $fileName
- ];
- $up = new \app\common\service\UploadService();
- $res = $up->uploadLocalFile($param);
-
- @unlink($dir . $fileName);
-
- // 更新文件地址
- $item->file_url = $res['file_name'];
- $item->save();
-
- 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');
- $item = $this->logicShow($config);
- return $this->postProcess('Print', $item);
- }
-
- public function serviceDetail(Request $request)
- {
- $config = $this->buildQueryConfig($request, 'detail');
- $item = $this->logicShow($config);
- $detail = $this->formatData($item);
- return $this->postProcess('Detail', $detail);
- }
-
- /**
- * 审批
- */
- 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);
-
- 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;
- $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_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' => 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/approval/service/ApprovalFlowService.php b/app/common/utils/approval/service/ApprovalFlowService.php
index 60957f0..6eae8d8 100644
--- a/app/common/utils/approval/service/ApprovalFlowService.php
+++ b/app/common/utils/approval/service/ApprovalFlowService.php
@@ -146,8 +146,7 @@ class ApprovalFlowService
'initiator_id' => $instance->initiator_id,
'status' => $action
];
- $xx = \Webman\RedisQueue\Redis::send('approval-callback', $approvalcallback);
- var_dump($xx);
+ \Webman\RedisQueue\Redis::send('approval-callback', $approvalcallback);
// 2) 聚合本步结论(any / all)
$typeRaw = strtolower($step['type'] ?? 'all');
diff --git a/app/common/utils/pdf/template/stockOrder copy.stub b/app/common/utils/pdf/template/stockOrder copy.stub
index 8a2dbf5..43f887f 100644
--- a/app/common/utils/pdf/template/stockOrder copy.stub
+++ b/app/common/utils/pdf/template/stockOrder copy.stub
@@ -110,7 +110,7 @@
| 阿里订单号/PI号: |
日期: |
- 关目的国: |
+ 清关目的国: |
客户来源: |
客户名称: |
客户所在国: |
@@ -144,6 +144,7 @@
优惠 |
单价 |
总价 |
+ 报关价 |
利润 |
@@ -163,16 +164,22 @@
|
0): ?>
- |
- |
+ |
+ |
- |
- |
+ |
+ |
- |
- |
- |
+ |
+ |
+ |
+ |
+
+
+ |
+ 备注:
+ |
@@ -180,8 +187,8 @@
合同汇率:
|
-
- 合计到岸价:
+ |
+ 合计到岸价:
|
@@ -275,8 +282,8 @@
备发货负责人签字:
-
-
; ?>)
+
+
@@ -287,8 +294,8 @@
组长签字:
-
-
; ?>)
+
+
diff --git a/app/common/utils/pdf/template/stockOrder.stub b/app/common/utils/pdf/template/stockOrder.stub
index 43f887f..20b10b3 100644
--- a/app/common/utils/pdf/template/stockOrder.stub
+++ b/app/common/utils/pdf/template/stockOrder.stub
@@ -120,49 +120,40 @@
-
-
-
-
-
-
-
-
-
-
-
-
| 编号 |
车型 |
数量/台 |
颜色/外 |
- 内饰 |
- 改装 |
- 官方指导价/二手挂牌价 |
- 优惠 |
- 单价 |
- 总价 |
- 报关价 |
- 利润 |
+ 颜色/内 |
+ 收款价 |
+ 总价 |
+ 官方指导价/二手挂牌价 |
+ 优惠 |
+ 利润 |
- |
-
+ |
+
+ |
+
0): ?>
()
|
- |
+
+
+ |
|
|
- |
-
+ |
+ |
+
0): ?>
|
|
@@ -170,28 +161,47 @@
|
|
-
- |
- |
- |
- |
+
+ |
+
+
+ | 改装费 |
+ FOB运费 |
+ 车价 |
+ 海运费 |
+ 佣金 |
+ 挂账 |
+ 港杂 |
- |
- 备注:
+ | |
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+ |
+ 备注:
+ |
+
+
|
-
+
+
- |
+ |
合同汇率:
|
-
- 合计到岸价:
+ |
+ 合计到岸价:
|
-
+
diff --git a/app/common/utils/pdf/template/stockOrder_bak.stub b/app/common/utils/pdf/template/stockOrder_bak.stub
deleted file mode 100644
index 6b93ecc..0000000
--- a/app/common/utils/pdf/template/stockOrder_bak.stub
+++ /dev/null
@@ -1,255 +0,0 @@
-
-
-
-
-
合塑实业-汽车事业部-备货单(客户下定)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | 阿里订单号/PI号: |
- 日期: |
- 关目的国: |
- 客户来源: |
- 客户名称: |
- 客户所在国: |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | 编号 |
- 车型 |
- 数量/台 |
- 颜色/外 |
- 内饰 |
- 改装 |
- 单价 |
- 总价 |
- 官方指导价/二手挂牌价 |
- 优惠/二手减价 |
-
-
-
-
-
- |
- |
- |
- |
- |
- |
- |
- |
-
- 0): ?>
- |
- |
-
- |
- |
-
-
-
-
-
-
- |
- 合同汇率:
- |
-
- 合计到岸价:
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | 清关人: |
- 预计发运日期: |
- 出运方式: |
- 国内收货港: |
- 贸易条款/清关目的港: / |
- 最迟到港时间: |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | 计划收款信息 |
- 序号 |
- 汇款国 |
- 日期 |
- 币种 |
- 账户 |
- 汇款人 |
- 金额 |
-
-
-
-
-
- |
- |
- |
- |
- |
- |
- |
-
-
-
-
-
-
-
-
-
下单人:
-
; ?>)
-
-
-
下单时间:
-
-
-
-
-
\ No newline at end of file
diff --git a/app/common/validate/StockOrdersFilesValidate.php b/app/common/validate/StockOrdersFilesValidate.php
new file mode 100644
index 0000000..c7fca82
--- /dev/null
+++ b/app/common/validate/StockOrdersFilesValidate.php
@@ -0,0 +1,29 @@
+ [
+
+ ],
+
+ 'update' => [
+
+ ]
+ ];
+}
\ No newline at end of file
diff --git a/app/controller/IndexController.php b/app/controller/IndexController.php
index 10969ac..72532c7 100644
--- a/app/controller/IndexController.php
+++ b/app/controller/IndexController.php
@@ -74,25 +74,25 @@ class IndexController
$options = [
'controller' => [
'module' => 'common',
- 'name' => 'user_group_members'
+ 'name' => 'stock_orders_files'
],
'model' => [
'module' => 'common',
- 'name' => 'user_group_members'
+ 'name' => 'stock_orders_files'
],
'service' => [
'module' => 'common',
- 'name' => 'user_group_members'
+ 'name' => 'stock_orders_files'
],
'logic' => [
'module' => 'common',
- 'name' => 'user_group_members'
+ 'name' => 'stock_orders_files'
],
'validate' => [
'module' => 'common',
- 'name' => 'user_group_members'
+ 'name' => 'stock_orders_files'
],
- 'table' => 'user_group_members'
+ 'table' => 'stock_orders_files'
];
$result = (new Generate($options))->doGenerate();
diff --git a/app/crm/controller/StockOrdersController.php b/app/crm/controller/StockOrdersController.php
index b297b51..3716c69 100644
--- a/app/crm/controller/StockOrdersController.php
+++ b/app/crm/controller/StockOrdersController.php
@@ -61,8 +61,44 @@ class StockOrdersController extends BaseController
if (isset($data['pick_up_date']) && $data['pick_up_date'] > 0) $data['pick_up_date'] = date('Y-m-d', $data['pick_up_date']);
if (isset($data['collect_all_date']) && $data['collect_all_date'] > 0) $data['collect_all_date'] = date('Y-m-d', $data['collect_all_date']);
- if (!empty($data['contract'])) {
- $data['contract_url'] = (new \app\common\service\OssService)->generatePrivateUrl($data['contract']);
+ // 处理文件附件
+ $fileTypes = [
+ 'contract' => \app\common\model\StockOrdersFiles::CONTRACT,
+ 'transaction_slip' => \app\common\model\StockOrdersFiles::TRANSACTION_SLIP,
+ 'pi_doc' => \app\common\model\StockOrdersFiles::PI_DOC
+ ];
+
+ // 初始化文件字段
+ foreach (array_keys($fileTypes) as $field) {
+ $data[$field] = [];
+ $data[$field . '_url'] = [];
+ }
+
+ // 按file_code分组文件
+ if (!empty($data['files'])) {
+ $groupedFiles = [];
+ foreach ($data['files'] as $file) {
+ if (!isset($groupedFiles[$file['file_code']])) {
+ $groupedFiles[$file['file_code']] = [];
+ }
+ $groupedFiles[$file['file_code']][] = $file['file_url'];
+ }
+
+ // 映射到对应字段
+ foreach ($fileTypes as $field => $fileCode) {
+ if (isset($groupedFiles[$fileCode])) {
+ // 原始URL数组
+ $data[$field] = $groupedFiles[$fileCode];
+
+ // 完整URL数组
+ $fullUrls = [];
+ foreach ($groupedFiles[$fileCode] as $url) {
+ $fullUrls[] = (new \app\common\service\OssService)->generatePrivateUrl($url);
+ }
+ $data[$field . '_url'] = $fullUrls;
+ }
+ }
+ unset($data['files']);
}
if (count($data['moneyValues']) > 0) {
@@ -223,99 +259,4 @@ class StockOrdersController extends BaseController
return $this->error($e->getMessage());
}
}
-
- public function desc(Request $request)
- {
-
- $data = [
- 'id' => '', //'主键',
- 'order_no' => '', //'备货单编号(业务唯一)',
- 'pi_no' => '', //'PI号'/'阿里订单号',
- 'biz_date' => '', //'单据日期(时间戳)',
- 'salesperson_id' => '', //'业务员ID(关联数据)',
- 'salesperson_snapshot' => '', //'业务员姓名快照',
- 'clearance_country_id' => '', //'清关目的国ID(关联数据)',
- 'clearance_country_snapshot' => '', //'清关目的国名称快照',
- // 'ali_order_no' => '', //'阿里订单号',
- 'customer_source_id' => '', //'客户来源ID(关联数据)',
- 'customer_source_snapshot' => '', //'客户来源名称快照',
- 'customer_id' => '', //'客户ID(关联数据)',
- 'customer_snapshot' => '', //'客户名称快照',
- 'customer_country_id' => '', //'客户所在国ID(关联数据)',
- 'customer_country_snapshot' => '', //'客户所在国名称快照',
- 'declarant_name' => '', //'清关人(文本)',
- 'eta_ship_date' => '', //'预计发运日(时间戳)',
- 'shipping_method' => '', //'出运方式(如海运/空运/铁路等)',
- 'cif_total_amount' => '', //'0.00' COMMENT '合计到岸价(CIF)',
- 'domestic_port_id' => '', //'国内收货港ID(关联数据)',
- 'domestic_port_snapshot' => '', //'国内收货港名称快照',
- 'trade_term_id' => '', //'贸易条款ID(关联数据,EXW/FOB/CIF等)',
- 'trade_term_snapshot' => '', //'贸易条款名称快照',
- 'clearance_port_id' => '', //'清关目的港ID(关联数据)',
- 'clearance_port_snapshot' => '', //'清关目的港名称快照',
- 'latest_arrival_date' => '', //'最迟到港时间(时间戳)',
- 'contract_exchange_rate' => '', //'合同汇率(下单锁定)',
- 'settlement_currency' => '', //'CNY' COMMENT '结算币种',
- 'remark' => '', //'备注',
- // 'real_veh' => '', //'0' COMMENT '实车ID',
- 'is_final' => '', //'0' COMMENT '是否终版1是0否',
- 'status' => '', //'draft' COMMENT '单据状态:draft/submitted/approved/void/reversed等',
- ];
-
- // (?<=\x60 )[^\r\n']*(?=')
-
- $items = [
- // 'id' => '', // '主键',
- // 'order_id' => '', // '所属备货单ID',
- // 'product_code' => '', // '商品编号(可作外部编码)',
- // 'sku_snapshot' => '', // '商品/车型名称快照',
- // 'unit_price_value_id' => '', // '单价',
- // 'handling_fee_value_id' => '', // '操作费',
- // 'fob_transport_fee_value_id' => '', // 'FOB内陆运费',
- // 'port_misc_fee_value_id' => '', // '港杂费',
- // 'retrofit_fee_value_id' => '', // '改装费',
- // 'total_price_value_id' => '', // '合计(按订单结算币计算)',
-
- 'vin' => '', // '车架号',
- 'sku_id' => '', // '商品/车型ID(关联数据)',
- 'model_snapshot' => '', // '车型(若与sku一致可复用;此处为显示快照)',
- 'quantity' => '', // '1.000000' COMMENT '数量',
- 'color_interior_id' => '', // '颜色内饰ID(关联数据)',
- 'color_interior_snapshot' => '', // '颜色内饰名称快照',
- 'color_exterior_id' => '', // '颜色外饰ID(关联数据)',
- 'color_exterior_snapshot' => '', // '颜色外饰名称快照',
- 'remark' => '', // '备注',
- 'unit_price' => '', // '0.000000' COMMENT '单价(含/不含税按业务口径约定)',
- 'handling_fee' => '', // '0.000000' COMMENT '手续费(按单车)',
- 'fob_transport_fee' => '', // '0.000000' COMMENT 'FOB运输费(按单车)',
- 'port_misc_fee' => '', // '0.000000' COMMENT '港杂(按单车)',
- 'retrofit_fee' => '', // '0.000000' COMMENT '改装费(按单车)',
- 'total_price' => '', // '0.000000' COMMENT '总价(quantity*unit_price,写时落地)',
- 'official_price' => '', // 官方指导价
- 'discount_price' => '', // 优惠价
-
-
- 'modify_list' => [
- // 'order_item_id' => '', // '所属明细ID',
- 'option_id' => '', // '配置项ID(关联数据)',
- 'option_name_snapshot' => '', // '配置项名称快照',
- 'option_price' => '', // '配置项价格(可选,写时快照)',
- ]
- ];
-
-
- $account = [
- 'order_id' => '', // '所属备货单ID',
- // 'seq_no' => '', // '1' COMMENT '账户序号(行号)',
- 'remit_country_id' => '', // '汇款国ID(关联数据)',
- 'remit_country_name_snapshot' => '', // '汇款国名称快照',
- 'remit_date' => '', // '汇款日期(时间戳)',
- 'currency_code' => '', // 'USD' COMMENT '币种代码(如USD/CNY/AED等)',
- 'currency_name_snapshot' => '', // '币种名称快照(可选)',
- 'account_id' => '', // '账户ID(关联数据)',
- 'account_name_snapshot' => '', // '账户名称/开户名快照',
- 'remitter_name' => '', // '汇款人',
- 'amount' => '', // '0.00' COMMENT '金额',
- ];
- }
}
\ No newline at end of file
diff --git a/app/crm/service/StockOrdersService.php b/app/crm/service/StockOrdersService.php
index 9a98e6f..492ffd3 100644
--- a/app/crm/service/StockOrdersService.php
+++ b/app/crm/service/StockOrdersService.php
@@ -50,6 +50,7 @@ class StockOrdersService extends \app\common\service\StockOrdersService
$config['with'][] = 'accounts';
$config['with'][] = 'moneyValues';
$config['with'][] = 'salesperson';
+ $config['with'][] = 'files';
break;
case 'store':
break;
diff --git a/app/crm/service/StockOrdersService_bak.php b/app/crm/service/StockOrdersService_bak.php
deleted file mode 100644
index 6e1f287..0000000
--- a/app/crm/service/StockOrdersService_bak.php
+++ /dev/null
@@ -1,444 +0,0 @@
-validator;
- }
-
-
- protected function buildQueryConfig(Request $request, string $scene = 'index'): array
- {
- $p = $request->all();
-
- $config = [];
- $config['model'] = $this->modelClass;
- switch ($scene) {
- case 'index':
-
- // ====== ====== 筛选 ====== ======
- // 业务id
- if (isset($p['salesperson_id']) && $p['salesperson_id']) {
- $config['where']['salesperson_id'] = $p['salesperson_id'];
- }
- // 初、终版
- $config['where']['is_final'] = $p['is_final'] ?? 0;
- // 关键字
- if (isset($p['keyword']) && $p['keyword']) {
- $k = '%' . $p['keyword'] . '%';
- foreach (['pi_no', 'order_no', 'customer_snapshot'] as $col) {
- $config['orWhere'][] = [$col, 'like', $k];
- }
- }
-
- $config['order']['id'] = 'desc';
-
- $config['where']['salesperson_id'] = $request->user->uid;
- break;
- case 'print':
- $config['where']['id'] = $p['id'];
- break;
- case 'show':
- $config['where']['id'] = $p['id'];
-
- $config['with'][] = 'items';
- $config['with'][] = 'items.options';
- $config['with'][] = 'items.moneyValues';
- $config['with'][] = 'accounts';
- $config['with'][] = 'moneyValues';
- $config['with'][] = 'salesperson';
- break;
- case 'store':
- break;
- case 'update':
- $config['where']['id'] = $p['id'];
- break;
- case 'destroy':
- $config['where']['id'] = $p['id'];
- break;
- }
-
- 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'], '改装费');
- }
- if ($veh['ocean_freight']['amount']) {
- $item->addMoney('ocean_freight', $veh['ocean_freight']['currency'], $veh['ocean_freight']['amount'], $veh['ocean_freight']['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']
- - (float)$veh['ocean_freight']['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;
-
- $data['order_no'] = generateStockNo();
- $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['salesperson_id'] = $userId;
- $data['salesperson_snapshot'] = User::where('id', $userId)->value('name') ?? '';
-
- return $data;
- }
-
- protected function afterServiceStore($res)
- {
- // 处理原单
- if ($res->is_final == 1 && $res->object_id > 0) {
- $order = StockOrders::find($res->object_id);
- $order->is_use = 1;
- $order->object_id = $res->id;
- if (!$order->save()) {
- flg('备货单【'.$order->order_no.'】创建终版成功,但更新原单失败');
- }
- }
- // 启动审批
- $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]);
- return $res;
- }
-
-
- public function createdPdfFile($id)
- {
- $config = [];
- $config['model'] = $this->modelClass;
- $config['where']['id'] = $id;
- $config['with'][] = 'items';
- $config['with'][] = 'items.options';
- $config['with'][] = 'items.moneyValues';
- $config['with'][] = 'accounts';
- $config['with'][] = 'moneyValues';
- $config['with'][] = 'salesperson';
- $item = $this->logicShow($config);
- $pdfData = $this->pdfData($item);
-
- // 渲染模板为最终HTML
- $tplPath = app_path('common/utils/pdf/template/stockOrder.stub');
- $html = \app\common\utils\pdf\service\PdfHelper::render($tplPath, ['data' => $pdfData]);
-
- // 生成PDF
- $driver = new \app\common\utils\pdf\service\MpdfDriver();
- $pdfBin = $driver->htmlToPdf($html);
-
- // 存储
- $dir = public_path('pdf').'/';
- $fileName = ($pdfData['order_no'] ?? date('YmdHis')) . '.pdf';
-
- // 本地保存
- \app\common\utils\pdf\service\PdfStorage::saveBinary(
- $pdfBin,
- $dir,
- $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,
- 'scene' => 'stock_orders',
- 'category' => 'pdf',
- 'original_name' => $fileName
- ];
- $up = new \app\common\service\UploadService();
- $res = $up->uploadLocalFile($param);
-
- @unlink($dir . $fileName);
-
- // 更新文件地址
- $item->file_url = $res['file_name'];
- $item->save();
-
- return $res;
- }
-
- public function servicePrint(Request $request)
- {
- $config = $this->buildQueryConfig($request, 'show');
- $item = $this->logicShow($config);
- return $this->postProcess('Print', $item);
- }
-
-
- public function pdfData($item)
- {
- $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, '.', ',')
- ];
-
- // 根据里程处理 新车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, '.', ',');
- }
- }
-
- $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;
- }
-
- $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);
- }
-
- $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,
-
- // 订单项
- '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
- ];
-
- return $veh;
- }
-}
\ No newline at end of file
diff --git a/app/crm/service/StockOrdersService_bak2.php b/app/crm/service/StockOrdersService_bak2.php
deleted file mode 100644
index 1c4f7ea..0000000
--- a/app/crm/service/StockOrdersService_bak2.php
+++ /dev/null
@@ -1,762 +0,0 @@
-validator;
- }
-
-
- protected function buildQueryConfig(Request $request, string $scene = 'index'): array
- {
- $p = $request->all();
-
- $config = [];
- $config['model'] = $this->modelClass;
- switch ($scene) {
- case 'index':
-
- // ====== ====== 筛选 ====== ======
- // 业务id
- if (isset($p['salesperson_id']) && $p['salesperson_id']) {
- $config['where']['salesperson_id'] = $p['salesperson_id'];
- }
- // 初、终版
- $config['where']['is_final'] = $p['is_final'] ?? 0;
- // 关键字
- if (isset($p['keyword']) && $p['keyword']) {
- $k = '%' . $p['keyword'] . '%';
- foreach (['pi_no', 'order_no', 'customer_snapshot'] as $col) {
- $config['orWhere'][] = [$col, 'like', $k];
- }
- }
-
- $config['order']['id'] = 'desc';
-
- $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'];
-
- $config['with'][] = 'items';
- $config['with'][] = 'items.options';
- $config['with'][] = 'items.moneyValues';
- $config['with'][] = 'accounts';
- $config['with'][] = 'moneyValues';
- $config['with'][] = 'salesperson';
- break;
- case 'store':
- break;
- case 'update':
- $config['where']['id'] = $p['id'];
- break;
- case 'destroy':
- $config['where']['id'] = $p['id'];
- break;
- }
-
- return $config;
- }
-
- public function beforeServiceStore($data, Request $request)
- {
- $userId = $request->user->uid;
-
- $data['order_no'] = generateStockNo();
- $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['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;
- // }
- return $data;
- }
-
- protected function afterServiceStore($res)
- {
- // 处理原单
- if ($res->is_final == 1 && $res->object_id > 0) {
- $order = StockOrders::find($res->object_id);
- $order->is_use = 1;
- $order->object_id = $res->id;
- if (!$order->save()) {
- flg('备货单【'.$order->order_no.'】创建终版成功,但更新原单失败');
- }
- }
- // 启动审批
- 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 = [];
- $config['model'] = $this->modelClass;
- $config['where']['id'] = $id;
- $config['with'][] = 'items';
- $config['with'][] = 'items.options';
- $config['with'][] = 'items.moneyValues';
- $config['with'][] = 'accounts';
- $config['with'][] = 'moneyValues';
- $config['with'][] = 'salesperson';
- $item = $this->logicShow($config);
- $pdfData = $this->pdfData($item);
-
- // 渲染模板为最终HTML
- $tplPath = app_path('common/utils/pdf/template/stockOrder.stub');
- $html = \app\common\utils\pdf\service\PdfHelper::render($tplPath, ['data' => $pdfData]);
-
- // 生成PDF
- $driver = new \app\common\utils\pdf\service\MpdfDriver();
- $pdfBin = $driver->htmlToPdf($html);
-
- // 存储
- $dir = public_path('pdf').'/';
- $fileName = ($pdfData['order_no'] ?? date('YmdHis')) . '.pdf';
-
- // 本地保存
- \app\common\utils\pdf\service\PdfStorage::saveBinary(
- $pdfBin,
- $dir,
- $fileName
- );
-
- // 上传云端
- $param = [
- 'path' => $dir . $fileName,
- 'scene' => 'stock_orders',
- 'category' => 'pdf',
- 'original_name' => $fileName
- ];
- $up = new \app\common\service\UploadService();
- $res = $up->uploadLocalFile($param);
-
- @unlink($dir . $fileName);
-
- // 更新文件地址
- $item->file_url = $res['file_name'];
- $item->save();
-
- return $res;
- }
-
- public function pdfData($item)
- {
- $vehList = [];
- $index = 0;
- $totalProfit = 0; // 总利润
-
- // $priceFields = [
- // 'official_price', // '官方指导价',
- // 'discount_price', // '优惠',
- // 'listing_price', // '二手挂牌价价',
- // 'reduction_price', // '优惠',
-
- // 'handling_fee', // '手续费',
- // 'retrofit_fee', // '改装费',
- // 'fob_transport_fee', // 'FOB运输费',
- // 'port_misc_fee', // '港杂',
- // 'ocean_freight', // '海运费',
-
- // 'unit_price', // '单价',
- // 'total_price', // '总价',
- // // 'profit', // '利润'
- // ];
-
- foreach ($item->items as $k => $v) {
- $currencyInfo = SysCurrency::where('currency_code', $item->settlement_currency)->first(['currency_symbol', 'currency_name'])->toArray();
-
- // 存在则数量加1
- if (count($vehList) > 0 && isset($vehList[$v->unique_id])) {
- $vehList[$v->unique_id]['num'] += 1;
- $vehList[$v->unique_id]['total_price']['currency_info'] = $currencyInfo['currency_symbol'].number_format($vehList[$v->unique_id]['total_price']['amount']*$vehList[$v->unique_id]['num'], 2, '.', ',');
- $vehList[$v->unique_id]['profit']['currency_info'] = $currencyInfo['currency_symbol'].number_format($vehList[$v->unique_id]['profit']['amount']*$vehList[$v->unique_id]['num'], 2, '.', ',');
- continue;
- }
-
- $index += 1;
-
- // 处理金额 (每次循环重新初始化)
- $mv = [];
- foreach ($v->moneyValues as $money) {
- $mv[$money->field] = [
- 'currency' => $money->currency,
- 'amount' => $money->amount,
- 'rate' => $money->exchange_rate,
- 'currency_info' => SysCurrency::where('currency_code', $money->currency)->value('currency_symbol').number_format($money->amount, 2, '.', ',')
- ];
- }
-
- // 处理改装 (每次循环重新初始化)
- $mfy = '';
- foreach ($v->options as $my) {
- $mfy .= $my->option_name_snapshot.' ';
- }
-
- // 计算单项利润并累加到总利润
- $itemProfit = $this->calculateProfit($mv, $item);
- $totalProfit += $itemProfit;
-
- // 处理结果集
- $vehListItem = [
- '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
- ];
-
- $vehList[$v->unique_id] = $vehListItem + $mv;
- }
-
- $mvs = [];
- foreach ($item->moneyValues as $moneys) {
- $mvs[$moneys->field] = [
- 'currency' => $moneys->currency,
- 'amount' => $moneys->amount,
- 'rate' => $moneys->exchange_rate,
- 'currency_info' => SysCurrency::where('currency_code', $moneys->currency)->value('currency_symbol').number_format($moneys->amount, 2, '.', ','),
- ];
- }
-
- $accList = [];
- 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,
- ];
- }
-
-
-
- $veh = [
- 'order_no' => $item->order_no,
- 'salesperson_snapshot' => $item->salesperson_snapshot,
- '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,
-
- // 订单项
- 'veh_list' => array_values($vehList), // 重新索引数组
-
- 'contract_exchange_rate' => $item->contract_exchange_rate,
- 'cif_total_amount' => $mvs['cif_total_amount'],
- 'profit_total' => $mvs['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' => $accList,
- 'acc_index' => count($accList)+1,
- 'currency_symbol' => $item->settlement_currency,
- 'sign_imgs' => $this->queryAppro($item->id),
- 'contract_url' => (!empty($item->contract)) ? (new \app\common\service\OssService)->generatePrivateUrl($item->contract) : ''
- ];
-
- return $veh;
- }
-
-
- 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');
- $item = $this->logicShow($config);
- return $this->postProcess('Print', $item);
- }
-
- public function serviceDetail(Request $request)
- {
- $config = $this->buildQueryConfig($request, 'detail');
- $item = $this->logicShow($config);
- $pdfData = $this->pdfData($item);
- return $this->postProcess('Detail', $pdfData);
- }
-
- /**
- * 审批
- */
- 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 serviceUltimateApproval(Request $request)
- {
- $config = $this->buildQueryConfig($request, 'detail');
- $item = $this->logicShow($config);
- foreach ($item->items as $k => $v) {
- if ($v->vin === '') {
- throw new BusinessException('存在未填写vin的车辆,无法完成提交审核');
- }
- }
- $this->logicUpdateBy($config, [
- 'approval_status' => 1
- ]);
- $this->startApproval($item);
- return $this->postProcess('UltimateApproval', $item);
- }
-
- /**
- * 创建
- *
- * @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);
-
- 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;
- // $cifTotalAmountRate = 0;
- // $cifTotalAmountCurrency = 'CNY';
-
- $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, $order);
- $item->addMoney('profit', $order->settlement_currency, $profit, $order->contract_exchange_rate, '利润');
-
- // 累计到岸价
- $cifTotalAmount += $veh['total_price']['amount'] ?? 0;
- $profitTotalAmount += $profit;
-
- // if (isset($veh['retrofit_fee']['rate'])) {
- // $cifTotalAmountRate = $veh['retrofit_fee']['rate'];
- // }
- // if (isset($veh['retrofit_fee']['currency'])) {
- // $cifTotalAmountCurrency = $veh['retrofit_fee']['currency'];
- // }
-
- // 处理改装项
- $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'] ?? []);
-
- return md5($uniqueIdStr);
- }
-
- /**
- * 处理车辆价格信息
- */
- private function processVehiclePrices($item, array $veh): void
- {
- // 基础费用
- $priceFields = [
- 'unit_price' => '单价',
- 'total_price' => '总价',
- 'handling_fee' => '手续费',
- 'fob_transport_fee' => 'FOB运输费',
- 'port_misc_fee' => '港杂',
- 'retrofit_fee' => '改装费',
- 'ocean_freight' => '海运费'
- ];
-
- foreach ($priceFields as $field => $description) {
- if (!empty($veh[$field]['amount'])) {
- $item->addMoney(
- $field,
- $veh[$field]['currency'],
- $veh[$field]['amount'],
- $veh[$field]['rate'],
- $description
- );
- }
- }
-
- // 根据里程处理新车或二手车价格
- if (!empty($veh['mileage']) && $veh['mileage'] > 0) {
- // 二手车
- if (!empty($veh['listing_price']['amount'])) {
- $item->addMoney(
- 'listing_price',
- $veh['listing_price']['currency'],
- $veh['listing_price']['amount'],
- $veh['listing_price']['rate'],
- '二手挂牌价'
- );
- }
-
- if (!empty($veh['reduction_price']['amount'])) {
- $item->addMoney(
- 'reduction_price',
- $veh['reduction_price']['currency'],
- $veh['reduction_price']['amount'],
- $veh['reduction_price']['rate'],
- '二手减价'
- );
- }
- } else {
- // 新车
- if (!empty($veh['official_price']['amount'])) {
- $item->addMoney(
- 'official_price',
- $veh['official_price']['currency'],
- $veh['official_price']['amount'],
- $veh['official_price']['rate'],
- '官方指导价'
- );
- }
-
- if (!empty($veh['discount_price']['amount'])) {
- $item->addMoney(
- 'discount_price',
- $veh['discount_price']['currency'],
- $veh['discount_price']['amount'],
- $veh['discount_price']['rate'],
- '优惠价'
- );
- }
- }
- }
-
- /**
- * 计算利润
- */
- private function calculateProfit(array $veh, $order): float
- {
- $unitPrice = (float)($veh['unit_price']['amount'] ?? 0);
-
- if (!empty($veh['mileage']) && $veh['mileage'] > 0) {
- // 二手车
- $ttPrice = ($veh['listing_price']['amount'] ?? 0) / ($order->contract_exchange_rate ?: 1);
- $ddPrice = $veh['reduction_price']['amount'] ?? 0;
- } else {
- // 新车
- $ttPrice = ($veh['official_price']['amount'] ?? 0) / ($order->contract_exchange_rate ?: 1);
- $ddPrice = $veh['discount_price']['amount'] ?? 0;
- }
-
- $handlingFee = (float)($veh['handling_fee']['amount'] ?? 0);
- $fobTransportFee = (float)($veh['fob_transport_fee']['amount'] ?? 0);
- $portMiscFee = (float)($veh['port_misc_fee']['amount'] ?? 0);
- $retrofitFee = (float)($veh['retrofit_fee']['amount'] ?? 0);
- $oceanFreight = (float)($veh['ocean_freight']['amount'] ?? 0);
-
- return $unitPrice - $ttPrice - $ddPrice - $handlingFee - $fobTransportFee - $portMiscFee - $retrofitFee - $oceanFreight;
- }
-
- /**
- * 处理改装项
- */
- 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);
- }
- }
-}
\ No newline at end of file