Files
xk-api-yii/platform/modules/v1/controllers/ErpController.php
2026-07-20 16:18:43 +08:00

331 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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;
use common\models\oldDb\ExpressNos;
use common\models\oldDb\Drug;
use common\models\oldDb\Prescription;
use common\models\oldDb\ProductOrder;
use common\models\oldDb\ProductOrderLog;
use GuzzleHttp\Client;
use yii\base\Controller;
use yii\base\Exception;
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;
$productOrders = ProductOrder::find()->alias('po')->where([
'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);
//解析成erp所需参数订单详情是否需要改动 - 线上订单的展示)
$erpData = [];
$ids = [];
$defaultUserId = '41677';
foreach($productOrders as $k=>$v){
// 如果是商城订单
if ($v['order_type'] == 2) {
$erpData[$k]['orderId'] = $v['order_no'];
$erpData[$k]['createTime'] = date('Y-m-d H:i:s', $v['created_at']);
// $erpData[$k]['userId'] = $v['store']['erp_id'];
// 商城订单暂时都用11007诊所来接收订单
$erpData[$k]['userId'] = $defaultUserId;
$erpData[$k]['orderStatus'] = $v['status'];
$erpData[$k]['orderType'] = $v['type'];
$erpData[$k]['totalAmount'] = $v['total_pay_price'];
// $erpData[$k]['deliveryAmount'] = $v['trans_expenses'];
if($v['delivery_method'] == 1){ //到店自取
// 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']?? '';
} 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);
}
$erpData[$k]['orderItems'] = $orderItems;
$ids[]=$v['id'];
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单数据:'. $v['id']. ''. json_encode($orderItems));
// ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单数据:'. $v['id']);
} else {
// 如果是处方订单
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']);
// 如果是商城处方订单
if ($v['is_online'] == 3) {
$erpData[$k]['userId'] = $defaultUserId;
} else {
$erpData[$k]['userId'] = $v['store']['erp_id'];
}
$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);
}
$erpData[$k]['orderItems'] = $orderItems;
$ids[]=$v['id'];
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单数据:'. $v['id']. ''. json_encode($orderItems));
}
}
}
}
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单结束,拉取订单数据'. '--------'. json_encode($erpData));
if(!empty($ids)){
//更新为已同步erp
\Yii::$app->db->createCommand()->update('yii_product_order', [
'is_sync_erp' => 1
], ['in', 'id',$ids])->execute();
}
ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单结束,拉取订单数量:'.count($productOrders).', 拉取的订单ids:'.implode(',',$ids));
} catch (\Exception $e) {
// 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());
throw new Exception('获取处方异常'.$e->getMessage());
}
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),
];
}
/**
* @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());
}
}
}