Files
xk-api-yii/platform/modules/v1/controllers/ErpController.php

331 lines
15 KiB
PHP
Raw Normal View History

2024-09-19 11:32:39 +08:00
<?php
/*
* @author: liudiao
* @Date: 2023-05-23 17:10:09
* @Description:
*/
namespace platform\modules\v1\controllers;
use common\jobs\ProductOrderSendJob;
use common\jobs\templateMessage\ProductOrderSend;
2024-12-19 19:20:27 +08:00
use common\models\oldDb\ExpressNos;
use common\models\oldDb\Drug;
2024-12-19 19:20:27 +08:00
use common\models\oldDb\Prescription;
use common\models\oldDb\ProductOrder;
use common\models\oldDb\ProductOrderLog;
2024-09-19 11:32:39 +08:00
use GuzzleHttp\Client;
use yii\base\Controller;
2024-12-19 19:20:27 +08:00
use yii\base\Exception;
2024-09-19 11:32:39 +08:00
use yii\helpers\Json;
/**
* @doc-module 西中成药订单数据同步江奥川ERP
*/
class ErpController extends Controller
{
public function actionOrderSync(){
$headers = \Yii::$app->request->getHeaders();
// $userid = $headers->get('userid');
$secret = $headers->get('secret');
$jacErpConfig = \Yii::$app->params['jac_erp'];
if($secret != $jacErpConfig['secret']){
throw new Exception('非法请求');
}
$rawData = \Yii::$app->request->rawBody;
$post = Json::decode($rawData);
if(!$post['startDate'] || !$post['endDate']){
throw new Exception('startDate或endDate不能为空');
}
try {
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单开始 startDate:'.$post['startDate'].' endDate:'.$post['endDate']);
$startDate = strtotime($post['startDate']);
$endDate = strtotime($post['endDate']) + 86400;
2024-09-19 11:32:39 +08:00
$productOrders = ProductOrder::find()->alias('po')->where([
2025-10-25 13:32:06 +08:00
'po.prescription_type' => 2,
'po.is_sync_erp' => 0,
])
->andWhere([
'in','po.status',[1,2,3,6,7]
])
->andWhere(['BETWEEN', 'po.created_at', $startDate, $endDate])
// ->joinWith('approvedPrescription')
->with(['orderItems','store', 'prescription'])
->asArray()
->all();
// 批量加载药品 ERP 数量倍数,避免循环内逐条查询
$drugFactorMap = $this->buildDrugErpQtyFactorMap($productOrders);
2024-09-19 11:32:39 +08:00
//解析成erp所需参数订单详情是否需要改动 - 线上订单的展示)
$erpData = [];
$ids = [];
2026-01-28 09:32:59 +08:00
$defaultUserId = '41677';
2024-09-19 11:32:39 +08:00
foreach($productOrders as $k=>$v){
2025-12-02 11:14:59 +08:00
// 如果是商城订单
2025-10-25 13:32:06 +08:00
if ($v['order_type'] == 2) {
$erpData[$k]['orderId'] = $v['order_no'];
$erpData[$k]['createTime'] = date('Y-m-d H:i:s', $v['created_at']);
2025-12-02 11:14:59 +08:00
// $erpData[$k]['userId'] = $v['store']['erp_id'];
// 商城订单暂时都用11007诊所来接收订单
2026-01-28 09:32:59 +08:00
$erpData[$k]['userId'] = $defaultUserId;
2025-10-25 13:32:06 +08:00
$erpData[$k]['orderStatus'] = $v['status'];
2025-12-02 11:14:59 +08:00
$erpData[$k]['orderType'] = $v['type'];
2025-10-25 13:32:06 +08:00
$erpData[$k]['totalAmount'] = $v['total_pay_price'];
2025-12-02 11:14:59 +08:00
2025-10-25 13:32:06 +08:00
// $erpData[$k]['deliveryAmount'] = $v['trans_expenses'];
if($v['delivery_method'] == 1){ //到店自取
2025-12-02 11:14:59 +08:00
// if (!in_array($v['order_type'], [2])) {
// $prescriptionContent = Json::decode($v['prescription']['content']);
// $erpData[$k]['deliveryName'] = $prescriptionContent['patient']['name']?? '';
// $erpData[$k]['deliveryMobile'] = $prescriptionContent['patient']['mobile']?? '';
// $erpData[$k]['deliveryAddress'] = $v['store']['position']?? '';
// } else {
// $erpData[$k]['deliveryName'] = $v['store']['name']?? '';
// $erpData[$k]['deliveryMobile'] = $v['store']['mobile']?? '';
// $erpData[$k]['deliveryAddress'] = $v['store']['position']?? '';
// }
$erpData[$k]['deliveryName'] = $v['store']['name']?? '';
$erpData[$k]['deliveryMobile'] = $v['store']['mobile']?? '';
$erpData[$k]['deliveryAddress'] = $v['store']['position']?? '';
2025-10-25 13:32:06 +08:00
} else {//快递到家
$erpData[$k]['deliveryName'] = $v['express_name'];
$erpData[$k]['deliveryMobile'] = $v['express_mobile'];
$erpData[$k]['deliveryAddress'] = $v['express_region'].$v['express_address'];
}
$orderItems = [];
foreach($v['orderItems'] as $vk=>$vv){
$orderItems[$vk] = $this->buildErpOrderItem($vv, $drugFactorMap);
2025-10-25 13:32:06 +08:00
}
$erpData[$k]['orderItems'] = $orderItems;
$ids[]=$v['id'];
2025-12-02 13:40:03 +08:00
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单数据:'. $v['id']. ''. json_encode($orderItems));
// ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单数据:'. $v['id']);
2025-10-25 13:32:06 +08:00
} else {
2025-12-02 11:14:59 +08:00
// 如果是处方订单
2025-10-25 13:32:06 +08:00
if (!empty($v['prescription'])) {
// 如果是处方药或者挂号药
if ($v['prescription']['status'] == 1) {
$erpData[$k]['orderId'] = $v['order_no'];
$erpData[$k]['createTime'] = date('Y-m-d H:i:s', $v['created_at']);
2026-02-02 16:11:31 +08:00
// 如果是商城处方订单
2026-01-28 09:32:59 +08:00
if ($v['is_online'] == 3) {
$erpData[$k]['userId'] = $defaultUserId;
} else {
$erpData[$k]['userId'] = $v['store']['erp_id'];
}
2025-10-25 13:32:06 +08:00
$erpData[$k]['orderStatus'] = $v['status'];
$erpData[$k]['totalAmount'] = $v['total_pay_price'];
// $erpData[$k]['deliveryAmount'] = $v['trans_expenses'];
if($v['delivery_method'] == 1){
//到店自取
$prescriptionContent = Json::decode($v['prescription']['content']);
$erpData[$k]['deliveryName'] = $prescriptionContent['patient']['name']?? '';
$erpData[$k]['deliveryMobile'] = $prescriptionContent['patient']['mobile']?? '';
$erpData[$k]['deliveryAddress'] = $v['store']['position']?? '';
} else {//快递到家
$erpData[$k]['deliveryName'] = $v['express_name'];
$erpData[$k]['deliveryMobile'] = $v['express_mobile'];
$erpData[$k]['deliveryAddress'] = $v['express_region'].$v['express_address'];
}
$orderItems = [];
foreach($v['orderItems'] as $vk=>$vv){
$orderItems[$vk] = $this->buildErpOrderItem($vv, $drugFactorMap);
2025-10-25 13:32:06 +08:00
}
$erpData[$k]['orderItems'] = $orderItems;
$ids[]=$v['id'];
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单数据:'. $v['id']. ''. json_encode($orderItems));
}
}
}
2024-09-19 11:32:39 +08:00
}
2026-07-20 16:18:43 +08:00
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单结束,拉取订单数据'. '--------'. json_encode($erpData));
2024-09-19 11:32:39 +08:00
if(!empty($ids)){
//更新为已同步erp
\Yii::$app->db->createCommand()->update('yii_product_order', [
'is_sync_erp' => 1
], ['in', 'id',$ids])->execute();
}
2024-09-19 11:32:39 +08:00
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单结束,拉取订单数量:'.count($productOrders).', 拉取的订单ids:'.implode(',',$ids));
} catch (\Exception $e) {
2025-10-25 13:32:06 +08:00
// ds([
// 'e' => $e->getMessage(),
// 'trace' => $e->getTraceAsString(),
// 'file' => $e->getFile(),
// 'line' => $e->getLine(),
// 'code' => $e->getCode(),
// 'traceAsString' => $e->getTraceAsString(),
// ]);
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单异常:'.$e->getMessage(). '在:'. $e->getFile(). '行:'. $e->getLine());
2024-09-19 11:32:39 +08:00
throw new Exception('获取处方异常'.$e->getMessage());
}
2024-09-19 11:32:39 +08:00
return $erpData;
}
/**
* 从待同步订单中收集 drug_id批量查询 ERP 数量倍数
* @param array $productOrders
* @return array<int, float> drug_id => factor
*/
private function buildDrugErpQtyFactorMap(array $productOrders): array
{
$drugIds = [];
foreach ($productOrders as $order) {
if (empty($order['orderItems'])) {
continue;
}
foreach ($order['orderItems'] as $item) {
if (!empty($item['drug_id'])) {
$drugIds[] = (int) $item['drug_id'];
}
}
}
$drugIds = array_unique($drugIds);
if (empty($drugIds)) {
return [];
}
$rows = Drug::find()
->select(['id', 'erp_qty_factor'])
->where(['id' => $drugIds])
->asArray()
->all();
$map = [];
foreach ($rows as $row) {
$factor = (float) ($row['erp_qty_factor'] ?? 1);
$map[(int) $row['id']] = $factor > 0 ? $factor : 1;
}
return $map;
}
/**
* 构建 ERP 订单明细quantity 按药品倍数换算price 仍按原订单数量
* @param array $item 订单明细
* @param array<int, float> $drugFactorMap
* @return array
*/
private function buildErpOrderItem(array $item, array $drugFactorMap): array
{
$drugId = (int) ($item['drug_id'] ?? 0);
$factor = $drugFactorMap[$drugId] ?? 1;
$originQty = (int) ($item['number'] ?? 0);
$erpQty = (int) round($originQty * $factor);
$scale = 2; // 金额一般保留 2 位小数
$buyPrice = $item['buy_price'];
if (bccomp($factor, '1', $scale) === 1) {
$erpPaymentPrice = bcdiv($buyPrice, $factor, $scale);
} else {
$erpPaymentPrice = $buyPrice;
}
return [
'detailId' => $item['id'],
'productSku' => $item['drug_no'],
'quantity' => (string)$erpQty,
'paymentPrice' => $erpPaymentPrice,
'price' => round($originQty * $item['buy_price'], 2),
];
}
2024-09-19 11:32:39 +08:00
/**
* @author: liudiao
* @Date: 2023-08-01 14:10:45
* @Description: erp发货推送物流信息
* @return {*}
*/
public function actionExpressNotify(){
ProductOrderLog::saveLog(0,'江奥川ERP发货推送订单物流信息开始');
$t = \Yii::$app->db->beginTransaction();
try {
$headers = \Yii::$app->request->getHeaders();
$secret = $headers->get('secret');
$jacErpConfig = \Yii::$app->params['jac_erp'];
if($secret != $jacErpConfig['secret']){
throw new Exception('非法请求');
}
$rawData = \Yii::$app->request->rawBody;
$post = Json::decode($rawData);
if(!$post['order_type'] || !$post['order_no'] || !$post['express_company'] || !$post['express_no'] || !$post['express_mobile']){
throw new Exception('order_type/order_no/express_company/express_no/express_mobile不能为空');
}
if(!in_array($post['express_company'], ['邮政快递','顺丰速运'])){
throw new Exception('仅支持顺丰速运和邮政快递');
}
if($post['order_type'] == 1){ //中药/颗粒药 order_no为处方号
$prescription = Prescription::find()->where(['prescription_no' => $post['order_no']])->one();
if(empty($prescription)){
throw new Exception('订单不存在');
}
$productOrder = ProductOrder::find()->where(['p_id' =>$prescription->id, 'status' => 1])->one();
} else {
$productOrder = ProductOrder::find()->where(['order_no' =>$post['order_no'], 'status' => 1])->one();
}
if(!$productOrder){
throw new Exception('订单不存在.');
}
//快递单号信息
$ExpressNos = new ExpressNos();
$ExpressNos->express_company_name = $post['express_company'];
$ExpressNos->express_company_code = $post['express_company'] == '邮政快递' ? 'youzhengguonei' : 'shunfeng';
$ExpressNos->express_no = $post['express_no'];
$ExpressNos->mobile = $post['express_mobile'];
$ExpressNos->state = null;
$ExpressNos->sync_at = null;
$ExpressNos->created_at = date('Y-m-d H:i:s', time());
$ExpressNos->updated_at = date('Y-m-d H:i:s', time());
$ExpressNos->saveOrFail();
//更新订单为发货状态
$productOrder->is_send = 1;
$productOrder->status = 2;
$productOrder->send_time = date('Y-m-d H:i:s', time());
$productOrder->express_no_id = $ExpressNos->id;
$productOrder->saveOrFail();
//订单发货订阅消息通知
\Yii::$app->queue->push(new ProductOrderSend([
'orderId' => $productOrder->id,
]));
//订单发货后分账结算
if($productOrder->type == 2){ //易票联支付的产品订单
$config = \Yii::$app->params;
$orderAutoSettlementTime = isset($config['product_order']['settlement_time']) ? $config['product_order']['settlement_time'] : 72*3600;
\Yii::$app->queue->delay($orderAutoSettlementTime)->push(new ProductOrderSendJob([
'orderId' => $productOrder->id
]));
}
$t->commit();
//获取最新快递信息
(new Client(['http_errors' => false]))->get("https://shop.xiaokang88.com/t/express_update", [
'query' => [
'id' => $ExpressNos->id,
],
]);
ProductOrderLog::saveLog(0,'江奥川ERP发货推送订单物流信息成功,订单id'.$productOrder->id);
return ['success'];
} catch (\Exception $e) {
$t->rollBack();
ProductOrderLog::saveLog(0,'江奥川ERP发货推送订单物流信息异常'.$e->getMessage());
throw new Exception($e->getMessage());
}
}
}