| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470 |
- <?php
- namespace bizGhs\order\services;
- use biz\ghs\classes\GhsClass;
- use biz\shop\classes\ShopAdminClass;
- use biz\shop\classes\ShopCapitalClass;
- use biz\shop\classes\ShopClass;
- use biz\shop\classes\ShopExtClass;
- use biz\stat\classes\StatKdClass;
- use biz\stat\classes\StatKhCgClass;
- use biz\stat\classes\StatSaleClass;
- use biz\wx\classes\WxMessageClass;
- use bizGhs\base\services\BaseService;
- use bizGhs\book\classes\BookItemClass;
- use bizGhs\custom\classes\CustomClass;
- use bizGhs\custom\classes\CustomDebtChangeClass;
- use bizGhs\custom\services\GhsRechargeSettleService;
- use bizGhs\clear\classes\OrderCgClearClass;
- use bizGhs\order\classes\OrderClass;
- use bizGhs\order\classes\OrderExpressClass;
- use bizGhs\order\classes\OrderForwardClass;
- use bizGhs\order\classes\OrderItemClass;
- use bizGhs\order\classes\OrderSendClass;
- use bizGhs\order\classes\RefundOrderClass;
- use bizGhs\order\classes\RefundOrderItemClass;
- use bizGhs\product\classes\ProductClass;
- use bizGhs\shop\classes\MainClass;
- use bizGhs\shop\classes\ShopMoneyChangeClass;
- use bizGhs\stat\classes\StatYjClass;
- use biz\stat\classes\StatOrderCountClass;
- use bizGhs\stock\classes\StockRecordClass;
- use bizHd\cg\classes\CgRefundClass;
- use bizHd\cg\services\CgRefundService;
- use bizHd\purchase\classes\PurchaseItemClass;
- use bizHd\purchase\services\PurchaseService;
- use bizHd\stat\classes\StatIncomeClass;
- use bizHd\stat\classes\StatOrderClass;
- use common\components\dict;
- use common\components\orderSn;
- use common\components\util;
- use bizHd\purchase\classes\PurchaseClass;
- use common\components\stringUtil;
- use Yii;
- class OrderService extends BaseService
- {
- public static $baseFile = '\bizGhs\order\classes\OrderClass';
- public static function arrival($order, $data)
- {
- $params = ['fhType' => 0, 'fhWl' => '', 'fhWlNo' => '',];
- OrderClass::orderSend($order, $params);
- //product [{"productId":"3674","num":0,"price":1}]
- $product = $data['product'] ?? '';
- if (empty($product)) {
- util::fail('请填写成本价和到货数量');
- }
- $product = json_decode($product, true);
- if (empty($product)) {
- util::fail('没有填写成本价和到货数量');
- }
- $data['product'] = $product;
- //供货商到货
- $respond = OrderClass::arrival($order, $data);
- $cgId = $order->purchaseId ?? 0;
- $cg = PurchaseClass::getById($cgId, true);
- if (empty($cg)) {
- util::fail('没有找到采购单');
- }
- //供货商花材转换为零售店花材
- $ids = array_column($product, 'productId');
- $ghsProductInfo = ProductClass::getByIds($ids);
- if (empty($ghsProductInfo)) {
- util::fail('没有花材??');
- }
- $ghsPtIdRelation = [];
- foreach ($ghsProductInfo as $ghsProduct) {
- $id = $ghsProduct['id'] ?? 0;
- $ptItemId = $ghsProduct['itemId'] ?? 0;
- $ghsPtIdRelation[$ptItemId] = $id;
- }
- $ptIds = array_keys($ghsPtIdRelation);
- $cgMainId = $cg->mainId ?? 0;
- $cgSjId = $cg->sjdId ?? 0;
- $cgShopId = $cg->shopId ?? 0;
- $cgItem = ProductClass::getAllByCondition(['mainId' => $cgMainId, 'itemId' => ['in', $ptIds]], null, '*');
- $ghsHdIdRelate = [];
- foreach ($cgItem as $it) {
- $ptItemId = $it['itemId'] ?? 0;
- $ghsItemId = $ghsPtIdRelation[$ptItemId] ?? 0;
- $cgItemId = $it['id'] ?? 0;
- $ghsHdIdRelate[$ghsItemId] = $cgItemId;
- }
- $cgProduct = [];
- foreach ($product as $pro) {
- $price = $pro['price'] ?? 0;
- $num = $pro['num'] ?? 0;
- $productId = $pro['productId'] ?? 0;
- $currentId = $ghsHdIdRelate[$productId] ?? 0;
- $cgProduct[$currentId] = ['num' => $num, 'price' => $price, 'productId' => $currentId];
- }
- //零售到货
- $saleRefund = $respond['refund'] ?? null;
- $saleRefundId = 0;
- if (!empty($saleRefund)) {
- $saleRefundId = $saleRefund->id ?? 0;
- }
- $kiloFee = $respond['kiloFee'] ?? 0;
- $miniKilo = $respond['miniKilo'] ?? 0;
- $saleRefundId = $saleRefundId;
- $sendCost = isset($data['sendCost']) && is_numeric($data['sendCost']) ? $data['sendCost'] : 0;
- $packCost = isset($data['packCost']) && is_numeric($data['packCost']) ? $data['packCost'] : 0;
- $cgData = [
- 'product' => $cgProduct,
- 'kiloFee' => $kiloFee,
- 'miniKilo' => $miniKilo,
- 'saleRefundId' => $saleRefundId,
- 'sjId' => $cgSjId,
- 'shopId' => $cgShopId,
- 'mainId' => $cgMainId,
- 'sendCost' => $sendCost,
- 'packCost' => $packCost,
- ];
- $result = PurchaseClass::arrival($cg, $cgData);
- $cgRefund = $result['refund'] ?? null;
- if (!empty($cgRefund)) {
- $cgRefundId = $cgRefund->id ?? 0;
- if (!empty($saleRefund)) {
- $saleRefund->cgRefundId = $cgRefundId;
- $saleRefund->save();
- }
- }
- //不是预订单,并且供货商不是源花汇、小明鲜花、淄博花超、云漫梦金鹏、海翔,则订单直接完成掉。是预订单,则确认发货时直接完成掉。有多个地方要修改,请搜索关键词zjFinish
- if (!empty($cg) && !empty($order)) {
- $ghsShopId = $order->shopId ?? 0;
- $ext = ShopExtClass::getByCondition(['shopId' => $ghsShopId], true, null, 'id,shopId,orderFlow');
- if ($ext->orderFlow == 0) {
- $newCg = PurchaseClass::getById($cgId, true);
- PurchaseClass::confirmTake($newCg);
- }
- }
- }
- //添加订单
- public static function createNewOrder($data, $custom, $hasPay = 1)
- {
- //有unitType数据,说明是收银台传过来的数据,转换成和手机端结构一致
- $hasUnitType = array_column($data['product'], 'unitType');
- if (!empty($hasUnitType)) {
- $newProductData = [];
- foreach ($data['product'] as $productItem) {
- $unitType = $productItem['unitType'] ?? 0;
- $num = $productItem['num'] ?? 0;
- $productId = $productItem['productId'] ?? 0;
- $classId = $productItem['classId'] ?? 0;
- $itemId = $productItem['itemId'] ?? 0;
- $price = $productItem['price'] ?? 0;
- if ($unitType == 0) {
- $bigNum = $num;
- $smallNum = '';
- } else {
- $bigNum = '';
- $smallNum = $num;
- }
- $newProductData[] = [
- 'productId' => (int)$productId,
- 'bigNum' => (int)$bigNum,
- 'smallNum' => (int)$smallNum,
- 'classId' => (int)$classId,
- 'itemId' => (int)$itemId,
- 'price' => floatval($price),
- ];
- }
- $data['product'] = $newProductData;
- }
- //供货商销售单
- $returnOrder = OrderClass::addOrder($data, $custom);
- $saleId = $returnOrder->id ?? 0;
- $customSjId = $custom['sjId'] ?? 0;
- $customShopId = $custom['shopId'] ?? 0;
- $localOrder = $data['localOrder'] ?? 0;
- $transType = $data['transType'] ?? 0;
- $ghsShopAdminId = $data['shopAdminId'] ?? 0;
- $ghsShopAdminName = $data['shopAdminName'] ?? '';
- $customId = $data['customId'] ?? 0;
- $ghsId = $data['ghsId'] ?? 0;
- $ghs = GhsClass::getById($ghsId);
- if (empty($ghs)) {
- util::fail('没有找到供货商');
- }
- $ghsName = $ghs['name'] ?? '';
- $ghsAvatar = $ghs['avatar'] ?? '';
- $ghsMobile = $ghs['mobile'] ?? '';
- $ghsFullAddress = $ghs['fullAddress'] ?? '';
- $payWay = $data['payWay'] ?? dict::getDict('payWay', 'wxPay');
- //销售单欠款字段与采购单欠款字段转换
- $debt = $data['debt'] ?? 0;
- $purchaseDebt = $debt == 1 ? PurchaseClass::DEBT_YES : PurchaseClass::DEBT_NO;
- if ($hasPay == dict::getDict('hasPay', 'balance')) {
- $payWay = dict::getDict('payWay', 'balancePay');
- $purchaseDebt = PurchaseClass::DEBT_NO;
- } elseif ($debt == 1) {
- $payWay = dict::getDict('payWay', 'debtPay');
- }
- //销售单的自取还是配送字段 与 采购单的转换
- $sendType = $data['sendType'] ?? OrderClass::SEND_TYPE_CAR_GET;
- $getType = $sendType == OrderClass::SEND_TYPE_THIRD_SEND ? PurchaseClass::GET_TYPE_SEND : PurchaseClass::GET_TYPE_SELF_GET;
- //零售采购单时没有传price字段,供货商可以改价会传price字段,这里转成userPrice以便采购单识别使用改的价还是花材原价!
- $currentProduct = $data['product'];
- foreach ($currentProduct as $currentKey => $currentItem) {
- if (isset($currentItem['price'])) {
- $currentProduct[$currentKey]['userPrice'] = $currentItem['price'];
- unset($currentProduct[$currentKey]['price']);
- }
- }
- $sendTimeWant = !empty($data['sendTimeWant']) ? $data['sendTimeWant'] : date("Y-m-d");
- $remark = $data['remark'] ?? '';
- $xj = $data['xj'] ?? '';
- $treeData = $data['treeData'] ?? [];
- $book = $data['book'] ?? 0;
- //后端开单,涉及花材满减,关键词 back_order_reach_discount_price
- $reachDiscountPrice = $data['reachDiscountPrice'] ?? 0;
- $wlName = $data['wlName'] ?? '';
- $cgMainId = $ghs['ownMainId'] ?? 0;
- $purchaseData = [
- 'book' => $book,
- 'product' => $currentProduct,
- 'sendTimeWant' => $sendTimeWant,
- 'sendCost' => $data['sendCost'] ?? '0',
- 'packCost' => $data['packCost'] ?? '0',
- 'ghsShopAdminId' => $ghsShopAdminId,
- 'ghsShopAdminName' => $ghsShopAdminName,
- 'sjId' => $customSjId,
- 'shopId' => $customShopId,
- 'saleId' => $saleId,
- 'ghsId' => $ghsId,
- 'ghsName' => $ghsName,
- 'ghsMobile' => $ghsMobile,
- 'ghsFullAddress' => $ghsFullAddress,
- 'ghsAvatar' => $ghsAvatar,
- 'customId' => $customId,
- 'payWay' => $payWay,
- 'status' => PurchaseClass::STATUS_UN_PAY,
- 'cgStyle' => dict::getDict('cgStyle', 'ghs'),
- 'debt' => $purchaseDebt,
- 'getType' => $getType,
- 'sendType' => $sendType,
- 'remark' => $remark,
- 'xj' => $xj,
- 'treeData' => $treeData,
- 'discount' => 1,
- 'mainId' => $cgMainId,
- 'wlName' => $wlName,
- 'localOrder' => $localOrder,
- 'transType' => $transType,
- 'reachDiscountPrice' => $reachDiscountPrice,
- ];
- if (!empty($data['deadline'])) {
- $purchaseData['deadline'] = $data['deadline'];
- }
- if (isset($data['modifyPrice']) && is_numeric($data['modifyPrice'])) {
- $purchaseData['modifyPrice'] = $data['modifyPrice'];
- }
- $purchase = PurchaseClass::addPurchase($purchaseData, $ghs);
- //开历史订单
- $historyDate = $data['historyDate'] ?? '';
- if (!empty($historyDate)) {
- $currentPayTime = $historyDate . ' 12:00:00';
- $returnOrder->payTime = $currentPayTime;
- $purchase->payTime = $currentPayTime;
- $purchase->save();
- CustomDebtChangeClass::updateByCondition(['capitalType' => 10, 'relateId' => $returnOrder->id], ['payTime' => $currentPayTime]);
- }
- $purchaseId = $purchase->id ?? 0;
- $returnOrder->purchaseId = $purchaseId;
- $returnOrder->save();
- //欠款、已付款、余额支付的走付款后流程
- if (in_array($hasPay, [dict::getDict('hasPay', 'payed'), dict::getDict('hasPay', 'debt'), dict::getDict('hasPay', 'balance')])) {
- // 挂账/余额:先处理销售单(含余额抵挂账),再同步采购单待结
- if (in_array($hasPay, [dict::getDict('hasPay', 'debt'), dict::getDict('hasPay', 'balance')])) {
- self::payAfter($returnOrder, $payWay);
- $purchase = PurchaseClass::getLockById($purchaseId);
- if (!empty($purchase)) {
- $purchase->remainDebtPrice = $returnOrder->remainDebtPrice ?? '0.00';
- $purchase->debtPrice = $returnOrder->debtPrice ?? '0.00';
- $purchase->debt = ($returnOrder->debt ?? 0) == OrderClass::DEBT_YES
- ? PurchaseClass::DEBT_YES : PurchaseClass::DEBT_NO;
- $purchase->save(false, ['remainDebtPrice', 'debtPrice', 'debt']);
- }
- PurchaseService::payAfter($purchase, $payWay);
- } else {
- PurchaseService::payAfter($purchase, $payWay);
- self::payAfter($returnOrder, $payWay);
- }
- //不是预订单,并且供货商不是源花汇、小明鲜花、淄博花超、云漫梦金鹏、海翔,则订单直接完成掉。是预订单,则确认发货时直接完成掉。有多个地方要修改,请搜索关键词zjFinish
- if (isset($returnOrder->book) && $returnOrder->book == 0) {
- $ghsShopId = $ghs['shopId'] ?? 0;
- $ext = ShopExtClass::getByCondition(['shopId' => $ghsShopId], true, null, 'id,shopId,orderFlow');
- if ($ext->orderFlow == 0) {
- $returnId = $returnOrder->id;
- $order = OrderClass::getById($returnId, true);
- if (!empty($order)) {
- OrderClass::confirmReach($order);
- }
- }
- }
- }
- return $returnOrder;
- }
- //修改订单
- public static function updateOrder($order, $data)
- {
- $purchaseId = $order->purchaseId ?? 0;
- $purchase = PurchaseClass::getLockById($purchaseId);
- //修改供货商销售单
- $returnOrder = OrderClass::updateOrder($order, $data);
- //供货商销售单的 0未欠款 1欠款 转成零售采购单的 1欠款 2未欠款
- $debt = $data['debt'] ?? 0;
- $purchaseDebt = $debt == 1 ? PurchaseClass::DEBT_YES : PurchaseClass::DEBT_NO;
- $payWay = $data['payWay'] ?? dict::getDict('payWay', 'wxPay');
- if ($debt == 1) {
- $payWay = dict::getDict('payWay', 'debtPay');
- }
- //自取还是配送订单,销售单与采购单之间转换
- $sendType = $data['sendType'] ?? OrderClass::SEND_TYPE_MYSELF;
- $getType = $sendType == OrderClass::SEND_TYPE_NO ? PurchaseClass::GET_TYPE_SELF_GET : PurchaseClass::GET_TYPE_SEND;
- //供货商价格是可以修改的,修改的价格一起传给采购单保存
- $currentProduct = $data['product'];
- foreach ($currentProduct as $currentKey => $currentItem) {
- if (isset($currentProduct[$currentKey]['price'])) {
- $currentProduct[$currentKey]['userPrice'] = $currentProduct[$currentKey]['price'];
- unset($currentProduct[$currentKey]['price']);
- }
- }
- $remark = $data['remark'] ?? '';
- $purchaseData = [
- 'product' => $currentProduct,
- 'sendTime' => date("H:i:s"),
- 'sendCost' => $data['sendCost'] ?: '0.00',
- 'payWay' => $payWay,
- 'status' => PurchaseClass::STATUS_UN_PAY,
- 'cgStyle' => dict::getDict('cgStyle', 'ghs'),
- 'debt' => $purchaseDebt,
- 'getType' => $getType,
- 'status' => PurchaseClass::STATUS_UN_PAY,
- 'remark' => $remark,
- ];
- if (isset($data['deadline']) && !empty($data['deadline'])) {
- $purchaseData['deadline'] = $data['deadline'];
- }
- if (isset($data['modifyPrice']) && is_numeric($data['modifyPrice'])) {
- //优惠之后的金额
- if (is_numeric($data['modifyPrice']) == false || $data['modifyPrice'] <= 0) {
- util::fail('金额填错了哦');
- }
- $purchaseData['modifyPrice'] = $data['modifyPrice'];
- }
- //修改采购单
- $purchase = PurchaseClass::updatePurchase($purchase, $purchaseData);
- //除了自取订单直接变成已确认,其它都进入待确认流程。订单的确认以欠款或已收款方式确认。 ssh 20210809
- if (isset($data['sendType']) && $data['sendType'] == OrderClass::SEND_TYPE_NO) {
- PurchaseService::payAfter($purchase, $payWay);
- self::payAfter($returnOrder, $payWay);
- } else {
- //没有进入确认流程的订单也有打印需求
- if ($data['needPrint'] == dict::getDict('needPrint', 'need')) {
- OrderClass::onlinePrint($returnOrder);
- $returnOrder->printNum += 1;
- $returnOrder->save();
- }
- }
- return $returnOrder;
- }
- //自取免配送流程处理 ssh 2021.1.24
- public static function withoutSend($order)
- {
- if (isset($order->status) == false) {
- util::fail('没有订单状态');
- }
- if ($order->status == OrderClass::ORDER_STATUS_COMPLETE) {
- util::fail('订单已完成');
- }
- //自取订单,订单直接完成。【现在有三个地方有订单完成操作】
- $shopId = $order->shopId ?? 0;
- $shop = ShopClass::getLockById($shopId);
- if (empty($shop)) {
- util::fail('没有找到门店3');
- }
- $shop->unSendOrder -= 1;
- $shop->sendingOrder += 1;
- $shop->save();
- //自取免配送
- $order->sendType = OrderClass::SEND_TYPE_NO;
- $order->save();
- //这个是采购模板的withoutSend,应另外封装方法
- $purchaseId = $order->purchaseId ?? 0;
- $purchase = PurchaseClass::getById($purchaseId, true);
- $pShopId = $purchase->shopId;
- $pShop = ShopClass::getLockById($pShopId);
- $pShop->cgUnSend -= 1;
- $pShop->cgSending += 1;
- $pShop->save();
- //订单完成
- self::finish($order, $shop);
- OrderSendClass::withoutSend($order);
- return OrderClass::TOTAL_FLOW;
- }
- //确认送达 ssh 2021.3.4
- public static function reach($order)
- {
- if ($order->status != OrderClass::ORDER_STATUS_SENDING) {
- util::fail('订单没有在配送状态');
- }
- //第三方配送的变更第三方订单状态
- if (isset($order->sendType) && $order->sendType == OrderClass::SEND_TYPE_THIRD) {
- $express = OrderExpressClass::getByCondition(['orderSn' => $order->orderSn], true);
- if (!empty($express)) {
- $express->status = OrderExpressClass::STATUS_COMPLETE;
- $express->save();
- }
- }
- $shopId = $order->shopId ?? 0;
- $shop = ShopClass::getLockById($shopId);
- if (empty($shop)) {
- util::fail('没有找到门店4');
- }
- //订单完成
- self::finish($order, $shop);
- OrderSendClass::reach($order);
- //是否微信通知
- $noNeedWxNotice = isset(Yii::$app->params['noNeedWxNotice']) ? Yii::$app->params['noNeedWxNotice'] : 0;
- if ($noNeedWxNotice == 0) {
- //微信通知
- WxMessageClass::reachInform($shop, $order);
- }
- }
- //订单完成
- public static function finish($order, $shop)
- {
- //销售单完成
- $order = OrderClass::complete($order, $shop);
- //采购单完成
- $purchaseId = $order->purchaseId ?? 0;
- $purchase = PurchaseClass::getById($purchaseId, true);
- PurchaseClass::complete($purchase);
- }
- //获取订单信息 ssh 2019.11.28
- public static function getOrderList($where)
- {
- $data = self::getList('*', $where, 'addTime DESC');
- if (isset($data['list']) == false || empty($data['list'])) {
- return $data;
- }
- $orderSns = array_column($data['list'], 'orderSn');
- //获取订单的商品信息
- $goodsList = OrderGoodsService::getGoodsListByOrderSns($orderSns);
- //获取订花人的用户信息
- $orderUserIds = array_column($data['list'], 'userId');
- $orderUserIds = array_unique($orderUserIds);
- $userInfoList = UserService::getUserByIds($orderUserIds);
- $sjIdList = array_column($data['list'], 'sjId');
- $sjIdList = array_filter(array_unique($sjIdList));
- $merchantList = MerchantService::getByIds($sjIdList, null, 'id');
- $periodData = [0 => '上午', 1 => '下午', 2 => '晚上'];
- foreach ($data['list'] as $key => $val) {
- $id = $val['id'];
- $userId = $val['userId'];
- $data['list'][$key]['goodsInfoList'] = isset($goodsList[$id]) ? $goodsList[$id] : [];
- $data['list'][$key]['bookAvatar'] = isset($userInfoList[$userId]['smallAvatarUrl']) ? $userInfoList[$userId]['smallAvatarUrl'] : '';
- $sjId = $val['sjId'];
- $data['list'][$key]['name'] = isset($merchantList[$sjId]['name']) ? $merchantList[$sjId]['name'] : '';
- $data['list'][$key]['reachTime'] = OrderClass::getReachTime($val);
- $requireReachTime = '';
- if ($val['reachDate'] != '0000-00-00') {
- $reachPeriodId = $val['reachPeriod'];
- $reachPeriod = isset($periodData[$reachPeriodId]) ? $periodData[$reachPeriodId] : '上午';
- $requireReachTime = date("m-d", strtotime($val['reachDate'])) . ' ' . $reachPeriod;
- }
- $data['list'][$key]['requireReachTime'] = $requireReachTime;
- }
- return $data;
- }
- //取客户最近若干条订单 ssh 2019.11.30
- public static function getUserOrder($userId, $limit = 10, $order = null, $with = null)
- {
- $where = ['userId' => $userId, 'payStatus' => 1];
- return self::getLimitList('*', $where, $limit, $order, $with);
- }
- //支付前验证订单 ssh 2019.12.6
- public static function checkBeforePay($order, $userId)
- {
- $now = time();
- if (empty($order)) {
- util::fail('订单无效');
- }
- if (isset($order['userId']) && $order['userId'] != $userId) {
- util::fail('非法访问');
- }
- if ($order['status'] != 0) {
- util::fail('订单不是待付款状态');
- }
- if (isset($order['deadline']) && $now > $order['deadline']) {
- util::fail('订单已过期');
- }
- if (ceil($order['actPrice']) <= 0) {
- util::fail('订单金额有问题');
- }
- if ($order['payStatus'] == 1) {
- util::fail('您已经付过了');
- }
- }
- //商家验证是否有效 ssh 2019.12.15
- public static function valid($order, $shopId)
- {
- $now = date("Y-m-d H:i:s");
- if (empty($order)) {
- util::fail('订单无效');
- }
- if ($order['shopId'] != $shopId) {
- util::fail('不是您的订单');
- }
- if (isset($order['status']) && $order['status'] == OrderClass::ORDER_STATUS_UN_PAY) {
- if (isset($order['deadline']) && $now > $order['deadline']) {
- util::fail('订单已过期');
- }
- }
- }
- //点评 ssh 2019.12.16
- public static function comment($data)
- {
- return OrderClass::comment($data);
- }
- //订单归类
- public static function classify($id, $categoryId, $usageId)
- {
- $connection = Yii::$app->db;
- $transaction = $connection->beginTransaction();
- try {
- $order = OrderClass::getById($id, true);
- if ($order->payStatus != 1) {
- util::fail('订单还未付款');
- }
- if ($order->classify == 1) {
- util::fail('已经归类过了');
- }
- $order->categoryId = $categoryId;
- $order->usageId = $usageId;
- $order->classify = 1;
- $order->save();
- //设置流水的分类和用途并分配资金
- $setData = [
- 'sjId' => $order->sjId,
- 'capitalId' => $order->capitalId,
- 'time' => $order->payTime,
- 'usageId' => $order->usageId,
- 'categoryId' => $order->categoryId,
- 'amount' => $order->actPrice,
- 'payWay' => $order->payWay,
- ];
- SjCapitalService::orderClassify($setData);
- $transaction->commit();
- } catch (Exception $e) {
- $transaction->rollBack();
- util::fail('没有归类成功');
- }
- }
- //更新配送单 ssh 2019.12.17
- public static function updateSheet($order, $data)
- {
- $id = $order['id'];
- if ($order['status'] != OrderClass::ORDER_STATUS_UN_SEND) {
- util::fail('订单当前不是待配送状态');
- }
- $data['deliver'] = 1;
- OrderClass::updateById($id, $data);
- }
- //订单详情 ssh 2020.1.2
- public static function getOrderById($id)
- {
- return OrderClass::getOrderById($id);
- }
- //查看订单详情 ssh 2020.1.4
- public static function getOrderBySn($orderSn)
- {
- return OrderClass::getOrderBySn($orderSn);
- }
- //计算优惠 ssh 2020.3.9
- public static function getDiscountPrice($params)
- {
- $couponId = isset($params['couponId']) ? $params['couponId'] : 0;
- $userId = isset($params['userId']) ? $params['userId'] : 0;
- $price = isset($params['price']) ? $params['price'] : 0;
- $sourceType = isset($params['sourceType']) ? $params['sourceType'] : 0;
- $discountAmount = 0;
- $discountType = 0;
- $discountPrice = $price;
- //使用优惠券
- if (!empty($couponId)) {
- $discountAmount = CouponService::checkBeforeUse($couponId, $price, $userId);
- $discountPrice = stringUtil::calcSub($price, $discountAmount);
- $discountType = 1;
- } else {
- //使用会员
- // $asset = UserAssetClass::getByUserId($userId);
- // if (isset($asset['member']) && $asset['member'] > 0) {
- // $currentDiscount = $asset['discount'];
- // $currentPrice = $price * $currentDiscount;
- // $newPrice = substr(sprintf("%.3f", $currentPrice), 0, -1);
- // $discountType = 2;
- // $discountAmount = stringUtil::calcSub($price, $newPrice);
- // $discountPrice = $newPrice;
- // }
- }
- //如果没有优惠券和会员优惠,并且是朋友圈收款,则进行随机优惠 ssh 2019.9.12
- if ($discountPrice == $price && $sourceType == 3) {
- $discountAmount = OrderClass::getRandDiscount($price);
- //开发和测试环境直接随机优惠
- $env = getenv('YII_ENV');
- if ($env == 'local' || $env == 'test') {
- $discountAmount = 0.01;
- }
- $discountPrice = stringUtil::calcSub($price, $discountAmount);
- $discountType = 3;
- }
- $discountType = $discountAmount <= 0 ? 0 : $discountType;
- $discountPrice = $discountPrice <= 0 ? 0.01 : $discountPrice;
- return ['price' => $discountPrice, 'discountType' => $discountType, 'discountAmount' => $discountAmount];
- }
- //获取订单详情 ssh 2021.1.21
- public static function getOrderInfo($id, $showButton = false, $showItem = false, $showExpress = false, $isList = false)
- {
- $order = OrderClass::getById($id, true);
- if (empty($order)) {
- util::fail('没有找到订单');
- }
- $info = $order->attributes;
- $respond = OrderClass::groupOrder([$info], $showButton, $showItem, $showExpress, $isList);
- $result = current($respond);
- $orderId = intval($result['id'] ?? 0);
- $result['orderClearList'] = $orderId > 0 ? OrderCgClearClass::listPaidClearRecordsForOrder($orderId) : [];
- return $result;
- }
- //订单失效后的操作 ssh 2021.5.14
- public static function expire($order)
- {
- $purchaseId = $order->purchaseId ?? 0;
- $current = PurchaseClass::getById($purchaseId, true);
- if (empty($current)) {
- util::fail('没有找到采购单');
- }
- PurchaseService::expire($current);
- return true;
- }
- //支付成功后的流程 ssh 2021.5.14
- //$isPurchase 是否零售端采购支付,如果是会引起销售方余额变动
- public static function payAfter($order, $payWay, $isPurchase = false)
- {
- if (isset($order->status) == false) {
- util::fail('没有订单状态');
- }
- if ($order->status != OrderClass::ORDER_STATUS_UN_PAY) {
- util::fail('重复操作');
- }
- if (isset($order->debt) == false) {
- util::fail('订单有问题,没有欠款项');
- }
- $orderId = $order->id;
- $orderSn = $order->orderSn ?? '';
- $customId = $order->customId;
- $ghs = null;
- if (in_array($payWay, [dict::getDict('payWay', 'balancePay'), dict::getDict('payWay', 'debtPay')], true)) {
- $pair = GhsRechargeSettleService::lockAccountPair(['id' => $customId]);
- $custom = $pair['custom'];
- $ghs = $pair['ghs'];
- } else {
- $custom = CustomClass::getLockById($customId);
- }
- if (empty($custom)) {
- util::fail('没有找到客户信息');
- }
- //门店资产变化
- $amount = $order->actPrice ?? 0.00;
- $realPrice = $order->realPrice ?? 0.00;
- $currentShopId = $order->shopId ?? 0;
- $book = $order->book ?? 0;
- $shop = ShopClass::getLockById($currentShopId);
- if (empty($shop)) {
- util::fail('没有找到门店5');
- }
- if ($payWay == dict::getDict('payWay', 'debtPay') && $book != 1) {
- if (isset($shop->overAllowDebt) && $shop->overAllowDebt == 0) {
- $debtLimit = $custom->debtLimit ?? 0;
- $outstanding = \bizGhs\custom\classes\AccountMoneyClass::getOutstandingDebt($custom);
- $newDebt = bcadd((string)$realPrice, (string)$outstanding, 2);
- if (bccomp($newDebt, (string)$debtLimit, 2) > 0) {
- util::fail('待结款已超' . $debtLimit . ',请先结账');
- }
- }
- }
- $mainId = $shop->mainId ?? 0;
- $main = MainClass::getLockById($mainId);
- if (empty($main)) {
- util::fail('没有main信息3');
- }
- $main->unPayOrder -= 1;
- //预订单的待发货订单增加
- if ($book == 1) {
- $main->unSendOrder += 1;
- //预订单统计数量增加
- $itemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
- if (!empty($itemList)) {
- $bookData = [];
- foreach ($itemList as $currentItem) {
- $itemRemark = $currentItem->remark ?? 0;
- $hasRemark = !empty($itemRemark) ? 1 : 0;
- $bookData[] = [
- 'productId' => $currentItem->productId,
- 'num' => $currentItem->xhNum ?? 0,
- 'lastNum' => $currentItem->xhNum ?? 0,
- 'remark' => $itemRemark,
- 'hasRemark' => $hasRemark,
- ];
- }
- $staffId = $order->shopAdminId ?? 0;
- $staffName = $order->shopAdminName ?? '';
- $params = [
- 'staffId' => $staffId, 'staffName' => $staffName, 'action' => 'add'
- ];
- BookItemClass::addBatchItem($bookData, $order, $params);
- }
- } else {
- $main->finishOrder += 1;
- }
- $main->totalOrderNum += 1;
- $currentTotalIncome = bcadd($main->totalIncome, $amount, 2);
- $main->totalIncome = $currentTotalIncome;
- $totalSale = bcadd($main->totalSale, $amount, 2);
- $main->totalSale = $totalSale;
- if ($payWay == dict::getDict('payWay', 'debtPay')) {
- $currentGathering = bcadd($main->mayGathering, $realPrice, 2);
- $main->mayGathering = $currentGathering;
- if ($custom->debtNum == 0) {
- $main->mayGatheringNum += 1;
- }
- }
- $main->save();
- $capitalType = dict::getDict('capitalType', 'xhGhsOrder', 'id');
- $shopAdminId = $order->shopAdminId ?? 0;
- $shopAdminName = $order->shopAdminName ?? '';
- $event = '下单';
- if ($isPurchase) {
- $event = '客户采购';
- if (isset($custom->name) && !empty($custom->name)) {
- $event = $custom->name . '采购';
- }
- }
- $sjId = $order->sjId ?? 0;
- $shopId = $order->shopId ?? 0;
- $capital = [
- 'capitalType' => $capitalType,
- 'relateId' => $orderId,
- 'io' => 1,
- 'amount' => $amount,
- 'totalIncome' => $currentTotalIncome,
- 'payWay' => $payWay,
- 'event' => $event,
- 'mainId' => $mainId,
- 'sjId' => $sjId,
- 'shopId' => $shopId,
- 'shopAdminId' => $shopAdminId,
- 'shopAdminName' => $shopAdminName,
- 'mainId' => $mainId,
- ];
- ShopCapitalClass::addCapital($capital);
- //客户采购,会增加余额,会增加收入
- if ($isPurchase == true) {
- //余额支付和在线支付(微信支付、支付宝支付)会增加余额
- if ($order->onlinePay == dict::getDict('onlinePay', 'yes') || $payWay == dict::getDict('payWay', 'balancePay')) {
- ShopClass::customKdAddBalance($main, $shop, $realPrice, $order, $capitalType);
- }
- }
- //现金付款,现金余额需要增加
- if ($payWay == dict::getDict('payWay', 'cash')) {
- $moneyBalance = bcadd($main->money, $realPrice, 2);
- $main->money = $moneyBalance;
- $main->save();
- $moneyEvent = $custom->name . "现金下单" . floatval($realPrice) . "元(单号 {$orderSn})";
- $moneyRemark = '';
- $change = [
- 'relateId' => $orderId,
- 'amount' => $realPrice,
- 'balance' => $moneyBalance,
- 'io' => 1,
- 'mainId' => $mainId,
- 'capitalType' => $capitalType,
- 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
- 'event' => $moneyEvent,
- 'remark' => $moneyRemark,
- ];
- ShopMoneyChangeClass::addData($change);
- }
- //更新订单基础状态和支付状态
- $order->payWay = $payWay;
- if ($book == 1) {
- $order->status = OrderClass::ORDER_STATUS_UN_SEND;
- } else {
- $order->status = OrderClass::ORDER_STATUS_UN_SEND;
- }
- if ($payWay == dict::getDict('payWay', 'debtPay')) {
- if (isset($order->actPrice) && $order->actPrice == 0) {
- $order->debt = OrderClass::DEBT_NO;
- } else {
- $order->debt = OrderClass::DEBT_YES;
- }
- $order->remainDebtPrice = $order->orderPrice ?? 0;
- $order->debtPrice = $order->orderPrice ?? 0;
- }
- $order->payStatus = 1;
- if (!isset($order->payTime) || $order->payTime == '0000-00-00 00:00:00') {
- $order->payTime = date("Y-m-d H:i:s");
- }
- $order->save();
- //新订单进入队列,用于花材的销量统计
- OrderClass::newOrderAddQueue($order);
- //员工业绩、总业绩增加
- $shopAdminId = $order->shopAdminId ?? 0;
- if (!empty($shopAdminId)) {
- $shopAdmin = ShopAdminClass::getById($shopAdminId, true);
- $shopAdmin->kdAmount = bcadd($shopAdmin->kdAmount, $amount, 2);
- $shopAdmin->save();
- $yjAmount = $order->orderPrice ?? 0;
- StatYjClass::addYj($main, $shop, $shopAdminId, $yjAmount);
- }
- //余额支付
- if ($payWay == dict::getDict('payWay', 'balancePay') && $isPurchase == false) {
- CustomClass::payToChangeBalance($order, $custom, $ghs);
- }
- //欠款
- if ($payWay == dict::getDict('payWay', 'debtPay')) {
- CustomClass::cgDebtAmountAdd($custom, $order, false, $ghs);
- }
- $custom->buyNum += 1;
- $custom->buyAmount = bcadd($custom->buyAmount, $amount, 2);
- $custom->visitTime = date("Y-m-d H:i:s");
- $custom->save();
- //收入统计
- StatIncomeClass::updateOrInsert($main, $shop, $amount);
- //各渠道收入金额统计
- StatKdClass::replace($shop, $amount, $payWay);
- //今日订单+1
- StatOrderClass::updateOrInsert($main, $shop);
- //销售统计
- StatSaleClass::replace($main, $shop, $amount);
- //客户采购统计
- StatKhCgClass::replace($order, $amount);
- //当天同个人同地址的订单汇总
- $prefixDate = substr($order->payTime, 0, 10);
- OrderClass::updateSameTimeIds($order, $prefixDate);
- OrderClass::updateMergeOrder($order, 0);
- }
- //发起退款
- public static function refund($id, $post)
- {
- $order = OrderClass::getLockById($id);
- if (empty($order)) {
- util::fail('没有找到订单');
- }
- // 无支付时间不能售后
- \bizGhs\order\services\NextDayRefundService::assertCanRefund($order);
- $sameDay = intval($post['sameDay'] ?? \bizGhs\order\classes\RefundOrderClass::SAME_DAY_YES);
- // 非当天 / 已结账 / 挂账结清 → 强制隔天售后(sameDay=0),不再拦截为「不能售后」
- if (\bizGhs\order\services\NextDayRefundService::mustUseNextDay($order)) {
- $sameDay = \bizGhs\order\classes\RefundOrderClass::SAME_DAY_NO;
- $post['sameDay'] = $sameDay;
- }
- // 兜底:仍写成当天且已结账时拦截(正常不会走到,mustUseNextDay 已覆盖)
- if ($sameDay === \bizGhs\order\classes\RefundOrderClass::SAME_DAY_YES
- && isset($order->clearId) && !empty($order->clearId)) {
- util::fail('已经结账,请按冲销处理');
- }
- if ($order->debt != 1 && $order->addTime < '2023-10-17 00:00:00') {
- util::fail('10月17日前订单无法申请退款');
- }
- //供货商销售单退款
- $saleRefund = RefundOrderService::addRefund($post, $order);
- $saleRefundId = $saleRefund->id;
- $purchaseId = $order->purchaseId;
- $cg = PurchaseClass::getLockById($purchaseId);
- if (empty($cg)) {
- util::fail('没有找到采购订单');
- }
- $mainId = $cg->mainId ?? 0;
- //花材列表结构
- // [{productId:0,num:1,unitType:0,unitPrice:12,unitName:'扎'}] productId 花材id num 退货数 unitType 大小单位0大1小 unitPrice 售价 unitName单位名称
- //供货商的花材信息转换成零售店的花材信息
- $ghsProduct = $post['product'] ?? '';
- $ghsProductIndex = array_column($ghsProduct, null, 'productId');
- $ids = array_column($ghsProduct, 'productId');
- $ghsProductInfo = ProductClass::getByIds($ids, null, 'itemId');
- $ptItemIds = array_keys($ghsProductInfo);
- $ptItemIds = array_unique(array_filter($ptItemIds));
- $hdProductInfo = ProductClass::getAllByCondition(['mainId' => $mainId, 'itemId' => ['in', $ptItemIds]], null, '*', 'itemId');
- $newProduct = [];
- foreach ($hdProductInfo as $ptItemId => $hdInfo) {
- $ghsItemId = $ghsProductInfo[$ptItemId]['id'] ?? 0;
- $current = $ghsProductIndex[$ghsItemId] ?? [];
- $hdItemId = $hdInfo['id'] ?? 0;
- $cost = $hdInfo['cost'] ?? 0;
- $name = $hdInfo['name'] ?? '';
- $cover = $hdInfo['cover'] ?? '';
- $ratio = $hdInfo['ratio'] ?? 20;
- if (empty($current)) {
- util::fail('没有找到花材');
- }
- $current['productId'] = $hdItemId;
- $current['ptItemId'] = $ptItemId;
- $current['cost'] = $cost;
- $current['name'] = $name;
- $current['cover'] = $cover;
- $current['ratio'] = $ratio;
- $newProduct[] = $current;
- }
- $refundType = $post['refundType'] ?? 0;
- $price = $post['price'] ?? 0;
- $remark = $post['remark'] ?? '';
- $cause = $post['cause'] ?? 0;
- $refundSendCost = isset($post['refundSendCost']) && is_numeric($post['refundSendCost']) ? $post['refundSendCost'] : 0;
- $refundPackCost = isset($post['refundPackCost']) && is_numeric($post['refundPackCost']) ? $post['refundPackCost'] : 0;
- $cgData = [
- 'product' => $newProduct,
- 'refundType' => $refundType,
- 'price' => $price,
- 'remark' => $remark,
- 'cause' => $cause,
- 'refundSendCost' => $refundSendCost,
- 'refundPackCost' => $refundPackCost,
- // 与销售侧售后成对写入隔天标记
- 'sameDay' => $saleRefund->sameDay ?? \bizGhs\order\classes\RefundOrderClass::SAME_DAY_YES,
- 'fundType' => $saleRefund->fundType ?? 0,
- ];
- $cgRefund = CgRefundService::addRefund($cgData, $cg);
- $cgRefundId = $cgRefund->id;
- $saleRefund->cgRefundId = $cgRefundId;
- $saleRefund->save();
- $cgRefund->saleRefundId = $saleRefundId;
- $cgRefund->sameDay = intval($saleRefund->sameDay ?? 1);
- $cgRefund->fundType = intval($saleRefund->fundType ?? 0);
- $cgRefund->save();
- return $saleRefund;
- }
- /**
- * 创建冲销单(金额为负的独立订单)
- * 设计说明:不复用极其庞杂的常规开单主链路(createNewOrder->OrderClass::addOrder),
- * 避免误伤现网所有商户的正常开单流程;只在数据落地时保持与正常订单相同的表结构,方便统一查询/统计。
- * @param $post array 前端提交参数:customId,product(JSON数组),remark,needPrint,payWay,forwardStock,returnBalance,
- * originalRefund(可选,原路退回网关,仅线上支付+关联原单时生效),relateOrderId(可选),refundOrderId(可选)
- * @param $custom array 客户信息(CustomClass::getCustom 返回)
- * @return array ['order'=>冲销单模型, 'customBalance'=>返充后的余额(未返充时为null), 'thirdRefundNo'=>原路退回的网关流水号(未走原路退回时为空)]
- */
- public static function createForwardOrder($post, $custom)
- {
- $customId = $custom['id'] ?? 0;
- $mainId = $post['mainId'] ?? 0;
- $shopId = $post['shopId'] ?? 0;
- $sjId = $post['sjId'] ?? 0;
- $shopAdminId = $post['shopAdminId'] ?? 0;
- $shopAdminName = $post['shopAdminName'] ?? '';
- $ghsId = $custom['ghsId'] ?? 0;
- //售后申请审核转冲销单场景:refundOrderId 是待审核的售后申请(xhRefund)id,
- //由 refundDetail.vue"通过"弹框直接提交而来,商品明细以售后申请里已提交的为准(不信任前端重新传的product),
- //避免和客户/花店实际申请的售后商品不一致;这里锁行是因为最后要把它标记为"已通过"。ssh 冲销单功能
- $refundOrderId = $post['refundOrderId'] ?? 0;
- $refundOrder = null;
- if (!empty($refundOrderId)) {
- $refundOrder = RefundOrderClass::getLockById($refundOrderId);
- if (empty($refundOrder)) {
- util::fail('没有找到售后申请');
- }
- if ($refundOrder->mainId != $mainId) {
- util::fail('售后申请信息不匹配');
- }
- if ($refundOrder->status != 0) {
- util::fail('该售后申请已被处理,请刷新页面');
- }
- if ($refundOrder->customId != $customId) {
- util::fail('售后申请客户信息不匹配');
- }
- $relateOrderSnFromRefund = $refundOrder->relateOrderSn ?? '';
- $relateOrderFromRefund = OrderClass::getByCondition(['orderSn' => $relateOrderSnFromRefund], true);
- if (empty($relateOrderFromRefund)) {
- util::fail('没有找到售后申请关联的原订单');
- }
- $post['relateOrderId'] = $relateOrderFromRefund->id;
- $refundItems = RefundOrderItemClass::getAllByCondition(['orderSn' => $refundOrder->orderSn], null, '*');
- $productList = [];
- foreach ($refundItems as $refundItem) {
- $productList[] = [
- 'productId' => $refundItem['productId'] ?? 0,
- 'bigNum' => ($refundItem['xhUnitType'] ?? 0) == 0 ? ($refundItem['xhNum'] ?? 0) : 0,
- 'smallNum' => ($refundItem['xhUnitType'] ?? 0) == 1 ? ($refundItem['xhNum'] ?? 0) : 0,
- 'price' => $refundItem['xhUnitPrice'] ?? 0,
- ];
- }
- } else {
- $productList = $post['product'] ?? [];
- }
- if (empty($productList)) {
- util::fail('请选择花材');
- }
- $level = $custom['level'] ?? 1;
- $live = isset($custom['live']) ? $custom['live'] : 1;
- $respond = ProductClass::formatProductInfo($productList, $level, $live, ['custom' => $custom]);
- $items = $respond['product'] ?? [];
- if (empty($items)) {
- util::fail('花材信息有误');
- }
- //本次冲销总金额(正数)
- $totalAmount = 0;
- foreach ($items as $it) {
- $totalAmount = bcadd($totalAmount, $it['price'], 2);
- }
- if (bccomp($totalAmount, '0', 2) <= 0) {
- util::fail('冲销金额必须大于0');
- }
- $forwardStock = isset($post['forwardStock']) && in_array((int)$post['forwardStock'], [0, 1], true) ? (int)$post['forwardStock'] : 1;
- $returnBalance = isset($post['returnBalance']) && (int)$post['returnBalance'] == 1 ? 1 : 0;
- //原路退回(仅线上支付关联原单场景可用):是否调支付网关把这笔钱退回给付款人,与"返充到余额"二选一。ssh 冲销单功能
- $originalRefund = isset($post['originalRefund']) && (int)$post['originalRefund'] == 1 ? 1 : 0;
- $payWay = isset($post['payWay']) ? (int)$post['payWay'] : dict::getDict('payWay', 'wxPay');
- //关联原单场景:累计冲销上限校验,并且强制按原单支付方式,不信任前端传的 payWay
- $relateOrderId = $post['relateOrderId'] ?? 0;
- $relateOrder = null;
- $relateCg = null;
- if (!empty($relateOrderId)) {
- $relateOrder = OrderClass::getLockById($relateOrderId);
- if (empty($relateOrder)) {
- util::fail('没有找到原订单');
- }
- if ($relateOrder->mainId != $mainId || $relateOrder->customId != $customId) {
- util::fail('原订单信息不匹配');
- }
- //服务端复核"转冲销单"资格:非当天下单 或者 欠款已结清,二者满足其一才允许,不能只靠前端拦截,
- //避免绕过前端直接调接口对"今天下的、欠款还没结清"的订单发起冲销单。ssh 冲销单功能
- $relatePayTime = $relateOrder->payTime ?? '';
- $notToday = empty($relatePayTime) || date('Y-m-d', strtotime($relatePayTime)) != date('Y-m-d');
- $debtCleared = bccomp($relateOrder->debtPrice ?? 0, '0', 2) > 0 && bccomp($relateOrder->remainDebtPrice ?? 0, '0', 2) == 0;
- if (!$notToday && !$debtCleared) {
- util::fail('该订单不满足转冲销单条件(需为非当天订单,或欠款已结清),请走常规售后流程');
- }
- $actPrice = $relateOrder->actPrice ?? 0;
- $hasForwardPrice = $relateOrder->forwardPrice ?? 0;
- if (bccomp($hasForwardPrice, $actPrice, 2) >= 0) {
- util::fail('该订单已冲销完,无法再次冲销');
- }
- $remain = bcsub($actPrice, $hasForwardPrice, 2);
- if (bccomp($totalAmount, $remain, 2) == 1) {
- util::fail("冲销金额超过原订单可冲销余额(剩余可冲销 ¥{$remain})");
- }
- //退款方式锁定为原单实际支付方式
- $payWay = $relateOrder->payWay ?? $payWay;
- //花店侧原采购单:下面"原路退回"网关退款、以及后面同步hasForward/forwardPrice都要用到,这里统一加锁取一次
- $relateCgId = $relateOrder->purchaseId ?? 0;
- if (!empty($relateCgId)) {
- $relateCg = PurchaseClass::getLockById($relateCgId);
- }
- }
- //资金处理方式按原单支付渠道强制/校验,不完全信任前端传值:仅在"售后转冲销单"(带relateOrderId)场景生效,
- //因为只有这种场景 payWay 才是真实原订单的支付渠道;没有关联原单的自由开冲销单,payWay 只是用户自己选的
- //一个记账渠道说明,并不对应任何真实交易,不需要也不能做这里的强制/原路退回逻辑。
- //挂账、余额支付:欠款本质是负余额,返充余额=冲减欠款,二者在账本层面是同一个动作,强制走"返充余额",不允许原路退回网关
- //微信/支付宝:允许"原路退回"(真实网关退款)与"返充余额"二选一
- if (!empty($relateOrderId)) {
- $wxPay = dict::getDict('payWay', 'wxPay');
- $aliPay = dict::getDict('payWay', 'alipay');
- $debtPay = dict::getDict('payWay', 'debtPay');
- $balancePay = dict::getDict('payWay', 'balancePay');
- if (in_array($payWay, [$debtPay, $balancePay], true)) {
- $returnBalance = 1;
- $originalRefund = 0;
- } elseif (in_array($payWay, [$wxPay, $aliPay], true)) {
- if ($originalRefund == 1) {
- if (empty($relateCg)) {
- util::fail('没有关联原订单的真实交易信息,无法原路退回');
- }
- //原路退回和返充余额二选一,不能同时生效
- $returnBalance = 0;
- }
- } else {
- $originalRefund = 0;
- }
- } else {
- //自由开冲销单:不存在"原路退回网关"这个概念,永远不生效,防止前端异常传参
- $originalRefund = 0;
- }
- //落库统一取负:金额字段为负,数量字段保持正数(代表冲销的数量)
- $negItems = [];
- $totalCost = 0;
- foreach ($items as $it) {
- $it['price'] = bcmul($it['price'], -1, 2);
- $it['userPrice'] = bcmul($it['userPrice'], -1, 2);
- $it['unitPrice'] = bcmul($it['unitPrice'], -1, 2);
- $it['smallUnitPrice'] = bcmul($it['smallUnitPrice'], -1, 2);
- $it['xhPrice'] = bcmul($it['xhPrice'], -1, 2);
- $it['xhUnitPrice'] = bcmul($it['xhUnitPrice'], -1, 2);
- $it['xhPrePrice'] = bcmul($it['xhPrePrice'], -1, 2);
- $it['xhPreUnitPrice'] = bcmul($it['xhPreUnitPrice'], -1, 2);
- $it['cost'] = bcmul($it['cost'], -1, 2);
- $it['forward'] = 1;
- $totalCost = bcadd($totalCost, $it['cost'], 2);
- $negItems[] = $it;
- }
- $actPrice = bcmul($totalAmount, -1, 2);
- $snData = ['shopId' => $shopId, 'mainId' => $mainId, 'ghsId' => $ghsId, 'customId' => $customId];
- $orderSn = orderSn::getGhsOrderSn($snData);
- $now = date('Y-m-d H:i:s');
- $deadline = date('Y-m-d H:i:s', time() + dict::getDict('order_pay_has_time'));
- $orderData = [
- 'mainId' => $mainId,
- 'sendNum' => '',
- 'orderSn' => $orderSn,
- 'customId' => $customId,
- 'customName' => $custom['name'] ?? '',
- 'customNamePy' => $custom['py'] ?? '',
- 'customAvatar' => $custom['shortSmallAvatar'] ?? '',
- 'customMobile' => $custom['mobile'] ?? '',
- 'ghsId' => $ghsId,
- 'sjId' => $sjId,
- 'shopId' => $shopId,
- 'shopAdminId' => $shopAdminId,
- 'shopAdminName' => $shopAdminName,
- 'getStaffId' => $shopAdminId,
- 'getStaffName' => $shopAdminName,
- 'itemNum' => $respond['totalItemNum'] ?? 0,
- 'bigNum' => $respond['bigNum'] ?? 0,
- 'smallNum' => $respond['smallNum'] ?? 0,
- 'itemPrice' => $actPrice,
- 'prePrice' => $actPrice,
- 'orderPrice' => $actPrice,
- 'bookPrice' => $actPrice,
- 'realPrice' => $actPrice,
- 'actPrice' => $actPrice,
- 'totalCost' => $totalCost,
- 'remainCost' => $totalCost,
- 'payWay' => $payWay,
- 'fromType' => 1,
- 'debt' => OrderClass::DEBT_NO,
- 'status' => OrderClass::ORDER_STATUS_COMPLETE,
- 'payStatus' => OrderClass::PAY_STATUS_HAS_PAY,
- 'sendType' => OrderClass::SEND_TYPE_SHOP_GET,
- 'sendStatus' => -4,
- 'sendTimeWant' => date('Y-m-d'),
- 'payTime' => $now,
- 'deadline' => $deadline,
- 'autoSetTime' => $deadline,
- 'needPrint' => $post['needPrint'] ?? 2,
- 'remark' => $post['remark'] ?? '',
- 'forward' => 1,
- 'forwardStock' => $forwardStock,
- 'salt' => stringUtil::charsShuffleLowerCase(10),
- ];
- $order = OrderClass::add($orderData, true);
- foreach ($negItems as $it) {
- $it['orderSn'] = $orderSn;
- $it['mainId'] = $mainId;
- OrderItemClass::add($it, true);
- }
- //库存处理:forwardStock==0 货退回来则加库存,==1 不退回则不动库存
- if ($forwardStock == 0) {
- $customName = $custom['name'] ?? '';
- foreach ($negItems as $it) {
- $productId = $it['productId'] ?? 0;
- $itemNum = $it['num'] ?? 0;
- if (empty($productId) || bccomp($itemNum, '0', 2) <= 0) {
- continue;
- }
- $stockInfo = ProductClass::addStockByItemNum($productId, $itemNum);
- $recordData = [
- 'sjId' => $sjId,
- 'shopId' => $shopId,
- 'mainId' => $mainId,
- 'orderSn' => $orderSn,
- 'itemId' => $it['itemId'] ?? 0,
- 'productId' => $productId,
- 'itemNum' => $itemNum,
- 'oldStock' => $stockInfo['oldStock'] ?? 0,
- 'newStock' => $stockInfo['newStock'] ?? 0,
- 'relateName' => $customName,
- 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
- 'io' => 1,
- ];
- StockRecordClass::ghsRefundAddRecord($recordData);
- }
- }
- //配对生成花店侧采购冲销记录 xhCg/xhCgItem,直接构造模型保存,不复用 PurchaseClass::addPurchase 的完整业务规则
- //此处需要加锁,因为下面还要用它同步扣减 xhGhs.expendAmount(累计消费镜像字段)
- $ghs = GhsClass::getLockById($ghsId);
- $cgSn = orderSn::getPurchaseSn($snData);
- $cgData = [
- 'mainId' => $ghs['ownMainId'] ?? 0,
- 'saleId' => $order->id ?? 0,
- 'orderSn' => $cgSn,
- 'customId' => $customId,
- 'ghsId' => $ghsId,
- 'ghsName' => $ghs['name'] ?? '',
- 'ghsAvatar' => $ghs['avatar'] ?? '',
- 'ghsMobile' => $ghs['mobile'] ?? '',
- 'ghsFullAddress' => $ghs['fullAddress'] ?? '',
- 'sjId' => $custom['sjId'] ?? 0,
- 'shopId' => $custom['shopId'] ?? 0,
- 'ghsShopId' => $shopId,
- 'ghsShopAdminId' => $shopAdminId,
- 'ghsShopAdminName' => $shopAdminName,
- 'itemPrice' => $actPrice,
- 'prePrice' => $actPrice,
- 'orderPrice' => $actPrice,
- 'bookPrice' => $actPrice,
- 'realPrice' => $actPrice,
- 'actPrice' => $actPrice,
- 'kindNum' => count($negItems),
- 'bigNum' => $respond['bigNum'] ?? 0,
- 'smallNum' => $respond['smallNum'] ?? 0,
- 'payWay' => $payWay,
- 'status' => PurchaseClass::STATUS_COMPLETE,
- 'cgStyle' => dict::getDict('cgStyle', 'ghs'),
- 'debt' => PurchaseClass::DEBT_NO,
- 'getType' => PurchaseClass::GET_TYPE_SELF_GET,
- 'payStatus' => 1,
- 'sendTimeWant' => date('Y-m-d'),
- 'payTime' => $now,
- 'remark' => $post['remark'] ?? '',
- 'forward' => 1,
- 'forwardStock' => $forwardStock,
- 'salt' => stringUtil::charsShuffleLowerCase(10),
- ];
- $cg = PurchaseClass::add($cgData, true);
- $order->purchaseId = $cg->id ?? 0;
- $order->save(false, ['purchaseId']);
- foreach ($negItems as $it) {
- $cgItemData = [
- 'name' => $it['name'] ?? '',
- 'cover' => $it['cover'] ?? '',
- 'orderSn' => $cgSn,
- 'productId' => $it['productId'] ?? 0,
- 'itemId' => $it['itemId'] ?? 0,
- 'mainId' => $cgData['mainId'],
- 'ghsId' => $ghsId,
- 'itemNum' => $it['num'] ?? 0,
- 'preItemNum' => $it['num'] ?? 0,
- 'itemInfo' => json_encode(['itemName' => $it['name'] ?? '', 'bigNum' => $it['bigNum'] ?? 0, 'smallNum' => $it['smallNum'] ?? 0]),
- 'ghsProductId' => $it['productId'] ?? 0,
- 'ratio' => $it['ratio'] ?? 0,
- 'ratioType' => $it['ratioType'] ?? 0,
- 'price' => $it['userPrice'] ?? 0,
- 'totalPrice' => $it['price'] ?? 0,
- 'preTotalPrice' => $it['price'] ?? 0,
- 'variety' => $it['variety'] ?? 0,
- 'unitWeight' => $it['unitWeight'] ?? 0,
- 'belongCost' => $it['belongCost'] ?? 0,
- 'remark' => $it['remark'] ?? '',
- 'kind' => $it['kind'] ?? 0,
- 'forward' => 1,
- ];
- PurchaseItemClass::add($cgItemData, true);
- }
- //累计消费金额同步:冲销单本质是负金额订单,$actPrice 已经是负数。
- //xhGhsCustom.buyAmount 与 xhGhs.expendAmount 是同一份"累计消费"的两边镜像
- //(参考 CustomController::actionRefreshBuyamount 按订单 actPrice 汇总重算两边字段的口径),
- //这里直接按 actPrice 同步扣减,两边保持一致;但冲销单不算一次新的"下单",buyNum/买入次数不增加。
- $lockCustom = CustomClass::getLockById($customId);
- if (empty($lockCustom)) {
- util::fail('没有找到客户');
- }
- $lockCustom->buyAmount = bcadd($lockCustom->buyAmount ?? '0.00', $actPrice, 2);
- $lockCustom->save(false, ['buyAmount']);
- $ghs->expendAmount = bcadd($ghs->expendAmount ?? '0.00', $actPrice, 2);
- $ghs->save(false, ['expendAmount']);
- //资金处理:originalRefund==1 调支付网关原路退回给付款人;returnBalance==1 加回客户余额;
- //两者都为0时不改动任何资金字段,只把 payWay 记在订单上作为返款渠道记录。ssh 冲销单功能
- $customBalance = null;
- $thirdRefundNo = '';
- if ($originalRefund == 1) {
- //原路退回:用原单对应的采购单(xhCg)真实支付信息调网关退款,用冲销单自己的orderSn做退款流水号,天然保证唯一/幂等
- $thirdRefundNo = PurchaseClass::forwardOriginalOnlineRefund($relateCg, $orderSn, $totalAmount, '冲销单' . $orderSn . '原路退回');
- $order->remark = trim(($order->remark ?? '') . " [原路退回成功,网关退款单号:{$thirdRefundNo}]");
- $order->save(false, ['remark']);
- } elseif ($returnBalance == 1) {
- $customBalance = CustomClass::forwardReturnBalance($lockCustom, $order, $totalAmount);
- }
- //关联原单:写关系表 + 同步原单 hasForward/forwardPrice 与订单项 forwardNum
- if (!empty($relateOrderId) && !empty($relateOrder)) {
- OrderForwardClass::addRelate($relateOrder, $order, $totalAmount);
- $relateOrder->hasForward = 1;
- $relateOrder->forwardPrice = bcadd($relateOrder->forwardPrice ?? 0, $totalAmount, 2);
- $relateOrder->save(false, ['hasForward', 'forwardPrice']);
- $relateItems = OrderItemClass::getAllByCondition(['orderSn' => $relateOrder->orderSn], null, '*', 'productId', true);
- foreach ($negItems as $it) {
- $productId = $it['productId'] ?? 0;
- $relateItem = $relateItems[$productId] ?? null;
- if (!empty($relateItem)) {
- $relateItem->forward = 1;
- $relateItem->forwardNum = bcadd($relateItem->forwardNum ?? 0, $it['num'] ?? 0, 2);
- $relateItem->save(false, ['forward', 'forwardNum']);
- }
- }
- //同步花店侧原采购单(xhCg)的 hasForward/forwardPrice 与采购单项(xhCgItem)的 forwardNum,
- //供 hdApp 的 purDetails.vue/refundList.vue 展示冲销记录,与 GHS 侧原单缓存字段保持一致
- //($relateCg 已在前面校验资金处理方式时统一加锁取过,这里直接复用,避免重复查询/重复加锁)
- if (!empty($relateCg)) {
- $relateCg->hasForward = 1;
- $relateCg->forwardPrice = bcadd($relateCg->forwardPrice ?? 0, $totalAmount, 2);
- $relateCg->save(false, ['hasForward', 'forwardPrice']);
- $relateCgItems = PurchaseItemClass::getAllByCondition(['orderSn' => $relateCg->orderSn], null, '*', 'productId', true);
- foreach ($negItems as $it) {
- $productId = $it['productId'] ?? 0;
- $relateCgItem = $relateCgItems[$productId] ?? null;
- if (!empty($relateCgItem)) {
- $relateCgItem->forward = 1;
- $relateCgItem->forwardNum = bcadd($relateCgItem->forwardNum ?? 0, $it['num'] ?? 0, 2);
- $relateCgItem->save(false, ['forward', 'forwardNum']);
- }
- }
- }
- }
- //售后申请审核转冲销单:这条售后申请本身并没有走老的 passRefund 流程(没有原路退款/没有改原订单actPrice等),
- //真正的退款/退货/返余额是由上面新生成的这张冲销单完成的,所以不能标"已通过"(会让人误以为是走了老流程原路退款)。
- //这里标"已取消",并把冲销单号写进 hdRemark 备注,同时用 forwardOrderId 结构化记录对应的冲销单id,
- //方便后续排查/统计这条售后申请最终去了哪(forwardOrderId=0表示常规售后,未转冲销单)。ssh 冲销单功能
- if (!empty($refundOrder)) {
- $refundOrder->status = RefundOrderClass::STATUS_CANCEL;
- $refundOrder->forwardOrderId = $order->id;
- $refundOrder->hdRemark = '已转为冲销单处理,退款/退货/返余额流程详见冲销单:' . $orderSn;
- $refundOrder->shopAdminId = $shopAdminId;
- $refundOrder->shopAdminName = $shopAdminName;
- $refundOrder->save(false, ['status', 'forwardOrderId', 'hdRemark', 'shopAdminId', 'shopAdminName']);
- //明细项同步标记为"已取消",与父级售后申请的status保持一致(不再是"已处理",因为并没有走老的passRefund流程去处理它)
- $refundItemModels = RefundOrderItemClass::getAllByCondition(['orderSn' => $refundOrder->orderSn], null, '*', null, true);
- foreach ($refundItemModels as $refundItemModel) {
- $refundItemModel->status = RefundOrderClass::STATUS_CANCEL;
- $refundItemModel->save(false, ['status']);
- }
- //同步花店端(hdApp)对应的售后记录(xhCgRefund):一条售后在GHS/HD两端各有一条记录(通过cgRefundId关联),
- //两端都要能看出"这条售后已转冲销单",HD侧记录的是花店视角的冲销采购单id(xhCg.id)
- $cgRefundId = $refundOrder->cgRefundId ?? 0;
- if (!empty($cgRefundId)) {
- $cgRefund = CgRefundClass::getLockById($cgRefundId);
- if (!empty($cgRefund)) {
- $cgRefund->forwardCgId = $cg->id ?? 0;
- $cgRefund->hdRemark = '已转为冲销单处理,退款/退货/返余额流程详见冲销单:' . $cgSn;
- $cgRefund->save(false, ['forwardCgId', 'hdRemark']);
- }
- }
- }
- return ['order' => $order, 'customBalance' => $customBalance, 'thirdRefundNo' => $thirdRefundNo];
- }
- }
|