Order.php 123 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469
  1. <?php
  2. namespace addons\Happiness\common\models;
  3. use addons\CardCoupons\common\models\CardCouponsScoreGive;
  4. use addons\Chanjet\common\global_func\Request;
  5. use addons\Chanjet\common\models\AddonsChanjetRequest;
  6. use addons\Community\common\service\HeadService;
  7. use addons\Coupon\common\models\AddonsCouponUserRelate;
  8. use addons\Mch\common\models\Mch;
  9. use addons\PaySuccessJump\common\service\JumpUrlService;
  10. use addons\RandFee\common\service\RandFeeService;
  11. use addons\ShoppingLottery\common\helper\LotteryHelper;
  12. use addons\Store\common\models\StoreOrder;
  13. use addons\Store\common\models\StoreOrderDetail;
  14. use addons\Store\common\models\StoreOrderMarketing;
  15. use addons\Happiness\common\service\OrderService;
  16. use common\components\export\CsvTool;
  17. use common\enums\AddonsChanjetRequestEnum;
  18. use common\enums\AddonsEnum;
  19. use common\enums\DownloadEnum;
  20. use common\enums\OrderSourceEnum;
  21. use common\enums\OrderStatusEnum;
  22. use common\enums\PayTypeEnum;
  23. use common\enums\RedisKeyEnum;
  24. use common\enums\RefundStatusEnum;
  25. use common\enums\RefundTypeEnum;
  26. use common\enums\ShippingStatusEnum;
  27. use common\enums\ShippingTypeEnum;
  28. use common\enums\StatusEnum;
  29. use common\enums\UserWalletEnum;
  30. use common\events\data\api\OrderToPayEvent;
  31. use common\events\order\OrderChangeAddressEvent;
  32. use common\events\order\OrderCloseEvent;
  33. use common\events\order\OrderCommentEvent;
  34. use common\events\order\OrderCreateEvent;
  35. use common\events\order\OrderDelEvent;
  36. use common\events\order\OrderFinishEvent;
  37. use common\events\order\OrderPaidEvent;
  38. use common\events\order\OrderReminderShipmentEvent;
  39. use common\events\order\OrderTakeDeliveryEvent;
  40. use common\helpers\ArrayHelper;
  41. use common\helpers\LockHelper;
  42. use common\models\cart\Cart;
  43. use common\models\common\Addons;
  44. use common\models\common\Download;
  45. use common\models\common\PaymentTrade;
  46. use common\models\common\PaymentTradeGroupOrder;
  47. use common\models\common\PaymentTradeOrder;
  48. use common\models\goods\Goods;
  49. use common\models\goods\GoodsAttr;
  50. use common\models\goods\GoodsCate;
  51. use common\models\goods\GoodsCateRelate;
  52. use common\models\goods\GoodsExtra;
  53. use common\models\mall\MallAddons;
  54. use common\models\order\OrderAction;
  55. use common\models\order\OrderComments;
  56. use common\models\order\OrderCommentsExtra;
  57. use common\models\order\OrderDetail;
  58. use common\models\order\OrderExpress;
  59. use common\models\order\OrderExpressLog;
  60. use common\models\order\OrderExtra;
  61. use common\models\order\OrderMarketing;
  62. use common\models\order\OrderRefund;
  63. use common\models\order\OrderReserve;
  64. use common\models\order\OrderReserveComments;
  65. use common\models\order\OrderUserHandle;
  66. use common\models\user\User;
  67. use common\models\user\UserPartitionRelationship;
  68. use common\models\user\UserSignAgreement;
  69. use Exception;
  70. use services\common\UserWalletService;
  71. use Yii;
  72. use yii\helpers\Json;
  73. /**
  74. * This is the model class for table "{{%order}}".
  75. *
  76. *
  77. * @property int $id 订单id
  78. * @property int $mall_id 商城id
  79. * @property int $mch_id 多商户id,0表示商城订单
  80. * @property int $store_id 门店id,
  81. * @property int $user_id 用户id
  82. * @property string $order_no 订单编号
  83. * @property string|null $out_trade_no 外部交易号
  84. * @property string|null $mobile 收货人的手机号码
  85. * @property int|null $province 收货人所在省
  86. * @property int|null $city 收货人所在城市
  87. * @property int|null $area 收货人所在街道
  88. * @property int|null $town 收货人所在镇
  89. * @property int|null $community 收货人所在镇
  90. * @property string|null $address 收货人详细地址
  91. * @property string|null $region_name 收货人详细地址
  92. * @property string|null $zip 收货人邮编
  93. * @property string|null $name 收货人姓名
  94. * @property string|null $receiver_name 收货人姓名
  95. * @property string $remark 用户订单备注
  96. * @property string $seller_remark 商家订单备注
  97. * @property int|null $shipping_type 订单配送方式
  98. * @property float|null $shipping_money 订单运费
  99. * @property float|null $reduce_shipping_money 满邮减免
  100. * @property float|null $refund_money 订单退款金额
  101. * @property float|null $pay_money 订单实付金额
  102. * @property float|null $goods_price 商品优惠后总价
  103. * @property float|null $original_goods_price 商品原本总价
  104. * @property string|null $ip 买家ip
  105. * @property int|null $coupon_id 优惠券券id
  106. * @property float|null $coupon_money 优惠券券支付金额
  107. * @property int|null $score 订单消耗积分
  108. * @property float|null $score_money 订单消耗积分抵多少钱
  109. * @property int|null $order_status 订单状态
  110. * @property int|null $pay_status 订单付款状态
  111. * @property int|null $shipping_status 订单配送状态
  112. * @property int|null $review_status 订单评价状态
  113. * @property int|null $is_feedback 订单售后状态
  114. * @property int|null $payment_type 支付类型
  115. * @property int $marketing_id 营销活动id
  116. * @property string $marketing_type 营销活动类型
  117. * @property int|null $invoice_id 发票id
  118. * @property int|null $status 状态[-1:删除;0:禁用;1启用]
  119. * @property int $is_comment 是否评价 0为未评价 1为已评价 2为已追评
  120. * @property int $is_recycle 是否加入回收站【1是 0否】
  121. * @property int|null $is_virtual 是否包含虚拟商品【1是 0否】
  122. * @property int|null $is_new_user 是否新顾客
  123. * @property int|null $pay_time 订单付款时间
  124. * @property int|null $shipping_time 买家要求配送时间
  125. * @property int|null $sign_time 买家签收时间
  126. * @property int|null $consign_time 卖家发货时间
  127. * @property int|null $finish_time 订单完成时间
  128. * @property int|null $close_time 关闭的时间
  129. * @property string|null $extra_info 额外信息
  130. * @property string|null $order_source 订单来源:JuheShop=>聚合供应链
  131. * @property int|null $created_at 创建时间
  132. * @property int|null $updated_at 更新时间
  133. * @property string|null $clerk_code 核销码
  134. */
  135. class Order extends \common\models\base\BaseActiveRecord
  136. {
  137. const DEFAULT = 'order';
  138. public static $getRefundId;
  139. /**
  140. * {@inheritdoc}
  141. */
  142. public static function tableName()
  143. {
  144. return '{{%order}}';
  145. }
  146. /**
  147. * {@inheritdoc}
  148. */
  149. public function rules()
  150. {
  151. return [
  152. [['mch_id','store_id', 'mall_id','user_id', 'province', 'city', 'area','town', 'shipping_type', 'coupon_id', 'order_status', 'pay_status', 'shipping_status', 'review_status', 'is_feedback', 'payment_type', 'marketing_id', 'invoice_id', 'status', 'is_comment', 'is_recycle', 'is_virtual', 'is_new_user', 'pay_time', 'shipping_time', 'sign_time', 'consign_time', 'finish_time', 'close_time', 'created_at', 'updated_at', 'community','is_bill','bill_time'], 'integer'],
  153. [['shipping_money', 'reduce_shipping_money', 'refund_money', 'pay_money', 'score', 'goods_price', 'original_goods_price', 'coupon_money', 'score_money'], 'number'],
  154. [['order_no', 'out_trade_no'], 'string', 'max' => 100],
  155. [['mobile'], 'safe'],
  156. [['address', 'region_name'], 'string', 'max' => 200],
  157. [['zip', 'ip'], 'string', 'max' => 20],
  158. [['receiver_name', 'marketing_type', 'order_source'], 'string', 'max' => 50],
  159. [['remark', 'seller_remark'], 'string', 'max' => 255],
  160. [['extra_info'], 'string'],
  161. [['clerk_code'], 'string', 'max' => 12],
  162. ];
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. public function attributeLabels()
  168. {
  169. return [
  170. 'id' => '订单id',
  171. 'mall_id' => '商城ID',
  172. 'mch_id' => '多商户id,0表示商城订单',
  173. 'store_id' => '门店i',
  174. 'user_id' => '用户id',
  175. 'order_no' => '订单编号',
  176. 'out_trade_no' => '外部交易号',
  177. 'mobile' => '收货人的手机号码',
  178. 'province' => '收货人所在省',
  179. 'city' => '收货人所在城市',
  180. 'area' => '收货人所在街道',
  181. 'town' => '收货人所在镇',
  182. 'address' => '收货详细地址',
  183. 'region_name' => '收货地区名称(省市区[乡/镇])',
  184. 'zip' => '收货人邮编',
  185. 'receiver_name' => '收货人姓名',
  186. 'remark' => '用户订单备注',
  187. 'seller_remark' => '商家订单备注',
  188. 'shipping_type' => '订单配送方式',
  189. 'shipping_money' => '订单运费',
  190. 'reduce_shipping_money' => '满邮减免',
  191. 'refund_money' => '订单退款金额',
  192. 'pay_money' => '订单实付金额',
  193. 'goods_price' => '商品优惠后总价',
  194. 'original_goods_price' => '商品原本总价',
  195. 'ip' => '买家ip',
  196. 'coupon_id' => '优惠券券id',
  197. 'coupon_money' => '优惠券券支付金额',
  198. 'score' => '订单消耗积分',
  199. 'score_money' => '订单消耗积分抵多少钱',
  200. 'order_status' => '订单状态',
  201. 'pay_status' => '订单付款状态',
  202. 'shipping_status' => '订单配送状态',
  203. 'review_status' => '订单评价状态',
  204. 'is_feedback' => '订单售后状态:0:未售后;1:售后中;2:售后完成',
  205. 'payment_type' => '支付类型',
  206. 'marketing_id' => '营销活动id',
  207. 'marketing_type' => '营销活动类型',
  208. 'invoice_id' => '发票id',
  209. 'status' => '状态[-1:删除;0:禁用;1启用]',
  210. 'is_comment' => '是否评价 0为未评价 1为已评价 2为已追评',
  211. 'is_recycle' => '是否加入回收站【1是 0否】',
  212. 'is_virtual' => '是否包含虚拟商品【1是 0否】',
  213. 'is_new_user' => '是否新顾客',
  214. 'pay_time' => '订单付款时间',
  215. 'shipping_time' => '买家要求配送时间',
  216. 'sign_time' => '买家签收时间',
  217. 'consign_time' => '卖家发货时间',
  218. 'finish_time' => '订单完成时间',
  219. 'close_time' => '关闭的时间',
  220. 'extra_info' => '额外信息',
  221. 'created_at' => '创建时间',
  222. 'updated_at' => '更新时间',
  223. 'clerk_code' => '核销码',
  224. ];
  225. }
  226. // 关联模型
  227. public function getUser()
  228. {
  229. return $this->hasOne(User::class, ['id' => 'user_id']);
  230. }
  231. public function getBase_user()
  232. {
  233. return $this->hasOne(User::class, ['id' => 'user_id'])->select(['id', 'username','nickname', 'avatar_url','mobile']);
  234. }
  235. public function getDetail()
  236. {
  237. return $this->hasMany(OrderDetail::class, ['order_id' => 'id']);
  238. }
  239. public function getExpress()
  240. {
  241. return $this->hasMany(OrderExpress::class, ['order_id' => 'id'])->where(['status' => StatusEnum::ENABLED]);
  242. }
  243. public function getExpress_log()
  244. {
  245. return $this->hasMany(OrderExpressLog::class, ['order_id' => 'id'])->where(['status' => StatusEnum::ENABLED]);
  246. }
  247. public function getReserve()
  248. {
  249. return $this->hasOne(OrderReserve::class, ['order_id' => 'id']);
  250. }
  251. /**
  252. * @return ActiveQueryInterface
  253. */
  254. public function getTrade()
  255. {
  256. return $this->hasOne(PaymentTrade::class, ['out_trade_no' => 'out_trade_no']);
  257. }
  258. public function getExtra()
  259. {
  260. return $this->hasOne(OrderExtra::class,['order_id' => 'id']);
  261. }
  262. /**
  263. * 畅捷通请求
  264. *
  265. * @return \yii\db\ActiveQuery
  266. */
  267. public function getAddonsChanjetRequest()
  268. {
  269. return $this
  270. ->hasOne(AddonsChanjetRequest::class, ['table_id' => 'id'])
  271. ->orderBy('updated_at desc')
  272. ->select('id, table_id, request_status, updated_at')
  273. ->where([
  274. 'table' => self::tableName(),
  275. 'path' => [Request::PATHS['SALE_DELIVERY_CREATE_BATCH']]
  276. ])
  277. ->andWhere(['>', 'request_status', 0]);
  278. }
  279. /**
  280. * @Author bing
  281. * @DateTime 2021-09-14 11:24:22
  282. * @copyright: Copyright (c) 2020 广东七件事集团
  283. * @param [type] $insert
  284. * @return void
  285. */
  286. public function beforeSave($insert)
  287. {
  288. // 未支付/未付款
  289. if ($this->isNewRecord || $this->order_status == OrderStatusEnum::NOT_PAY) {
  290. // 支付金额为产品金额
  291. if ($this->goods_price) {
  292. $this->pay_money = $this->goods_price;
  293. }
  294. // 实付增加运费
  295. if ($this->pay_money && $this->shipping_money) {
  296. $this->pay_money += $this->shipping_money - $this->reduce_shipping_money;
  297. }
  298. // 随机减金额计算,因为未支付前无法更改实付金额,所以只能在此处进行修改
  299. if (MallAddons::isInstall($this->mall_id, 'RandFee')) {
  300. $this->pay_money && $this->pay_money = RandFeeService::getRandFee($this->pay_money, $this->order_no);
  301. if(MallAddons::isInstall($this->mall_id,'Store')){
  302. $this->pay_money && StoreOrder::updateAll(['pay_money'=>$this->pay_money,'extra_info'=>$this->extra_info],['order_no'=> $this->order_no]);
  303. }
  304. }
  305. }
  306. // var_dump($this->id, $this->isNewRecord, $this->order_status, $this->oldAttributes['order_status']);
  307. // 修改订单商品状态
  308. if (!$this->isNewRecord && $this->order_status != $this->oldAttributes['order_status']) {
  309. OrderDetail::updateAll(
  310. ['order_status' => $this->order_status],
  311. [ 'order_status' => $this->oldAttributes['order_status'],'order_id' => $this->id]
  312. );
  313. }
  314. // self::orderStastics($orderStatis);
  315. return parent::beforeSave($insert);
  316. }
  317. public static function generateOrderNo($prefix = ''){
  318. // 优化唯一性保证:使用random_int()代替rand(),并结合微调以生成更唯一的ID
  319. $randInt = random_int(100000, 999999);
  320. // 日期时间戳处理
  321. $dateTimeStr = date('YmdHis');
  322. // 保证前缀不为空字符串且不超过一定长度(例如20个字符)
  323. $prefix = trim($prefix, '0');
  324. if (strlen($prefix) > 20) {
  325. $prefix = substr($prefix, 0, 20);
  326. }
  327. // 生成订单号,保证总长度为17(前缀+日期时间戳+随机数)
  328. $orderNo = $prefix . $dateTimeStr . str_pad($randInt, 6, '0', STR_PAD_LEFT);
  329. return $orderNo;
  330. }
  331. public static function createOrder( $form){
  332. $stock_locks = [];
  333. try{
  334. $group_order_goods = $form['group_order_goods'];
  335. $trans = Yii::$app->db->beginTransaction();
  336. $attr = [];
  337. $order_trade_info = [];
  338. $order_ids = [];
  339. $tmp_goods_ids = [];
  340. foreach($group_order_goods as $mch_order){
  341. $mch_order_info = $mch_order['mch_order_info'];
  342. $mch_order_info['mch_id'] = intval($mch_order_info['mch_id']);
  343. $order = new Order();
  344. $order->loadDefaultValues();
  345. if (!empty($mch_order_info['mobile']) && !self::isMobileNumber($mch_order_info['mobile'])) {
  346. throw new Exception('收货人手机号格式不正确');
  347. }
  348. $order->load($mch_order_info,'');
  349. $order->order_status = OrderStatusEnum::NOT_PAY;
  350. if ($form->data['shipping_type'] == ShippingTypeEnum::LOGISTICS) {
  351. empty($order->order_no) && $order->order_no = self::generateOrderNo('s');
  352. } else {
  353. empty($order->order_no) && $order->order_no = self::generateOrderNo('sy');
  354. if ($form->data['shipping_type'] == ShippingTypeEnum::PICKUP) {
  355. //记录核销码
  356. $order->clerk_code = (new OrderService())->getClerkCode($mch_order_info['mall_id']);
  357. }
  358. if (!empty($form->data['extra_info'])) {
  359. $order->receiver_name = $form->data['extra_info']['contact_name'];
  360. $order->mobile = $form->data['extra_info']['contact_phone'];
  361. }
  362. }
  363. $order->store_id = 0;
  364. $res = $order->save();
  365. if($res === false) throw new Exception($order->getErrorMessage());
  366. //记录幸福小店订单
  367. $yun_order_data = [
  368. 'mall_id' => $mch_order_info['mall_id'],
  369. 'user_id' => $mch_order_info['user_id'],
  370. 'store_id' => $form->data['store_id'],
  371. 'order_id' => $order->id,
  372. 'order_no' => $order->order_no,
  373. 'shipping_type' => $form->data['shipping_type'],
  374. 'order_status' => 0,
  375. 'price' => $order->pay_money,
  376. 'parent_id' => $form->data['share_id']??0,
  377. ];
  378. $yun_res = HappinessOrder::setData($yun_order_data);
  379. if (!$yun_res) throw new Exception(HappinessOrder::$static_error);
  380. //记录历史门店数据
  381. HappinessHistoryStore::setData(['mall_id' => $mch_order_info['mall_id'], 'user_id' => $mch_order_info['user_id'], 'store_id' => $form->data['store_id'], 'status' => StatusEnum::ENABLED]);
  382. $order_id = $order->id;
  383. $order_ids[] = $order->id;
  384. //$region_statistics[] = ['mall_id' => $order->mall_id, 'province_id' => $order->province, 'city_id' => $order->city, 'order' => $order->pay_money];
  385. // 总商品库存维护
  386. $goods_stock_arr = [];
  387. // 积分扣除数据
  388. $wallet_deduct_score = [
  389. 'mall_id' => $mch_order_info['mall_id'],
  390. 'user_id' => $mch_order_info['user_id'],
  391. 'is_frozen' => false,
  392. 'wallet_type' => 'score',
  393. 'source_table' => 'order',
  394. 'money' => 0,
  395. 'source_table_id' => $order_id,
  396. 'from_type' => UserWalletEnum::CONSUME,
  397. 'capital_type' => UserWalletEnum::CONSUMPTION_ORDER,
  398. ];
  399. // 遍历商户商品
  400. $goods_ids = array_keys($mch_order['goods']);
  401. array_push($tmp_goods_ids, ...$goods_ids);
  402. foreach($mch_order['goods'] as $goods_id =>$goods){
  403. if ($goods['status'] == 0) continue;
  404. !isset($goods_name) && $goods_name = $goods['goods_name'];
  405. foreach($goods['goods_details'] as $goods_detail){
  406. $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_GOODS_ATTR , $goods_detail['goods_attr_id']);
  407. $identification = uniqid();
  408. if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new Exception('当前访问人数过多');
  409. $stock_locks[$lock_key] = $identification;
  410. //操作商品库存-减
  411. GoodsAttr::handleStock($goods_detail['goods_attr_id'],$goods_detail['num']*-1);
  412. if(!isset($goods_stock_arr[$goods_id])){
  413. $goods_stock_arr[$goods_id] = $goods_detail['num'];
  414. }else{
  415. $goods_stock_arr[$goods_id] += $goods_detail['num'];
  416. }
  417. // 订单详情
  418. $order_detail = new OrderDetail();
  419. $order_detail->loadDefaultValues();
  420. $goods_detail['mch_id'] = intval($goods_detail['mch_id']);
  421. $order_detail->load($goods_detail,'');
  422. $order_detail->order_id = $order_id;
  423. // $goods_statistics[] = ['goods_id' => $goods_detail['goods_id'], 'order_num' => 1, 'sales_num' => $goods_detail['num']];
  424. $res = $order_detail->save();
  425. if($res === false) throw new Exception($order_detail->getErrorMessage());
  426. $attr[$goods_detail['goods_attr_id']] = $goods_detail['num'];
  427. $goods_detail['marketing'] = $goods_detail['marketing'] ?? [];
  428. $goods_detail['marketing'] = OrderMarketing::handleGiveScore($order_detail->mall_id, $goods_detail['marketing'], $order_detail->goods_price - $order_detail->cost_price + $order_detail->adjust_money, $order_detail->num, $order_detail->mch_id);
  429. // 订单营销
  430. if (!empty($goods_detail['marketing'])) {
  431. $order_marketing = new OrderMarketing();
  432. $order_marketing->loadDefaultValues();
  433. $order_marketing->load($goods_detail['marketing'],'');
  434. $order_marketing->order_detail_id = $order_detail->id;
  435. $res = $order_marketing->save();
  436. if($res === false) throw new Exception($order_marketing->getErrorMessage());
  437. }
  438. // 积分扣除
  439. if (isset($goods_detail['marketing']['deduct_score']) && ($deduct_score = $goods_detail['marketing']['deduct_score'])) {
  440. $wallet_deduct_score['money'] = bcmul(bcadd(abs($wallet_deduct_score['money']), $deduct_score, 2), -1, 2);
  441. $wallet_deduct_score['desc'] = sprintf(
  442. '用户(%s),下单(%s)抵扣积分,数量:%s',
  443. $wallet_deduct_score['user_id'],
  444. $wallet_deduct_score['source_table_id'],
  445. abs($wallet_deduct_score['money'])
  446. );
  447. }
  448. }
  449. }
  450. // 存在扣除积分
  451. if ($wallet_deduct_score['money']) UserWalletService::handle(0, $wallet_deduct_score, false);
  452. $form_data = self::findFormDataByKey($form, 'data');
  453. $data = is_array($form_data)?$form_data:Json::decode($form_data,true);
  454. if(!empty($data['user_coupon_ids'])){
  455. $user_coupon_id = $data['user_coupon_ids'];
  456. $res = AddonsCouponUserRelate::updateAll(['is_use'=>1], ['id' => $user_coupon_id]);
  457. if($res === false) throw new Exception($order->getErrorMessage());
  458. }
  459. $order_trade_info[] = [
  460. 'order_id' => $order->id,
  461. 'order_type' => Order::DEFAULT,
  462. 'order_no' => $order->order_no,
  463. 'amount' => $order->goods_price + ($order->shipping_money - $order->reduce_shipping_money),
  464. 'title' => Order::getOrderTitle($order),
  465. 'notify_class' => 'addons\Happiness\common\logic\notify\Notify',
  466. ];
  467. }
  468. $form_data = self::findFormDataByKey($form, 'data');
  469. $data = is_array($form_data)?$form_data:Json::decode($form_data,true);
  470. if(isset($data['is_agree']) && !empty($data['is_agree'])){
  471. UserSignAgreement::setData([
  472. 'mall_id' => self::findFormDataByKey($form, 'mall_id'),
  473. 'user_id' => self::findFormDataByKey($form, 'user_id'),
  474. 'source' => UserSignAgreement::SOURCE_GOODS,
  475. 'source_id' => json_encode($tmp_goods_ids),
  476. ]);
  477. }
  478. if ($order->order_source === OrderSourceEnum::SOURCE_RESERVE) {
  479. // 预约类型的订单,单独保存信息
  480. $res = OrderReserve::create($order, $form);
  481. if ($res == false) throw new Exception(OrderReserve::getStaticError());
  482. }
  483. //
  484. $trans->commit();
  485. LockHelper::batchUlock($stock_locks);
  486. //生成支付流水
  487. $res = \Yii::$app->services->pay->createTrade($form['mall_id'],$form['user_id'],$order_trade_info);
  488. if($res==false) throw new Exception('生成支付流水失败');
  489. Order::updateAll(['out_trade_no'=>$res['trade_no']],['id'=>$order_ids]);
  490. // 触发订单添加事件,事务提交完成后触发
  491. $event = new OrderCreateEvent($form['mall_id']);
  492. $form['data']['share_user_id'] = $form['data']['share_user_id']??0;
  493. Yii::$app->services->events->dispatch($event, ['order_ids' => $order_ids,'share_user_id'=>$form['data']['share_user_id']], $event->listeners);
  494. //删除购物车
  495. if (self::findFormDataByKey($form, 'type') == 'cart' && empty($form->process_extra_data['is_not_del_cart'])) Cart::decreaseNumb(['user_id' => self::findFormDataByKey($form, 'user_id'), 'list' => $attr]);
  496. $res['order_ids'] = implode(',', $order_ids);
  497. $arr['transaction'] = $res;
  498. $arr['cart_list'] = $attr;//社安消防插件--该方法的删除购物车无法删除数据,返回购物车数据回插件方法,进行删除
  499. $trade=PaymentTrade::getOne([['out_trade_no'=>$res['trade_no']]]);
  500. $trade->limit_payment='';
  501. //限制支付方式
  502. foreach ($form['sku'] as $key => $oldGoods) {
  503. $ogood=$oldGoods['goods'];
  504. if($ogood['is_pay_limit'])
  505. {
  506. $trade->limit_payment=$ogood['pay_limit'];
  507. continue;
  508. }
  509. }
  510. $trade->save();
  511. // 有可能需要跳转到指定页面
  512. if (count($tmp_goods_ids) == 1 && MallAddons::isInstall($order->mall_id, AddonsEnum::ADDONS_NAME_PAY_SUCCESS_JUMP)) {
  513. // 判断是否有开启
  514. $jump_url_config = \Yii::$app->services->setting->addons->get($order->mall_id,
  515. AddonsEnum::ADDONS_NAME_PAY_SUCCESS_JUMP, 'basic');
  516. // 两个都开启的情况下
  517. if (intval($jump_url_config['is_enable_jump']) && intval($jump_url_config['is_enable'])) {
  518. $jump_url = (new JumpUrlService())->getJumpUrl($order->mall_id, $tmp_goods_ids[0], '');
  519. if (!empty($jump_url)) {
  520. $arr['pay_success_page'] = Json::encode(['route' => $jump_url, 'open_type' => 'page', 'params' => []]);
  521. }
  522. }
  523. }
  524. // 判断是否有安装抽奖插件
  525. if (MallAddons::isInstall($order->mall_id, AddonsEnum::ADDONS_NAME_SHOPPING_LOTTERY)) {
  526. $pay_success_page = LotteryHelper::getJumpUrl($order->mall_id, $res['trade_no']);
  527. if (!empty($pay_success_page)) {
  528. $arr['pay_success_page'] = $pay_success_page;
  529. $arr['is_jump'] = StatusEnum::ENABLED;
  530. }
  531. }
  532. if (empty($arr['pay_success_page'])) {
  533. $arr['pay_success_page'] = Yii::$app->services->setting->mall->get($form['mall_id'], 'order.pay_after_link');// 支付成功后跳转的地址
  534. }
  535. $payment_expire_time = Yii::$app->services->setting->mall->get($form['mall_id'], 'order.payment_expire_time');
  536. $arr['surplus_second'] = 30*60;//剩余秒数
  537. if($payment_expire_time){
  538. $arr['surplus_second'] = intval($payment_expire_time) * 60;//剩余秒数
  539. }
  540. return $arr;
  541. }catch(Exception $e){
  542. LockHelper::batchUlock($stock_locks);
  543. if(isset($trans)) $trans->rollback();
  544. self::$static_error = $e->getMessage();
  545. return false;
  546. }
  547. }
  548. private static function findFormDataByKey($form, $key)
  549. {
  550. if (is_array($form)) return $form[$key] ?? null;
  551. return $form->{$key} ?? null;
  552. }
  553. /**
  554. * 订单改价
  555. * @Author bing
  556. * @DateTime 2021-09-10 19:10:45
  557. * @copyright: Copyright (c) 2020 广东七件事集团
  558. * @param [type] $params
  559. * @param [type] $peyment_type
  560. * @return void
  561. */
  562. public static function changePrice(array $params){
  563. try{
  564. $model = self::findOne(['mall_id' => $params['mall_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED]]);
  565. if(empty($model)) throw new Exception('订单不存在或已删除');
  566. $model->shipping_money = $params['shipping_money'];
  567. $trans = Yii::$app->db->beginTransaction();
  568. // 修改订单详情调价
  569. $all_goods_price = OrderDetail::priceAdjustment($params['detail']);
  570. if($all_goods_price === false) throw new Exception('调整订单商品价格失败:'. $model->getErrorMessage());
  571. $model->goods_price = $all_goods_price;
  572. $res = $model->save();
  573. if($res === false) throw new Exception('修改订单运费失败:'. $model->getErrorMessage());
  574. // 订单金额修复后
  575. self::changeOrderMarketingScore($model->id);
  576. $trans->commit();
  577. return $model;
  578. }catch(Exception $e){
  579. if(isset($trans)) $trans->rollback();
  580. self::$static_error = $e->getMessage();
  581. return false;
  582. }
  583. }
  584. /**
  585. * 更新订单营销积分
  586. * @return void
  587. * @throws Exception
  588. */
  589. public static function changeOrderMarketingScore(int $order_id)
  590. {
  591. try {
  592. $orderInfo = self::find()
  593. ->select('id, order_no, user_id')
  594. ->where(['status' => StatusEnum::ENABLED, 'id' => $order_id])
  595. ->with(['detail' => function($query){
  596. $query->select('id, goods_id, order_id, original_goods_price, goods_price, adjust_money');
  597. }
  598. ])->asArray()->one();
  599. foreach ($orderInfo['detail'] as $item) {
  600. // 查询当前订单是否生成营销积分
  601. $marketing_score = OrderMarketing::find()
  602. ->where(['order_detail_id' => $item['id'], 'status' => StatusEnum::ENABLED])
  603. ->asArray()
  604. ->one();
  605. if (empty($marketing_score)) continue; // 没有生成营销积分
  606. $scoreNum = self::getGoodsGiveScore($item['goods_id'], $item);
  607. if (!$scoreNum) continue; // 没有设置积分赠送规则
  608. $res = OrderMarketing::updateAll(['give_score' => $scoreNum], ['id' => $marketing_score['id']]);
  609. if (!$res) {
  610. throw new Exception('修改订单营销积分失败');
  611. }
  612. }
  613. } catch (Exception $e) {
  614. Yii::$app->custom->logs("修改订单营销积分失败:" . $e->getMessage(), $order_id);
  615. }
  616. }
  617. public static function getGoodsGiveScore($goods_id, $orderDetail)
  618. {
  619. $goodsExtra = GoodsExtra::find()->where(['status' => StatusEnum::ENABLED, 'goods_id' => $goods_id])
  620. ->select('id, goods_id, score_give_setting')
  621. ->one();
  622. if (!$goodsExtra) return false;
  623. $give_setting = Json::decode($goodsExtra['score_give_setting'], true);
  624. if (empty($give_setting['enable_give_score'])) return false;
  625. if (!empty($give_setting['give_type']) && $give_setting['give_type'] == 2) {
  626. if (!empty($give_setting['calculation_value']) && $give_setting['calculation_value'] == 1) {
  627. // 订单支付金额
  628. $goods_price = $orderDetail['goods_price'] + $orderDetail['adjust_money']; // 订单金额等于原来总金额加上调整金额
  629. $money = bcmul($goods_price, $give_setting['give_num'] / 100, 2);
  630. } else {
  631. // 订单商品总价
  632. $money = bcmul($orderDetail['original_goods_price'], $give_setting['give_num'] / 100, 2);
  633. }
  634. } else { // 固定赠送值
  635. $money = $give_setting['give_num'] ?? 0;
  636. }
  637. return $money ?? 0;
  638. }
  639. /**
  640. * 管理员订单支付
  641. * @Author bing
  642. * @DateTime 2021-09-10 10:43:57
  643. * @copyright: Copyright (c) 2020 广东七件事集团
  644. * @param Order $params 参数
  645. * @param [type] $payment_type 支付方式
  646. * @param string 支付流水号
  647. * @return boolean|object
  648. */
  649. public static function pay($params, $peyment_type,$out_trade_no = '')
  650. {
  651. $stock_locks = [];
  652. try{
  653. // $model = self::findOne(['id' => $params['id'],'status'=>[StatusEnum::ENABLED]]);
  654. $model = self::findOne(['id' => $params['id']]);
  655. if(empty($model)) throw new Exception('订单不存在或已删除');
  656. // if ($model->order_status != OrderStatusEnum::NOT_PAY) throw new Exception('订单已经被处理,无法进行支付');
  657. if (in_array($model->order_status ,[OrderStatusEnum::PAY,OrderStatusEnum::SHIPMENTS,OrderStatusEnum::ACCOMPLISH])) throw new Exception('订单已经被处理,无法进行支付');
  658. if ($model->pay_status == StatusEnum::ENABLED) throw new Exception('订单已支付,请不要重复支付');
  659. $order_status = $model->order_status;
  660. $model->order_status = OrderStatusEnum::PAY;
  661. if ($model->shipping_type == ShippingTypeEnum::PICKUP) {
  662. $model->order_status = OrderStatusEnum::TAKE;
  663. }
  664. $model->payment_type = $peyment_type;
  665. $model->pay_status = StatusEnum::ENABLED;
  666. $model->pay_time = time();
  667. $model->out_trade_no = $out_trade_no ?? '';
  668. $trans = Yii::$app->db->beginTransaction();
  669. // if ($model->order_source === OrderSourceEnum::SOURCE_RESERVE) {
  670. // // 平台订单
  671. // $reserveOrder = OrderReserve::findOne(['order_id' => $model->id]);
  672. // if ($reserveOrder->reserve_type == StatusEnum::DISABLED) { // 家政才需要修改为发货状态
  673. // // 预约商品支付后,改成发货状态
  674. // $model->shipping_status = StatusEnum::ENABLED; // 全部发货状态改为已发货
  675. // // 如果是技师,那么就为已支付
  676. // $model->order_status = OrderStatusEnum::SHIPMENTS;
  677. // $model->consign_time = time();
  678. // }
  679. // OrderReserve::syncOrderStatus($model);
  680. // }
  681. $res = $model->save();
  682. if($res === false) throw new Exception('修改订单失败:'. $model->getErrorMessage());
  683. // 增加销量
  684. $order_detail = $model->detail;
  685. $sale_num_goods = [];
  686. //配送方式为快递配送,处理主商城库存
  687. if ($model->shipping_type == ShippingTypeEnum::LOGISTICS) {
  688. foreach($order_detail as $product){
  689. if($order_status==OrderStatusEnum::REPEAL) {
  690. if ($model->order_source !== OrderSourceEnum::SOURCE_RESERVE) {
  691. $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_GOODS_ATTR, $product['goods_attr_id']);
  692. $identification = uniqid();
  693. if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new Exception('当前访问人数过多');
  694. $stock_locks[$lock_key] = $identification;
  695. //操作商品库存-减
  696. GoodsAttr::handleStock($product['goods_attr_id'], $product['num'] * -1);
  697. $stock = GoodsAttr::find()->where(['goods_id' => $product['goods_id'], 'status' => StatusEnum::ENABLED])->sum('stock');
  698. $stock = $stock ?? 0;
  699. Goods::updateAll(['stock' => $stock], ['id' => $product['goods_id']]);
  700. }
  701. }
  702. if(isset($sale_num_goods[$product['goods_id']])){
  703. $sale_num_goods[$product['goods_id']] += $product['num'];
  704. }else{
  705. $sale_num_goods[$product['goods_id']] = $product['num'];
  706. }
  707. }
  708. foreach($sale_num_goods as $goods_id => $sale_num){
  709. $goods = Goods::findOne($goods_id);
  710. $goods->sales_num += $sale_num;
  711. $goods->save();
  712. }
  713. }
  714. $trans->commit();
  715. LockHelper::batchUlock($stock_locks);
  716. // 触发订单支付事件,事务提交完成后触发
  717. if(!empty($model['mch_id'])){
  718. $number = 0;
  719. $addons_arr = [AddonsEnum::ADDONS_NAME_AGENT,AddonsEnum::ADDONS_NAME_DISTRIBUTION,AddonsEnum::ADDONS_NAME_AREA];
  720. foreach ($addons_arr as $addons){
  721. if(MallAddons::isInstall($model['mall_id'],$addons)){
  722. $number++;
  723. }
  724. }
  725. //多商户事件触发
  726. \Yii::$app->services->taskCounter->set('mch:order_id:' . $model['id'])->incr($number);
  727. if (MallAddons::isInstall($model['mall_id'], AddonsEnum::ADDONS_NAME_MCH)){
  728. $data = [];
  729. $event = new \addons\Mch\common\events\order\OrderPaidEvent($model['mall_id']);
  730. $data['id'] = $model['id'];
  731. $data['operator_id'] = $params['operator_id'] ?? 0;
  732. $data['operator_name'] = $params['operator_name'] ?? '';
  733. \Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  734. }
  735. }else{
  736. $number = 0;
  737. $addons_arr = [AddonsEnum::ADDONS_NAME_AGENT,AddonsEnum::ADDONS_NAME_DISTRIBUTION,AddonsEnum::ADDONS_NAME_AREA,AddonsEnum::ADDONS_NAME_DOUBLE_COPY];
  738. foreach ($addons_arr as $addons){
  739. if(MallAddons::isInstall($model['mall_id'],$addons)){
  740. $number++;
  741. }
  742. }
  743. //云库存商品-先等经销、分销、区域分佣完
  744. \Yii::$app->services->taskCounter->set($model['id'])->incr($number);
  745. $event = new OrderPaidEvent($model['mall_id']);
  746. $order['id'] = $model['id'];
  747. $order['operator_id'] = $params['operator_id'] ?? 0;
  748. $order['operator_name'] = $params['operator_name'] ?? '';
  749. $order['is_admin'] = (int)!empty($params['is_admin']);
  750. Yii::$app->services->events->dispatch($event, $order, $event->listeners);
  751. }
  752. return $model;
  753. }catch(Exception $e){
  754. LockHelper::batchUlock($stock_locks);
  755. if(isset($trans)) $trans->rollback();
  756. self::$static_error = $e->getMessage();
  757. return false;
  758. }
  759. }
  760. /**
  761. * 取消订单
  762. * @Author bing
  763. * @DateTime 2021-09-14 15:43:18
  764. * @copyright: Copyright (c) 2020 广东七件事集团
  765. * @param [type] $params
  766. * @return order
  767. */
  768. public static function close($params,$force = false){
  769. $trans = Yii::$app->db->beginTransaction();
  770. $stock_locks = [];
  771. $close_lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_GOODS , $params['id']);
  772. try{
  773. // 加锁
  774. $close_identification = uniqid();
  775. $stock_locks[$close_lock_key] = $close_identification;
  776. if (!LockHelper::lock($close_lock_key, $close_identification, 30, 60)) throw new \Exception('正在关闭订单');
  777. $cond = ['mall_id' => $params['mall_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED]];
  778. isset($params['user_id']) && $cond['user_id'] = $params['user_id'];
  779. $model = self::findOne($cond);
  780. if(empty($model)) throw new Exception('订单不存在或已删除');
  781. if($model['order_source']=='Aiyunuo') {
  782. $extra_info = $model['extra_info'];
  783. if(!empty($extra_info)){
  784. $extra_info = json_decode($extra_info,true);
  785. if(!empty($extra_info['aiyunuo_rp_order_rp_id'])){
  786. throw new Exception('爱优诺处方订单不允许取消');
  787. }
  788. }
  789. }
  790. // 判断订单是否已经被关闭
  791. if ($model->order_status == OrderStatusEnum::REPEAL) throw new Exception('订单已经关闭');
  792. // 判断是否是未支付的订单
  793. if ($force == false && $model->order_status != OrderStatusEnum::NOT_PAY) throw new Exception('订单已经被处理');
  794. $model->close_time = time();
  795. $model->order_status = OrderStatusEnum::REPEAL;
  796. if (!$model->save()) throw new Exception($model->getErrorMessage());
  797. $goods_attr_arr = array_column($model->detail,'num','goods_attr_id');
  798. //操作规格库存-回退
  799. if ($model->order_source !== OrderSourceEnum::SOURCE_RESERVE) {
  800. // 非预约商品处理库存
  801. foreach ($goods_attr_arr as $goods_attr_id => $num) {
  802. $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_GOODS_ATTR, $goods_attr_id);
  803. $identification = uniqid();
  804. if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new Exception('当前访问人数过多');
  805. $stock_locks[$lock_key] = $identification;
  806. //操作商品库存-回退
  807. GoodsAttr::handleStock($goods_attr_id, $num);
  808. }
  809. }
  810. // 订单营销扣减返还
  811. $order_detail_id_arr = array_column($model->detail, 'id');
  812. if (empty($model['store_id'])) {
  813. $res = OrderMarketing::deductBack($model->id, $order_detail_id_arr, $order_detail_id_arr, $model->mall_id, $model->user_id, '交易关闭返还');
  814. if ($res == false) throw new Exception(OrderMarketing::getStaticError());
  815. }
  816. // liuzhantao,这里注释的原因是:订单支付用积分抵扣,那么取消订单时,就会返回两次积分,这里的代码返回一次积分,下面监听的代码也返回一次积分,所以把这里的注释了。
  817. // else {
  818. // if (MallAddons::isInstall($model->mall_id, AddonsEnum::ADDONS_NAME_STORE)) {
  819. // $store_order_detail_list = StoreOrderDetail::lists(['where' => [['main_order_detail_id' => $order_detail_id_arr]]]);
  820. // $store_order_detail_id_arr = array_column($store_order_detail_list, 'id');
  821. // $store_order = StoreOrder::findOne(['order_no' => $model['order_no']]);
  822. // $res = StoreOrderMarketing::deductBack($store_order, $store_order_detail_id_arr, $store_order_detail_id_arr, $model['mall_id'], $model['user_id'], '交易关闭返还');
  823. // if ($res == false) throw new Exception(StoreOrderMarketing::getStaticError());
  824. // }
  825. // }
  826. if ($model->order_source === OrderSourceEnum::SOURCE_RESERVE) {
  827. // 同步订单状态
  828. OrderReserve::syncOrderStatus($model);
  829. }
  830. $trans->commit();
  831. // 触发订单取消事件
  832. if (!empty($model['store_id'])) {
  833. if (MallAddons::isInstall($model->mall_id, AddonsEnum::ADDONS_NAME_STORE)) {
  834. $event = new \addons\Store\common\events\order\OrderCloseEvent($model->mall_id);
  835. $order_data['id'] = $model->id;
  836. $order_data['operator_id'] = $params['operator_id'] ?? 0;
  837. $order_data['operator_name'] = $params['operator_name'] ?? '系统';
  838. $order_data['is_store'] = 1;
  839. Yii::$app->services->events->dispatch($event, $order_data, $event->listeners);
  840. }
  841. } else {
  842. $event = new OrderCloseEvent($model->mall_id);
  843. $order_data['id'] = $model->id;
  844. $order_data['operator_id'] = $params['operator_id'] ?? 0;
  845. $order_data['operator_name'] = $params['operator_name'] ?? '系统';
  846. $order_data['is_admin'] = (int)!empty($params['is_admin']);
  847. Yii::$app->services->events->dispatch($event, $order_data, $event->listeners);
  848. }
  849. // 解锁
  850. LockHelper::batchUlock($stock_locks);
  851. return $model;
  852. } catch (Exception $e) {
  853. $trans->rollback();
  854. // 解锁
  855. LockHelper::batchUlock($stock_locks);
  856. self::$static_error = $e->getMessage();
  857. return false;
  858. }
  859. }
  860. /**
  861. * 订单备注
  862. * @Author bing
  863. * @DateTime 2021-09-14 15:43:18
  864. * @copyright: Copyright (c) 2020 广东七件事集团
  865. * @param [type] $params
  866. * @return void
  867. */
  868. public static function remark($params){
  869. try{
  870. $where = ['mall_id' => $params['mall_id'], 'id' => $params['id']];
  871. if(!empty($params['mch_id']))$where['mch_id'] = $params['mch_id'];
  872. $model = self::findOne($where);
  873. if(empty($model)) throw new Exception('订单不存在或已删除');
  874. $model->remark = $params['remark'] ?? $model->remark;
  875. $model->seller_remark = $params['seller_remark'] ?? $model->seller_remark;
  876. if (!$model->save()) throw new Exception($model->getErrorMessage());
  877. return $model;
  878. }catch(Exception $e){
  879. if(isset($trans)) $trans->rollback();
  880. self::$static_error = $e->getMessage();
  881. return false;
  882. }
  883. }
  884. /**
  885. * @desc:删除订单
  886. * @Author: hua
  887. * @Date: 2021/12/3
  888. * @Time: 19:05
  889. * @Copyright: copyright (c) 2021 广东七件事集团
  890. * @param $params
  891. * @return Order|false
  892. */
  893. public static function del($params){
  894. try{
  895. $where = ['mall_id' => $params['mall_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED, StatusEnum::DISABLED]];
  896. if(!empty($params['mch_id']))$where['mch_id'] = $params['mch_id'];
  897. $model = self::findOne($where);
  898. if(empty($model)) throw new Exception('订单不存在或已删除');
  899. if(!empty($model->pay_time))throw new Exception('只允许删除未支付订单');
  900. if($model->order_status!=OrderStatusEnum::REPEAL)throw new Exception('只允许删除关闭订单');
  901. $model->status = StatusEnum::DELETE;
  902. if (!$model->save()) throw new Exception($model->getErrorMessage());
  903. OrderDetail::updateAll(['status'=>StatusEnum::DELETE],['order_id'=>$params['id']]);
  904. $event = new OrderDelEvent($model->mall_id);
  905. $order_data['id'] = $params['id'];
  906. $order_data['order_no'] = $model->order_no;
  907. $order_data['operator_id'] = $params['operator_id'] ?? 0;
  908. $order_data['operator_name'] = $params['operator_name'] ?? '系统';
  909. $order_data['is_admin'] = $params['is_admin'] ?? 0;
  910. $order_data['is_store'] = $params['is_store'] ?? 0;
  911. $order_data['is_mch'] = $params['is_mch'] ?? 0;
  912. $order_data['is_aiyunuo'] = $params['is_aiyunuo'] ?? 0;
  913. Yii::$app->services->events->dispatch($event,$order_data,$event->listeners);
  914. return $model;
  915. }catch(Exception $e){
  916. if(isset($trans)) $trans->rollback();
  917. self::$static_error = $e->getMessage();
  918. return false;
  919. }
  920. }
  921. public static function delByh5($params){
  922. try{
  923. $where = ['mall_id' => $params['mall_id'],'user_id'=>$params['user_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED]];
  924. if(!empty($params['mch_id']))$where['mch_id'] = $params['mch_id'];
  925. $model = self::findOne($where);
  926. if(empty($model)) throw new Exception('订单不存在或已删除');
  927. if(!in_array($model->order_status,[OrderStatusEnum::REPEAL,OrderStatusEnum::ACCOMPLISH]))throw new Exception('只允许删除关闭订单或者已完成订单');
  928. $model->status = StatusEnum::DISABLED;
  929. if (!$model->save()) throw new Exception($model->getErrorMessage());
  930. OrderDetail::updateAll(['status'=>StatusEnum::DISABLED],['order_id'=>$params['id']]);
  931. // 用户删除订单
  932. OrderAction::create("用户删除订单", $model->id, $model->order_status, $params['user_id'], $model->user->nickname);
  933. return $model;
  934. }catch(Exception $e){
  935. if(isset($trans)) $trans->rollback();
  936. self::$static_error = $e->getMessage();
  937. return false;
  938. }
  939. }
  940. /**
  941. * 修改收货地址
  942. * @Author bing
  943. * @DateTime 2021-09-14 15:43:18
  944. * @copyright: Copyright (c) 2020 广东七件事集团
  945. * @param [type] $params
  946. * @return void
  947. */
  948. public static function changeAddress($params){
  949. try{
  950. $where = ['mall_id' => $params['mall_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED]];
  951. if(!empty($params['mch_id']))$where['mch_id'] = $params['mch_id'];
  952. $model = self::findOne($where);
  953. // 记录原地址
  954. $params['old_receiver_name'] = $params['receiver_name'];
  955. $params['old_mobile'] = $params['mobile'];
  956. $params['old_region_name'] = $params['region_name'];
  957. $params['old_address'] = $params['address'];
  958. if(empty($model)) throw new Exception('订单不存在或已删除');
  959. self::isAllowChangeAddress($params['mall_id'], $model->order_source);
  960. if(!$model->load($params,'') || !$model->save()) throw new \Exception($model->getErrorMessage());
  961. // 事件
  962. $event = new OrderChangeAddressEvent($params['mall_id']);
  963. Yii::$app->services->events->dispatch($event,$params,$event->listeners);
  964. return $model;
  965. }catch(Exception $e){
  966. self::$static_error = $e->getMessage();
  967. return false;
  968. }
  969. }
  970. /**
  971. * 只有主商城订单和聚水潭订单允许修改订单地址
  972. *
  973. * @param int $mallId
  974. * @param string $orderSource
  975. *
  976. * @throws Exception
  977. */
  978. public static function isAllowChangeAddress(int $mallId, string $orderSource)
  979. {
  980. $needCheckIsAllowModifyAddressAddons = [
  981. AddonsEnum::ADDONS_NAME_JSTAN_ERP,
  982. AddonsEnum::ADDONS_NAME_QI_JUHE,
  983. AddonsEnum::ADDONS_NAME_JUHE_SHOP,
  984. 'StarChain'
  985. ];
  986. if (!in_array($orderSource, $needCheckIsAllowModifyAddressAddons)) {
  987. return;
  988. }
  989. // 获取插件的配置
  990. $event = new \common\events\mall\GetSpecifyAdsCfgEvent($mallId);
  991. Yii::$app->services->events->dispatch($event, ['mall_id' => $mallId, 'addons_name' => $orderSource], $event->listeners);
  992. if (!empty($event->getConfig()['is_allow_modify_address'])) {
  993. return;
  994. }
  995. throw new \RuntimeException('当前订单不允许修改地址');
  996. }
  997. /**
  998. * 发货
  999. * @Author bing
  1000. * @DateTime 2021-09-16 17:35:05
  1001. * @copyright: Copyright (c) 2020 广东七件事集团
  1002. * @param [type] $params
  1003. * @return void
  1004. */
  1005. public static function delivery($params){
  1006. try{
  1007. $model = self::findOne(['mall_id' => $params['mall_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED]]);
  1008. if(empty($model)) throw new Exception('订单不存在或已删除');
  1009. if ($model->order_status == OrderStatusEnum::SHIPMENTS) throw new Exception('订单已经发货');
  1010. if ($model->order_status != OrderStatusEnum::PAY) throw new Exception('订单已经被处理');
  1011. $model->shipping_status = StatusEnum::ENABLED;// 全部发货状态改为已发货
  1012. $model->order_status = OrderStatusEnum::SHIPMENTS;
  1013. $model->consign_time = time();
  1014. if (!$model->save()) throw new Exception($model->getErrorMessage());
  1015. return $model;
  1016. }catch(Exception $e){
  1017. self::$static_error = $e->getMessage();
  1018. return false;
  1019. }
  1020. }
  1021. /**
  1022. * 收货
  1023. * @Author bing
  1024. * @DateTime 2021-09-16 17:35:05
  1025. * @copyright: Copyright (c) 2020 广东七件事集团
  1026. * @param [type] $params
  1027. * @return void
  1028. */
  1029. public static function takeDelivery($params){
  1030. try{
  1031. $cond = ['mall_id' => $params['mall_id'], 'id' => $params['id'],'status'=>[StatusEnum::ENABLED]];
  1032. isset($params['user_id']) && $cond['user_id'] = $params['user_id'];
  1033. isset($params['mch_id']) && $cond['mch_id'] = $params['mch_id'];
  1034. $model = self::findOne($cond);
  1035. if (empty($model)) throw new Exception('订单不存在或已删除');
  1036. $actionText = ($params['from'] ?? '') == OrderSourceEnum::SOURCE_RESERVE ? '核销' : '签收';
  1037. if ($model->order_status == OrderStatusEnum::SING) throw new Exception('订单已经' . $actionText);
  1038. if ($model->order_status != OrderStatusEnum::SHIPMENTS) throw new Exception('订单已经被处理');
  1039. $orderDetailRefund = OrderDetail::find()->alias('or')
  1040. ->join('inner join', OrderRefund::tableName() . 'as refund', 'refund.order_detail_id=or.id')
  1041. ->where(['or.order_id' => $params['id'], 'or.is_feedback' => OrderStatusEnum::FEEDBACKING,
  1042. 'or.status' => StatusEnum::ENABLED, 'refund.status' => StatusEnum::ENABLED,
  1043. ])
  1044. ->andWhere(['!=', 'refund.refund_status', RefundStatusEnum::FINISH])
  1045. ->select('or.id, refund.id as refund_id, or.is_feedback, refund.type')
  1046. ->orderBy('refund.type desc')
  1047. ->asArray()->all();
  1048. if (!empty($orderDetailRefund)) {
  1049. $refundTypes = array_column($orderDetailRefund, 'type');
  1050. if (in_array(RefundTypeEnum::EXCHANGE_GOODS, $refundTypes)) {
  1051. $refund_id = array_filter($orderDetailRefund, function ($item) {
  1052. return $item['type'] == RefundTypeEnum::EXCHANGE_GOODS;
  1053. });
  1054. self::$getRefundId = reset($refund_id)['refund_id']; // 获取第一个换货商品id
  1055. throw new Exception('该订单包含换货中商品,请先前往售后详情确认收货。');
  1056. } else if (in_array(RefundTypeEnum::MONEY_AND_PRODUCT, $refundTypes) && !in_array(RefundTypeEnum::MONEY, $refundTypes)) {
  1057. throw new Exception('该订单包含退货退款商品,确认收货后其售后流程将继续进行。');
  1058. } else if (in_array(RefundTypeEnum::MONEY, $refundTypes) && !in_array(RefundTypeEnum::MONEY_AND_PRODUCT, $refundTypes)) {
  1059. throw new Exception('该订单包含退款中商品,确认收货将关闭退款。');
  1060. } else if (in_array(RefundTypeEnum::MONEY_AND_PRODUCT, $refundTypes) && in_array(RefundTypeEnum::MONEY, $refundTypes)) {
  1061. throw new Exception('该订单包含退款中及退货退款中商品,确认收货将关闭退款;退货退款商品售后继续,不受影响。');
  1062. }
  1063. }
  1064. $model->order_status = OrderStatusEnum::SING;
  1065. $model->shipping_status = ShippingStatusEnum::RECEIVED;
  1066. $model->sign_time = time();
  1067. if (!$model->save()) throw new Exception($model->getErrorMessage());
  1068. OrderDetail::updateAll(['shipping_status' => ShippingStatusEnum::RECEIVED], ['order_id' => $model['id'],'is_feedback'=>0]);
  1069. if ($model->order_source === OrderSourceEnum::SOURCE_RESERVE) {
  1070. // 同步订单状态
  1071. OrderReserve::syncOrderStatus($model, $params['tech_id'] ?? null);
  1072. }
  1073. if (!empty($model['store_id'])) {
  1074. $is_install = MallAddons::isInstall($params['mall_id'], AddonsEnum::ADDONS_NAME_STORE);
  1075. if ($is_install) {
  1076. $store_order = StoreOrder::findOne(['order_no' => $model['order_no']]);
  1077. if ($store_order) {
  1078. $store_order->order_status = OrderStatusEnum::SING;
  1079. $store_order->sign_time = time();
  1080. if (!$store_order->save()) throw new Exception($store_order->getErrorMessage());
  1081. }
  1082. }
  1083. }
  1084. // 触发订单收货事件,事务提交完成后触发
  1085. $event = new OrderTakeDeliveryEvent($params['mall_id']);
  1086. $data['id'] = $model->id;
  1087. $data['operator_id'] = $params['operator_id'];
  1088. $data['operator_name'] = $params['operator_name'];
  1089. $data['is_admin'] = (int)!empty($params['is_admin']);
  1090. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1091. return $model;
  1092. }catch(Exception $e){
  1093. self::$static_error = $e->getMessage();
  1094. return false;
  1095. }
  1096. }
  1097. /**
  1098. * @notes:取消发货
  1099. * @param $params
  1100. * @return bool
  1101. * @author: lun
  1102. * @Time: 2022/10/27 10:21
  1103. */
  1104. public static function cancelShipment($params)
  1105. {
  1106. try {
  1107. $order_details = OrderDetail::find()->where(['id' => $params['order_detail_ids']])->all();
  1108. foreach ($order_details as $detail) {
  1109. if (!$detail->shipped_num) throw new Exception('订单处于非发货状态');
  1110. if (OrderDetail::getAfterSaleCountByOrderId($detail->order_id) > 0) throw new Exception('请先处理或关闭订单售后');
  1111. $detail->order_status = OrderStatusEnum::PAY;
  1112. $detail->shipping_status = StatusEnum::DISABLED;
  1113. if (!$detail->save()) throw new Exception($detail->getErrorMessage());
  1114. OrderDetail::updateAllCounters(['shipped_num' => -min($params['nums'][$detail->id] ?? $detail->shipped_num, $detail->shipped_num)], ['id' => $detail->id]);
  1115. }
  1116. // 统计订单详情数量
  1117. if ($order_details) {
  1118. $order = Order::findOne(['id' => $params['order_id']]);
  1119. $order->order_status = OrderStatusEnum::PAY; // 已发货改为待发货状态
  1120. $order->consign_time = 0; // 发货时间改为0
  1121. if (!$order->save()) throw new Exception($order->getErrorMessage());
  1122. }
  1123. return true;
  1124. } catch (Exception $e) {
  1125. self::$static_error = $e->getMessage();
  1126. return false;
  1127. }
  1128. }
  1129. /**
  1130. * 自动维护订单状态
  1131. * @Author bing
  1132. * @DateTime 2021-09-17 11:43:41
  1133. * @copyright: Copyright (c) 2020 广东七件事集团
  1134. * @param [type] $order_id
  1135. * @return void
  1136. */
  1137. public static function autoUpdateStatus($order)
  1138. {
  1139. $order_details = OrderDetail::getOrderDetails([['order_id' => $order->id]]);
  1140. // 正常订单详情数
  1141. $normal_count = count($order_details);
  1142. // 退款状态数
  1143. $refund_count = 0;
  1144. $not_refunding_count = 0;
  1145. $refunding_count = 0;
  1146. $feedback_completion = 0;
  1147. // 已发货状态数
  1148. $shipping_count = 0;
  1149. // 未发货状态数
  1150. $no_shipping_count = 0;
  1151. // 换货状态数
  1152. $exchange_count = 0;
  1153. // 订单完成需要关闭的订单详情数
  1154. $order_detail_close_ids = [];
  1155. foreach ($order_details as $order_detail) {
  1156. $shipping_status = $order_detail['shipping_status'];
  1157. $is_feedback = $order_detail['is_feedback'];
  1158. $shipping_status == StatusEnum::ENABLED && $shipping_count++;
  1159. $is_feedback == OrderStatusEnum::FEEDBACKED && $refund_count++;
  1160. $is_feedback == OrderStatusEnum::NOT_FEEDBACK && $not_refunding_count++;
  1161. $is_feedback == OrderStatusEnum::FEEDBACKING && $refunding_count++;
  1162. $is_feedback == OrderStatusEnum::FEEDBACKED && $feedback_completion++;
  1163. /****判断订单是否售后完成 --start-- ****/
  1164. if ($is_feedback == OrderStatusEnum::FEEDBACKED) {
  1165. // 订单售后完成(判断完成订单中是否存在换货数据)
  1166. $refund_exists = OrderRefund::find()
  1167. ->where(['mall_id' => $order_detail['mall_id'], 'status' => StatusEnum::ENABLED,
  1168. 'order_detail_id' => $order_detail['id'], 'type' => RefundTypeEnum::EXCHANGE_GOODS,
  1169. 'store_id' => 0, 'mch_id' => 0
  1170. ])->exists();
  1171. if ($refund_exists) {
  1172. $exchange_count++;
  1173. } else {
  1174. // 订单完成后订单状态为已关闭(仅为退款、退货退款)
  1175. $order_detail_close_ids[] = $order_detail['id'];
  1176. }
  1177. }
  1178. /****判断订单是否售后完成--end--****/
  1179. // 未发货的正常产品
  1180. if ($shipping_status == StatusEnum::DISABLED && in_array($is_feedback, OrderStatusEnum::getFeedbackMap())) {
  1181. $no_shipping_count++;
  1182. }
  1183. }
  1184. if (!empty($order_detail_close_ids)) {
  1185. // 关闭订单详情
  1186. OrderDetail::updateAll(['order_status' => OrderStatusEnum::REPEAL], ['id' => $order_detail_close_ids]);
  1187. }
  1188. // 全部已退款直接关闭
  1189. if ($normal_count === $refund_count) {
  1190. $order->close_time = time();
  1191. // 只有当退货订单中没有换货订单时,才对主订单进行关闭
  1192. if ($exchange_count == 0) {
  1193. $order->order_status = OrderStatusEnum::REPEAL;
  1194. }
  1195. if (!$order->save()) throw new Exception($order->getErrorMessage());
  1196. // return self::close(['mall_id'=>$order->mall_id,'id'=>$order->id], true);
  1197. }
  1198. //未售后(当售后完成中有拒绝时也更改主订单状态)
  1199. if (!empty($not_refunding_count)) {
  1200. $order->is_feedback = OrderStatusEnum::NOT_FEEDBACK;
  1201. $order->save();
  1202. }
  1203. // 全部售后中
  1204. if ($normal_count === $refunding_count) {
  1205. $order->is_feedback = OrderStatusEnum::FEEDBACKING;
  1206. $order->save();
  1207. }
  1208. // 全部售后完成
  1209. if ($normal_count === $feedback_completion) {
  1210. $order->is_feedback = OrderStatusEnum::FEEDBACKED;
  1211. $order->save();
  1212. }
  1213. if($order->order_source === OrderSourceEnum::SOURCE_RESERVE){
  1214. // 预约订单处理
  1215. try{
  1216. OrderReserve::syncOrderStatus($order);
  1217. }catch(Exception $e){
  1218. throw $e;
  1219. }
  1220. }
  1221. // 全部已发货
  1222. if ($normal_count === $shipping_count) {
  1223. return self::delivery(['mall_id' => $order->mall_id, 'id' => $order->id]);
  1224. }
  1225. // 校验发货状态如果其他货物已发就改变订单状态
  1226. $refund_shipping_count = $refund_count + $shipping_count;
  1227. if ($normal_count == $refund_shipping_count && $order->order_status == OrderStatusEnum::PAY && $no_shipping_count == 0) {
  1228. return self::delivery(['mall_id' => $order->mall_id, 'id' => $order->id]);
  1229. }
  1230. }
  1231. public function export(array $data)
  1232. {
  1233. foreach ($data as &$val) {
  1234. $val['created_at'] = date('Y-m-d H:i:s', $val['created_at']);
  1235. }
  1236. return $data;
  1237. }
  1238. /**
  1239. * 导出字段数组
  1240. * @Author: hua
  1241. * @DateTime: 2021/10/11 18:06
  1242. * @Copyright: copyright (c) 2021 广东七件事集团
  1243. * @return \string[][]
  1244. */
  1245. public static function fieldsLists($field = null)
  1246. {
  1247. $fields = [
  1248. 'o.order_id' => '订单ID',
  1249. 'o.user_id' => '用户ID',
  1250. 'o.order_no' => '订单编号',
  1251. 'o.out_trade_no' => '外部交易号',
  1252. 'o.mobile' => '收货人的手机号码',
  1253. 'o.receiver_name' => '收货人姓名',
  1254. 'o.region_name' => '地区名称(省市区[乡/镇]',
  1255. 'o.address' => '详细地址',
  1256. 'd.goods_name' => '商品名', //detail
  1257. 'd.goods_attr_name' => '规格', //detail
  1258. 'd.num' => '购买数量', //detail
  1259. 'd.cost_price' => '商品成本价', //detail
  1260. 'd.original_goods_price' => '商品原本总价', //detail
  1261. 'd.goods_price' => '商品优惠后总价', //detail
  1262. 'o.shipping_money' => '订单运费',
  1263. 'o.created_at' => '下单时间',
  1264. 'o.payment_type' => '支付方式', //-
  1265. 'o.order_status' => '订单状态', //-
  1266. 'o.pay_status' => '订单付款状态', //-
  1267. 'o.pay_time' => '订单付款时间',
  1268. 'd.shipping_status' => '订单配送状态', //- detail
  1269. 'o.consign_time' => '卖家发货时间', //
  1270. 'o.sign_time' => '买家签收时间',
  1271. 'd.remark' => '用户订单备注', //detail
  1272. 'o.seller_remark' => '商家订单备注',
  1273. 'o.pay_money' => '订单实付金额'
  1274. ];
  1275. if ($field === null) return $fields;
  1276. $temp = [];
  1277. foreach ($field as $val) {
  1278. if (isset($fields[$val])) $temp[$val] = $fields[$val];
  1279. }
  1280. return $temp;
  1281. }
  1282. /**
  1283. * 获取订单标题
  1284. * @param Order $order
  1285. * @return string
  1286. */
  1287. public static function getOrderTitle($order)
  1288. {
  1289. $details = $order->getDetail()->all();
  1290. if (empty($details) || !is_array($details) || count($details) < 1) {
  1291. return '';
  1292. }
  1293. $titles = [];
  1294. foreach ($details as $detail) {
  1295. $titles[] = $detail->goods_name;
  1296. }
  1297. $title = implode(';', $titles);
  1298. return mb_strlen($title) > 32 ? mb_substr($title, 0, 32) : $title;
  1299. }
  1300. /**
  1301. * @desc:去支付
  1302. * @Author: hua
  1303. * @Date: 2021/10/19
  1304. * @Time: 14:13
  1305. * @Copyright: copyright (c) 2021 广东七件事集团
  1306. * @param $params
  1307. * @return array|false|int
  1308. */
  1309. public static function toPay($params)
  1310. {
  1311. try {
  1312. $id = json_decode($params['id'], true);
  1313. $orderUserId = $params['order_user_id'] ?? $params['user_id'];
  1314. $where = ['id' => $id, 'user_id' => $orderUserId, 'mall_id' => $params['mall_id'], 'pay_status' => 0];
  1315. if (!empty($params['mch_id'])) $where['mch_id'] = $params['mch_id'];
  1316. $list = Order::findAll($where);
  1317. $orders = [];
  1318. $payment_expire_time = Yii::$app->services->setting->mall->get($params['mall_id'], 'order.payment_expire_time');
  1319. if (empty($payment_expire_time)) $payment_expire_time = 30;
  1320. $order_nos = [];
  1321. $goods_price = 0; // 最终支付金额
  1322. $store_order_nos = [];
  1323. foreach ($list as $order) {
  1324. // 获取插件内容
  1325. $event = new OrderToPayEvent($order['mall_id'], $order);
  1326. Yii::$app->services->events->dispatch($event);
  1327. $orders[] = [
  1328. 'order_id' => $order->id,
  1329. 'order_no' => $order->order_no,
  1330. 'amount' => $order->goods_price + ($order->shipping_money - $order->reduce_shipping_money),
  1331. 'title' => self::getOrderTitle($order),
  1332. 'notify_class' => empty($order['store_id']) ? 'common\logic\notify\Notify' : 'addons\Store\common\logic\notify\Notify',
  1333. 'order_type' => Order::DEFAULT,
  1334. ];
  1335. //如果是o2o门店订单,记录订单号
  1336. if (!empty($order['store_id'])) {
  1337. $store_order_nos[] = $order->order_no;
  1338. }
  1339. $order_time = $order['created_at'] + $payment_expire_time * 60;
  1340. $order_ids[] = $order->id;
  1341. $order_nos[] = $order->order_no;
  1342. $goods_price += $order->goods_price + ($order->shipping_money - $order->reduce_shipping_money);
  1343. }
  1344. if(empty($list)) throw new Exception('查无订单');
  1345. // 判断是否已有组合待支付订单
  1346. $group_trade_ids = PaymentTradeOrder::find()->where(['order_no'=>$order_nos])->select('trade_id')->column();
  1347. if(!empty($group_trade_ids)) {
  1348. // 组合支付查询
  1349. /**
  1350. * @var PaymentTrade|null
  1351. */
  1352. $mixed_trade = PaymentTrade::getMixedTradeByIds($group_trade_ids);
  1353. !empty($mixed_trade) && $res = [
  1354. 'trade_id' => $mixed_trade->id,
  1355. 'trade_no' => $mixed_trade->out_trade_no,
  1356. 'pay_fee' => $mixed_trade->getOnlinePayFee(),
  1357. 'is_pay' => $mixed_trade->is_pay,
  1358. 'pay_type' => PayTypeEnum::MIXED,
  1359. ];
  1360. // 选择重新支付
  1361. if (isset($params['re_pay']) && $params['re_pay']) {
  1362. $mixed_trade->rePay(reset($list));
  1363. $res = null;
  1364. }
  1365. }
  1366. if (empty($res)) {
  1367. //查询上一个订单是否有限制支付方式
  1368. $orderNo=$list[0]->order_no;
  1369. $tradeOrder=PaymentTradeOrder::find()->where(['order_no'=>$orderNo])->orderBy('id DESC')->one();
  1370. $trade=PaymentTrade::find()->where(['id'=>$tradeOrder->trade_id])->one();
  1371. $res = \Yii::$app->services->pay->createTrade($params['mall_id'], $params['user_id'], $orders);
  1372. if ($res == false) throw new Exception('生成支付流水失败');
  1373. Order::updateAll(['out_trade_no'=>$res['trade_no']],['id'=>$order_ids]);
  1374. //如果门店订单号不为空,修改门店订单的外部单号
  1375. if (!empty($store_order_nos)) {
  1376. StoreOrder::updateAll(['out_trade_no'=>$res['trade_no']],['order_no'=>$store_order_nos]);
  1377. }
  1378. //限制支付方式
  1379. if(!empty($trade) && !empty($trade->limit_payment)){
  1380. $newTrade=PaymentTrade::findOne($res['trade_id']);
  1381. $newTrade->limit_payment = $trade->limit_payment;
  1382. $newTrade->save();
  1383. }
  1384. }
  1385. $res['surplus_second'] = 30*60;//剩余秒数
  1386. $res['main_order_id'] = reset($id);
  1387. $res['goods_price'] = $goods_price;//剩余秒数
  1388. if(!empty($order_time)) $res['surplus_second'] = ($order_time - time())>0?$order_time - time():0;
  1389. return $res;
  1390. }catch (Exception $e){
  1391. self::$static_error = $e->getMessage();
  1392. return false;
  1393. }
  1394. }
  1395. /**
  1396. * @desc:提醒发货
  1397. * @Author: hua
  1398. * @Date: 2021/10/20
  1399. * @Time: 9:06
  1400. * @Copyright: copyright (c) 2021 广东七件事集团
  1401. * @param $params
  1402. * @return array|false|int
  1403. */
  1404. public static function remindSend($params){
  1405. try {
  1406. $where = ['id'=>$params['order_id'],'user_id'=>$params['user_id'],'mall_id'=>$params['mall_id']];
  1407. if(!empty($params['mch_id'])) $where['mch_id'] = $params['mch_id'];
  1408. $order = self::findOne($where);
  1409. if(empty($order)) throw new Exception('查无订单');
  1410. if($order['pay_status']!=1) throw new Exception('该订单未支付');
  1411. if($order['order_status']!=OrderStatusEnum::PAY) throw new Exception('该订单已发货');
  1412. $key = RedisKeyEnum::suffix(RedisKeyEnum::REMIND_SEND,$params['order_id']);
  1413. $res = \Yii::$app->redis->get($key);
  1414. if($res)throw new Exception('您已提醒过发货,请24小时后再来');
  1415. \Yii::$app->redis->set($key,1,'NX','EX',24*3600);
  1416. //todo 调用发送短信接口
  1417. OrderAction::create('发货提醒',$order['id'], $order['order_status'], $params['user_id'], $params['user']['nickname']??'');
  1418. // 提醒发货事件
  1419. $event = new OrderReminderShipmentEvent($params['mall_id']);
  1420. $data['order_id'] = $params['order_id'];
  1421. $data['operator_id'] = $params['user_id'];
  1422. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1423. return true;
  1424. }catch (Exception $e){
  1425. self::$static_error = $e->getMessage();
  1426. return false;
  1427. }
  1428. }
  1429. /**
  1430. * @desc:提交订单评价
  1431. * @Author: hua
  1432. * @Date: 2021/10/19
  1433. * @Time: 18:28
  1434. * @Copyright: copyright (c) 2021 广东七件事集团
  1435. * @param $params
  1436. * @return bool
  1437. */
  1438. public static function postComments($params){
  1439. $t = Yii::$app->db->beginTransaction();
  1440. try{
  1441. $order = Order::findOne($params['order_id']);
  1442. if (empty($order)) throw new Exception('订单不存在');
  1443. if ($order->order_status == OrderStatusEnum::ACCOMPLISH) { // 如果订单已被后台管理员设置为完成。则用户不能再评论
  1444. throw new Exception('订单已完成,不能再评价');
  1445. }
  1446. $order_comments = OrderComments::findOne(['order_id' => $params['order_id']]);
  1447. // if (!empty($order_comments)) throw new Exception('订单已评价,无需再次评价');
  1448. $goods_ids = array_column($params['comment_data'], 'goods_id');
  1449. if(!empty($order['store_id'])){
  1450. $class = \addons\Store\common\models\StoreGoods::class;
  1451. }else{
  1452. $class = Goods::class;
  1453. }
  1454. $goods_list = $class::lists([
  1455. 'where'=>[
  1456. ['id'=>$goods_ids]
  1457. ],
  1458. 'index'=>'id',
  1459. 'select'=>'id,goods_type'
  1460. ]);
  1461. foreach ($params['comment_data'] as $item) {
  1462. $item['mch_id'] = $order->mch_id;
  1463. $item['store_id'] = $order->store_id;
  1464. $item['mall_id'] = $order->mall_id;
  1465. $item['user_id'] = $order->user_id;
  1466. $item['order_id'] = $params['order_id'];
  1467. $item['goods_type'] = $goods_list[$item['goods_id']]['goods_type']??1;
  1468. $res = OrderComments::setData($item);
  1469. if ($res === false) throw new Exception(OrderComments::getStaticError());
  1470. //注释下面的代码,原因是:不是首评,也能记录数据
  1471. // $is_first_comment = OrderComments::find()->where(['mall_id' => $item['mall_id'], 'store_id' => $item['store_id'], 'mch_id' => $item['mch_id'], 'user_id' => $item['user_id'], 'goods_id' => $item['goods_id']])->count();
  1472. // if ($is_first_comment == 1) { //如果为首评,记录数据
  1473. $order_comments_extra_data = OrderCommentsExtra::find()->where(['mall_id' => $item['mall_id'], 'store_id' => $item['store_id'], 'mch_id' => $item['mch_id'], 'goods_id' => $item['goods_id']])->asArray()->one();
  1474. if (!empty($order_comments_extra_data)) {
  1475. // $order_comments_extra_data['num'] += 1;
  1476. OrderCommentsExtra::updateAllCounters(['num' => 1], ['mall_id' => $item['mall_id'], 'store_id' => $item['store_id'], 'mch_id' => $item['mch_id'], 'goods_id' => $item['goods_id']]);
  1477. } else {
  1478. $order_comments_extra_data = [
  1479. 'mall_id' => $item['mall_id'],
  1480. 'store_id' => $item['store_id'],
  1481. 'mch_id' => $item['mch_id'],
  1482. 'goods_id' => $item['goods_id'],
  1483. 'num' => 1,
  1484. ];
  1485. OrderCommentsExtra::setData($order_comments_extra_data);
  1486. }
  1487. // }
  1488. if (in_array($order->order_source, [OrderSourceEnum::SOURCE_RESERVE, OrderSourceEnum::SOURCE_STORE_RESERVE])) {
  1489. if (empty($item['reserve']) && !is_array($item['reserve'])) throw new Exception('对技师/师傅的评价不能为空');
  1490. $res = OrderReserveComments::setData([
  1491. 'store_id' => $order->store_id,
  1492. 'mch_id' => $order->mch_id,
  1493. 'id' => $res->id,
  1494. 'aging_score' => $item['reserve']['aging_score'],
  1495. 'attitude_score'=> $item['reserve']['attitude_score'],
  1496. 'major_score' => $item['reserve']['major_score'],
  1497. 'staff_score' => !empty($item['reserve']['staff_score']) ? $item['reserve']['staff_score'] : 0,
  1498. 'environment_score' => !empty($item['reserve']['environment_score']) ? $item['reserve']['environment_score'] : 0,
  1499. 'service_score' => !empty($item['reserve']['service_score']) ? $item['reserve']['service_score'] : 0,
  1500. 'tags' => $item['reserve']['tags'],
  1501. 'goods_id' => $item['goods_id'],
  1502. 'order_id' => $order->id,
  1503. 'order_detail_id' => $item['order_detail_id'],
  1504. 'user_id' => $order->user_id,
  1505. 'score' => $item['score'],
  1506. 'show_tech' => isset($item['show_tech']) ? $item['show_tech'] : 0, // 确保有默认值
  1507. ]);
  1508. if ($res === false) throw new Exception(OrderComments::getStaticError());
  1509. }
  1510. // 记录评分
  1511. $scores = OrderComments::getOne([
  1512. ['goods_id' => $item['goods_id']],
  1513. ['status' => StatusEnum::ENABLED],
  1514. ], true, [],
  1515. '',
  1516. "SUM(score) as score, COUNT(*) AS total"
  1517. );
  1518. if (!empty($scores['score'])) {
  1519. $scores['score'] = $item['score'];
  1520. } else {
  1521. $scores['score'] += $item['score'];
  1522. }
  1523. Goods::updateAll(['comment_score' => bcdiv($scores['score'], $scores['total'] + 1, 2)], ['id' => $item['goods_id']]);
  1524. }
  1525. $order->order_status = OrderStatusEnum::ACCOMPLISH;
  1526. $order->finish_time = time();
  1527. $order->is_comment = 1;
  1528. $order->save();
  1529. if(!empty($order['store_id'])){
  1530. $is_install = MallAddons::isInstall($order['mall_id'], AddonsEnum::ADDONS_NAME_STORE);
  1531. if($is_install){
  1532. $store_order = StoreOrder::findOne(['order_no'=>$order['order_no']]);
  1533. if($store_order){
  1534. $store_order->order_status = OrderStatusEnum::ACCOMPLISH;
  1535. $store_order->finish_time = time();
  1536. $store_order->is_comment = 1;
  1537. if (!$store_order->save()) throw new Exception($store_order->getErrorMessage());
  1538. }
  1539. }
  1540. }
  1541. $t->commit();
  1542. // 订单完成触发事件
  1543. $user = User::getOne([['id' => $order->user_id]], true, [], false, 'nickname');
  1544. if(empty($order['mch_id'])&&empty($order['store_id'])){
  1545. $user = User::getOne([['id' => $order->user_id]], true, [], false, 'nickname');
  1546. $event = new OrderFinishEvent($order->mall_id);
  1547. $data['id'] = $order->id;
  1548. $data['order_no'] = $order->order_no;
  1549. $data['operator_id'] = $order->user_id;
  1550. $data['operator_name'] = $user['nickname'];
  1551. $data['is_comment'] = 1;
  1552. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1553. }else {
  1554. if (!empty($order['mch_id'])) {
  1555. if (MallAddons::isInstall($order['mall_id'], AddonsEnum::ADDONS_NAME_MCH)) {
  1556. $user = User::getOne([['id' => $order->user_id]], true, [], false, 'nickname');
  1557. $event = new \addons\Mch\common\events\order\OrderFinishEvent($order->mall_id);
  1558. $data['id'] = $order->id;
  1559. $data['order_no'] = $order->order_no;
  1560. $data['operator_id'] = $order->user_id;
  1561. $data['operator_name'] = $user['nickname'];
  1562. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1563. }
  1564. } elseif ($order['store_id']) {
  1565. if (MallAddons::isInstall($order['mall_id'], AddonsEnum::ADDONS_NAME_STORE)) {
  1566. $event = new \addons\Store\common\events\order\OrderFinishEvent($order->mall_id);
  1567. $data['id'] = $order->id;
  1568. $data['order_no'] = $order->order_no;
  1569. $data['operator_id'] = $order->user_id;
  1570. $data['operator_name'] = $user['nickname'];
  1571. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1572. }
  1573. }
  1574. }
  1575. return true;
  1576. }catch(Exception $e){
  1577. $t->rollBack();
  1578. self::$static_error = $e->getMessage();
  1579. return false;
  1580. }
  1581. }
  1582. /**
  1583. * @name:
  1584. * @msg: 处理订单完成(过售后)
  1585. * @param {array} $params
  1586. * @return {*}
  1587. */
  1588. public static function complete(array $params)
  1589. {
  1590. try {
  1591. $cond = ['mall_id' => $params['mall_id'], 'id' => $params['id'], 'status' => [StatusEnum::ENABLED]];
  1592. isset($params['user_id']) && $cond['user_id'] = $params['user_id'];
  1593. if(!empty($params['mch_id'])) $cond['mch_id'] = $params['mch_id'];
  1594. $model = self::findOne($cond);
  1595. if (empty($model)) throw new Exception('订单不存在或已删除');
  1596. if ($model->order_status == OrderStatusEnum::ACCOMPLISH) throw new Exception('订单已经完成,无需重复处理');
  1597. if ($model->order_status != OrderStatusEnum::SING && $model->order_status != OrderStatusEnum::TAKE_FINISH) throw new Exception('订单已经被处理');
  1598. if (OrderDetail::getAfterSaleCountByOrderId($params['id']) > 0) throw new Exception('请先处理或关闭订单售后');
  1599. $model->order_status = OrderStatusEnum::ACCOMPLISH;
  1600. $model->finish_time = time();
  1601. if (!$model->save()) throw new Exception($model->getErrorMessage());
  1602. if (in_array($model->order_source, [OrderSourceEnum::SOURCE_RESERVE, OrderSourceEnum::SOURCE_STORE_RESERVE])) {
  1603. // 同步订单状态
  1604. OrderReserve::syncOrderStatus($model);
  1605. }
  1606. if (!empty($model['store_id'])) {
  1607. $is_install = MallAddons::isInstall($model['mall_id'], AddonsEnum::ADDONS_NAME_STORE);
  1608. if ($is_install) {
  1609. $store_order = StoreOrder::findOne(['order_no' => $model['order_no']]);
  1610. if ($store_order) {
  1611. $store_order->order_status = OrderStatusEnum::ACCOMPLISH;
  1612. $store_order->finish_time = time();
  1613. if (!$store_order->save()) throw new Exception($store_order->getErrorMessage());
  1614. }
  1615. }
  1616. }
  1617. if (empty($model['mch_id']) && empty($model['store_id'])) {
  1618. $user = User::getOne([['id' => $model->user_id]], true, [], false, 'nickname');
  1619. $event = new OrderFinishEvent($model->mall_id);
  1620. $data['id'] = $model->id;
  1621. $data['operator_id'] = !empty($params['operator_id']) ? $params['operator_id'] : $model->user_id;
  1622. $data['operator_name'] = !empty($params['operator_name']) ? $params['operator_name'] : $user['nickname'];
  1623. $data['is_admin'] = (int)!empty($params['is_admin']);
  1624. $data['is_system_auto'] = (int)!empty($params['is_system_auto']);
  1625. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1626. } else {
  1627. if (!empty($model['mch_id'])) {
  1628. if (MallAddons::isInstall($model['mall_id'], AddonsEnum::ADDONS_NAME_MCH)) {
  1629. $user = User::getOne([['id' => $model->user_id]], true, [], false, 'nickname');
  1630. $event = new \addons\Mch\common\events\order\OrderFinishEvent($model->mall_id);
  1631. $data['id'] = $model->id;
  1632. $data['operator_id'] = $model->user_id;
  1633. $data['operator_name'] = $user['nickname'];
  1634. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1635. }
  1636. } elseif ($model['store_id']) {
  1637. if (MallAddons::isInstall($model['mall_id'], AddonsEnum::ADDONS_NAME_STORE)) {
  1638. $user = User::getOne([['id' => $model->user_id]], true, [], false, 'nickname');
  1639. $event = new \addons\Store\common\events\order\OrderFinishEvent($model->mall_id);
  1640. $data['id'] = $model->id;
  1641. $data['order_no'] = $model->order_no;
  1642. $data['operator_id'] = $model->user_id;
  1643. $data['operator_name'] = $user['nickname'];
  1644. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  1645. }
  1646. }
  1647. }
  1648. return $model;
  1649. } catch (Exception $e) {
  1650. self::$static_error = $e->getMessage();
  1651. return false;
  1652. }
  1653. }
  1654. public static function exportHandle(array $data)
  1655. {
  1656. set_time_limit(3600); // 设置一个小时
  1657. ini_set('memory_limit', '1024M'); //设置内存
  1658. date_default_timezone_set('Asia/Shanghai');
  1659. $download_id = $data['download_id'] ?? 0;
  1660. $download = Download::findOne(['id' => $download_id]);
  1661. if ($download) {
  1662. // 因为当数据过大时会创建多个文件所以开启事务
  1663. $transaction = \Yii::$app->db->beginTransaction();
  1664. try {
  1665. $params = json_decode($download->params, true);
  1666. $isChanjetExport = !empty($params['is_chanjet_addons']);
  1667. $filename = $download->name;
  1668. $type = $download->type;
  1669. $order_detail_model = OrderDetail::find()->alias('od');
  1670. $order_detail_model->leftJoin(self::tableName() . 'as o', 'o.id=od.order_id');
  1671. $order_detail_model->where(['od.mall_id' => $params['mall_id'], 'o.status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]);
  1672. if (isset($params['store_id']) && $params['store_id'] !==''){
  1673. $order_detail_model->andWhere(['=', 'od.store_id', $params['store_id']]);
  1674. }else{
  1675. $order_detail_model->andWhere(['=', 'od.store_id', 0]);
  1676. }
  1677. $is_show_mch_name = 0;
  1678. if (isset($params['mch_id'])) {
  1679. if ($params['mch_id'] == -1) {
  1680. $is_show_mch_name = 1;
  1681. $order_detail_model->andWhere(['<>', 'od.mch_id', 0]);
  1682. } else {
  1683. $order_detail_model->andWhere(['=', 'od.mch_id', $params['mch_id']]);
  1684. }
  1685. }else{
  1686. $order_detail_model->andWhere(['=', 'od.mch_id', 0]);
  1687. }
  1688. $order_detail_model->andWhere(['>=', 'od.status', StatusEnum::DISABLED]);
  1689. if (!empty($params['ids'])) {
  1690. $order_detail_model->andWhere(['od.order_id' => $params['ids']]);
  1691. }
  1692. if (!empty($params['start_date'])) {
  1693. $order_detail_model->andWhere(['>=','od.created_at',strtotime($params['start_date'])]);
  1694. }
  1695. if (!empty($params['end_date'])) {
  1696. $order_detail_model->andWhere(['<=','od.created_at',strtotime($params['start_date'])]);
  1697. }
  1698. if(!empty($params['keyword'])){
  1699. $order_detail_model->andWhere(['like','od.goods_name',$params['keyword']]);
  1700. }
  1701. if(!empty($params['user_id'])){
  1702. if (!empty($params['child_orders'])) {
  1703. $u_ids = UserPartitionRelationship::getChildIdArr($params['user_id']);
  1704. $u_ids[] = $params['user_id'];
  1705. $order_detail_model->andWhere(['in','od.user_id',$u_ids]);
  1706. } else {
  1707. $order_detail_model->andWhere(['=','od.user_id',$params['user_id']]);
  1708. }
  1709. }
  1710. if (!empty($params['order_no'])) {
  1711. $order = self::findOne(['order_no' => $params['order_no']]);
  1712. $order_detail_model->andWhere(['=', 'od.order_id', $order->id]);
  1713. }
  1714. if (!empty($params['mobile'])) {
  1715. $user = User::find()->where(['like', 'mobile', $params['mobile'] . '%', false])->all();
  1716. $order_detail_model->andWhere(['in', 'od.user_id', array_column($user, 'id')]);
  1717. }
  1718. if (!empty($params['start'])) {
  1719. $order_detail_model->andWhere(['>=', 'od.created_at', strtotime($params['start'])]);
  1720. }
  1721. if (!empty($params['end'])) {
  1722. $order_detail_model->andWhere(['<=', 'od.created_at', strtotime($params['end'])]);
  1723. }
  1724. if (isset($params['order_status']) && $params['order_status'] !== '' && $params['order_status'] != 999) {
  1725. $order_detail_model->andWhere(['=', 'od.order_status', $params['order_status']]);
  1726. }
  1727. if (!empty($params['type']) && !empty($params['type_value'])) {
  1728. switch ($params['type']) {
  1729. case 'mobile':
  1730. $uids = User::find()->select('id')
  1731. ->where(['mall_id' => $params['mall_id']])
  1732. ->andWhere(['like', 'mobile', $params['type_value'] . '%', false])->column();
  1733. !empty($uids) && $order_detail_model->andWhere(['od.user_id' => $uids]);
  1734. break;
  1735. case 'username':
  1736. $uids = User::find()->select('id')
  1737. ->where(['mall_id' => $params['mall_id']])
  1738. ->andWhere(['username' => $params['type_value']])->column();
  1739. !empty($uids) && $order_detail_model->andWhere(['od.user_id' => $uids]);
  1740. break;
  1741. case 'user_id':
  1742. $order_detail_model->andWhere(['od.user_id' => $params['type_value']]);
  1743. break;
  1744. case 'order_id':
  1745. $order_detail_model->andWhere(['od.order_id' => $params['type_value']]);
  1746. break;
  1747. case 'goods_name':
  1748. $order_detail_model->andWhere(['like', 'od.goods_name', '%' . $params['type_value'] . '%', false]);
  1749. break;
  1750. default:
  1751. }
  1752. }
  1753. if (!empty($params['type'] == 'user_id') && !empty($params['type_value'])) {
  1754. $order_detail_model->andWhere(['=', 'od.user_id', $params['type_value']]);
  1755. }
  1756. if (!empty($params['payment_type'])) {
  1757. $order_detail_model
  1758. ->andWhere(['=', 'o.payment_type', $params['payment_type']]);
  1759. }
  1760. if (!empty($params['shipping_type'])) {
  1761. $order_detail_model->andWhere(['=', 'o.shipping_type', $params['shipping_type']]);
  1762. }
  1763. if(!empty($params['marketing_type'])){
  1764. if($params['marketing_type'] != 'order_user_handle_finish'){
  1765. $order_detail_model->andWhere(['=', 'o.marketing_type', $params['marketing_type']]);
  1766. }else{
  1767. $order_user_handle = OrderUserHandle::lists(['where' => [['mall_id' => $params['mall_id']], ['status' => StatusEnum::ENABLED]], 'select' => 'order_id']);
  1768. $order_detail_model->andWhere(['in', 'o.id', array_column($order_user_handle, 'order_id')]);
  1769. }
  1770. }
  1771. if (!empty($params['province'])) {
  1772. $order_detail_model->andWhere(['IN', 'o.id', (array)self::find()->where(['mall_id' => $params['mall_id']])
  1773. ->andWhere(['OR',['province' => $params['province']], ['city' => $params['province']], ['area' => $params['province']]])
  1774. ->select('id')
  1775. ->asArray()
  1776. ->column()]);
  1777. }
  1778. if(!empty($params['cate_id'])){
  1779. $goods_cate_ids = GoodsCate::getAllCate($params['mall_id'], [$params['cate_id']]);
  1780. $order_detail_model->andWhere(['IN', 'goods_id', (array)GoodsCateRelate::find()
  1781. ->select('goods_id')->andWhere(['IN', 'cate_id' , $goods_cate_ids])
  1782. ->column()]);
  1783. }
  1784. $order_detail_model->with(['order' => function ($query) use ($isChanjetExport) {
  1785. if ($isChanjetExport) {
  1786. $query->with('addonsChanjetRequest');
  1787. }
  1788. }, 'user' => function ($query) {
  1789. $query->select('id,nickname,username,mobile');
  1790. }]);
  1791. $fields = $params['fields'];
  1792. $fields_arr = self::fieldsList(null, $isChanjetExport);
  1793. $have_select_field_arr = [];
  1794. $is_attr = 0;
  1795. foreach ($fields as $value) {
  1796. if ($value == 'goods_attr_name') {
  1797. $is_attr = 1;
  1798. }
  1799. if (isset($fields_arr[$value])) $have_select_field_arr[] = $fields_arr[$value];
  1800. if ($value == 'mch_id') {
  1801. $have_select_field_arr[] = '商户名称';
  1802. }
  1803. }
  1804. $order_status_list = OrderStatusEnum::getMap();
  1805. $payment_type_list = PayTypeEnum::getMap();
  1806. $shipping_status_list = ShippingStatusEnum::getMap();
  1807. $batchSize = 10000; // 设置订单批量导出数量
  1808. $i = 0; //循环次数
  1809. $orderCount = $order_detail_model->count(); // 查询订单总条数
  1810. $is_order_page = $orderCount > $batchSize; // 判断是否需要分页
  1811. foreach ($order_detail_model->batch($batchSize) as $order_details) {
  1812. $goods_attr_arr = [];
  1813. if ($is_attr) {
  1814. $goods_attr_ids = array_column($order_details, 'goods_attr_id');
  1815. $goods_attr_arr = GoodsAttr::lists(['where' => [['id' => $goods_attr_ids]], 'select' => 'id,goods_no', 'index' => 'id']);
  1816. }
  1817. $mch_list = [];
  1818. if (!empty($is_show_mch_name)) {
  1819. $mch_ids = array_unique(array_column($order_details, 'mch_id'));
  1820. $mch_list = Mch::lists(['where' => [['id' => $mch_ids]], 'select' => 'id,store_name', 'index' => 'id']);
  1821. }
  1822. $order_ids_arr = [];
  1823. $exportList = array_map(function ($order_detail) use ($fields, $payment_type_list, $order_status_list, $shipping_status_list, $goods_attr_arr, $mch_list,&$order_ids_arr) {
  1824. $row = [];
  1825. foreach ($fields as $field) {
  1826. // 收货人地址切割
  1827. if (!empty($order_detail['order']['region_name'])) {
  1828. $region_name = explode(' ', $order_detail['order']['region_name']);
  1829. }
  1830. // 判断是否安装社区团购
  1831. $is_install = MallAddons::isInstall($order_detail['mall_id'], AddonsEnum::ADDONS_NAME_COMMUNITY);
  1832. if ($is_install && $order_detail['order']['shipping_type'] == 2 && !empty($order_detail['order']['extra_info'])) {
  1833. $extra_info = json_decode($order_detail['order']['extra_info'], true);
  1834. if (!empty($extra_info['head_id'])) {
  1835. $headInfo = (new HeadService())->getHeadInfo($order_detail['mall_id'], $extra_info['head_id']);
  1836. if (!empty($headInfo)) {
  1837. $region_name = [
  1838. $headInfo['province'] ?? '',
  1839. $headInfo['city'] ?? '',
  1840. $headInfo['district'] ?? ''
  1841. ];
  1842. $order_detail['order']['address'] = $headInfo['address'];
  1843. }
  1844. }
  1845. }
  1846. switch (true) {
  1847. case (in_array($field, ['created_at'])):
  1848. $row[] = !empty($order_detail[$field]) ? date('Y-m-d H:i:s', $order_detail[$field]) : '';
  1849. break;
  1850. case (in_array($field, ['pay_time', 'consign_time', 'sign_time'])):
  1851. $row[] = !empty($order_detail['order'][$field]) ? date('Y-m-d H:i:s', $order_detail['order'][$field]) : '';
  1852. break;
  1853. case (in_array($field, ['order_no', 'mobile', 'receiver_name', 'region_name', 'address', 'shipping_money', 'seller_remark', 'remark'])):
  1854. $row[] = !empty($order_detail['order'][$field]) ? $order_detail['order'][$field] : '';
  1855. break;
  1856. case ($field == 'pay_money'):
  1857. if (!isset($order_ids_arr[$field]) || !in_array($order_detail['order_id'],$order_ids_arr[$field])) {
  1858. $row[] = !empty($order_detail['order'][$field]) ? $order_detail['order'][$field] : '';
  1859. $order_ids_arr[$field][]=$order_detail['order_id'];
  1860. } else {
  1861. $row[] = '';
  1862. }
  1863. break;
  1864. case (in_array($field, ['order_id'])):
  1865. $row[] = !empty($order_detail['order']['id']) ? $order_detail['order']['id'] : '';
  1866. break;
  1867. case ($field == 'payment_type'):
  1868. if (!empty($order_detail['order'][$field])) {
  1869. $row[] = !empty($payment_type_list[$order_detail['order'][$field]]) ? $payment_type_list[$order_detail['order'][$field]] : '';
  1870. } else {
  1871. $row[] = '';
  1872. }
  1873. break;
  1874. case ($field == 'order_status'):
  1875. $row[] = !empty($order_status_list[$order_detail[$field]]) ? $order_status_list[$order_detail[$field]] : '';
  1876. break;
  1877. case ($field == 'order_type'):
  1878. if ($order_detail['order']['is_feedback'] != StatusEnum::DISABLED) {
  1879. if ($order_detail['order']['is_feedback'] == StatusEnum::ENABLED) {
  1880. $row[] = '售后订单维权中';
  1881. } else {
  1882. $row[] = '售后订单维权完成';
  1883. }
  1884. } else {
  1885. $row[] = '';
  1886. }
  1887. //var_dump($order_detail['order']['is_feedback'],$row);
  1888. break;
  1889. case ($field == 'shipping_status'):
  1890. $row[] = !empty($shipping_status_list[$order_detail[$field]]) ? $shipping_status_list[$order_detail[$field]] : '';
  1891. break;
  1892. case ($field == 'pay_status'):
  1893. $row[] = !empty($order_detail['order'][$field]) ? '已付款' : '未付款';
  1894. break;
  1895. case ($field == 'out_trade_no'):
  1896. $row[] = PaymentTradeOrder::getOutTradeNoOfOrderNo($order_detail['order']['order_no'] ?? '') ?: '';
  1897. break;
  1898. case ($field == 'user_mobile'):
  1899. $row[] = $order_detail['user']['mobile'] ?? '';
  1900. break;
  1901. case ($field == 'username'):
  1902. $row[] = $order_detail['user']['username'] ?? '';
  1903. break;
  1904. case ($field == 'nickname'):
  1905. $row[] = $order_detail['user']['nickname'] ?? '';
  1906. break;
  1907. case ($field == 'detail_address'):
  1908. $str = '';
  1909. if (!empty($region_name[0])) $str .= $region_name[0];
  1910. if (!empty($region_name[1])) $str .= $region_name[1];
  1911. if (!empty($region_name[2])) $str .= $region_name[2];
  1912. if (!empty($region_name[3])) $str .= $region_name[3];
  1913. $str .= $order_detail['order']['address'];
  1914. $row[] = $str;
  1915. break;
  1916. case ($field == 'province'):
  1917. $row[] = $region_name[0] ?? '';
  1918. break;
  1919. case ($field == 'city'):
  1920. $row[] = $region_name[1] ?? '';
  1921. break;
  1922. case ($field == 'area'):
  1923. $row[] = $region_name[2] ?? '';
  1924. break;
  1925. case ($field == 'town'):
  1926. $row[] = $region_name[3] ?? '';
  1927. break;
  1928. case ($field == 'goods_attr_name'):
  1929. $str = !empty($order_detail[$field]) ? $order_detail[$field] : '';
  1930. if (!empty($goods_attr_arr[$order_detail['goods_attr_id']]['goods_no'])) {
  1931. if (!empty($str)) {
  1932. $str .= ';';
  1933. }
  1934. $str .= '货号:' . $goods_attr_arr[$order_detail['goods_attr_id']]['goods_no'];
  1935. }
  1936. $row[] = $str;
  1937. break;
  1938. case ($field == 'mch_id'):
  1939. if (isset($mch_list) && isset($mch_list[$order_detail[$field]])) {
  1940. $row[] = $mch_list[$order_detail[$field]]['store_name'];
  1941. }
  1942. break;
  1943. case ($field == 'user_id'):
  1944. $row[] = !empty($order_detail[$field]) ? $order_detail[$field] : '';
  1945. break;
  1946. case ($field == 'chanjet_updated_at'):
  1947. if (isset($order_detail['order']['addonsChanjetRequest']['updated_at'])) {
  1948. $row[] = date('Y-m-d H:i:s', $order_detail['order']['addonsChanjetRequest']['updated_at']);
  1949. }else {
  1950. $row[] = '';
  1951. }
  1952. break;
  1953. case ($field == 'chanjet_request_status'):
  1954. if (isset($order_detail['order']['addonsChanjetRequest']['request_status'])) {
  1955. $row[] = AddonsChanjetRequestEnum::getMap()[$order_detail['order']['addonsChanjetRequest']['request_status']] ?? '';
  1956. }else {
  1957. $row[] = '';
  1958. }
  1959. break;
  1960. case ($field == 'cost_total_price'):
  1961. if (isset($order_detail['cost_price']) && isset($order_detail['num']))
  1962. {
  1963. $row[] = bcmul($order_detail['num'], $order_detail['cost_price'], 2);
  1964. }else {
  1965. $row[] = '';
  1966. }
  1967. break;
  1968. case ($field == 'parent_id'):
  1969. // 获取用户上级名称
  1970. $parentId = User::find()->where(['id' => $order_detail['user_id']])->select('parent_id')->scalar();
  1971. $parentName = User::find()->where(['id' => $parentId])->select('nickname')->scalar();
  1972. $row[] = $parentName ?? '';
  1973. break;
  1974. default:
  1975. $row[] = !empty($order_detail[$field]) ? $order_detail[$field] : '';
  1976. }
  1977. }
  1978. return $row;
  1979. }, $order_details);
  1980. if (!empty($exportList)) {
  1981. $csv = new CsvTool();
  1982. $csv->filename = $is_order_page ? $filename . "_1" : $filename;
  1983. $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type);
  1984. $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC;
  1985. $csv->header = $have_select_field_arr;
  1986. $csv->data = $exportList;
  1987. if ($is_order_page && $i == 0) { // 因为订单页需要分页,所以需要设置文件名
  1988. $download->name = $filename . '_1';
  1989. $download->save();
  1990. }
  1991. if ($i >= 1) {
  1992. $newFileName = $filename . '_' . ($i + 1);
  1993. $csv->filename = $newFileName;
  1994. $downloadData = array(
  1995. 'mall_id' => $download->mall_id,
  1996. 'mch_id' => $download->mch_id,
  1997. 'store_id' => $download->store_id,
  1998. 'name' => $newFileName,
  1999. 'type' => $download->type,
  2000. 'handler_class' => $download->handler_class,
  2001. 'method' => $download->method,
  2002. 'params' => $download->params,
  2003. 'data' => $exportList
  2004. );
  2005. $downloadModel = Download::setData($downloadData);
  2006. if ($downloadModel === false) {
  2007. Yii::$app->custom->logs('创建下载任务失败:' . $downloadData['name'], Download::getStaticError());
  2008. throw new Exception('创建新下载任务失败');
  2009. };
  2010. $download = $downloadModel;
  2011. }
  2012. $csv->export();
  2013. $csv->updateDown($download, $params['mall_id']);
  2014. $i++;
  2015. }
  2016. }
  2017. $transaction->commit();
  2018. return true;
  2019. } catch (\Exception $e) {
  2020. $transaction->rollBack();
  2021. $download->status = 3;
  2022. $res = $download->save();
  2023. var_dump($e->getMessage() . $e->getFile() . $e->getLine());
  2024. self::setStaticError($e->getMessage());
  2025. return $e->getMessage();
  2026. }
  2027. }
  2028. }
  2029. public static function fieldsList($field = null, $isChanjet = false)
  2030. {
  2031. $fields = [
  2032. 'order_id' => '订单ID',
  2033. 'user_id' => '用户ID',
  2034. 'username' => '真实姓名',
  2035. 'nickname' => '用户昵称',
  2036. 'user_mobile' => '用户手机号',
  2037. 'order_no' => '订单编号',
  2038. 'out_trade_no' => '外部交易号',
  2039. 'mobile' => '收货人的手机号码',
  2040. 'detail_address' => '收货人地址全称',
  2041. 'receiver_name' => '收货人姓名',
  2042. 'province' => '收货人省份',
  2043. 'city' => '收货人城市',
  2044. 'area' => '收货人地区/街道',
  2045. 'town' => '收货人乡/镇',
  2046. // 'region_name' => '地区名称(省市区[乡/镇]',
  2047. 'address' => '详细地址',
  2048. 'goods_name' => '商品名', //detail
  2049. 'goods_attr_name' => '规格', //detail
  2050. 'num' => '购买数量', //detail
  2051. 'cost_price' => '商品成本单价', //detail
  2052. 'cost_total_price' => '商品成本总价', //detail
  2053. 'original_goods_price' => '商品原本总价', //detail
  2054. 'goods_price' => '商品优惠后总价', //detail
  2055. 'shipping_money' => '订单运费',
  2056. 'created_at' => '下单时间',
  2057. 'payment_type' => '支付方式', //-
  2058. 'order_type' => '订单情况', //-
  2059. 'order_status' => '订单状态', //-
  2060. 'pay_status' => '订单付款状态', //-
  2061. 'pay_time' => '订单付款时间',
  2062. 'shipping_status' => '订单配送状态', //- detail
  2063. 'consign_time' => '卖家发货时间', //
  2064. 'sign_time' => '买家签收时间',
  2065. 'remark' => '用户订单备注',
  2066. 'seller_remark' => '商家订单备注',
  2067. 'pay_money' => '订单实付金额',
  2068. 'parent_id' => '直推上级',
  2069. ];
  2070. if ($isChanjet) {
  2071. $fields['chanjet_updated_at'] = '最后推送时间';
  2072. $fields['chanjet_request_status'] = '推送状态';
  2073. }
  2074. if ($field === null) return $fields;
  2075. $temp = [];
  2076. foreach ($field as $val) {
  2077. if (isset($fields[$val])) $temp[$val] = $fields[$val];
  2078. }
  2079. return $temp;
  2080. }
  2081. /**
  2082. * 拼装搜索参数
  2083. * @Author bing
  2084. * @DateTime 2021-11-29 14:52:23
  2085. * @copyright: Copyright (c) 2020 广东七件事集团
  2086. * @param [type] $mall_id
  2087. * @param [type] $search
  2088. * @return array
  2089. */
  2090. public static function searchParams($mall_id, $search)
  2091. {
  2092. date_default_timezone_set('PRC');
  2093. // 查询参数
  2094. $isReserve = $search['is_reserve'];
  2095. $where[] = ['=', 'mall_id', $mall_id];
  2096. $where[] = ['>=', 'status', StatusEnum::DISABLED];
  2097. if ($isReserve) {
  2098. $where[] = ['not in', 'order_source', [OrderSourceEnum::SOURCE_SELF_MALL]];
  2099. $where[] = ['=', 'order_source', OrderSourceEnum::SOURCE_RESERVE];
  2100. } else {
  2101. $where[] = ['not in', 'order_source', [OrderSourceEnum::SOURCE_SELF_MALL, OrderSourceEnum::SOURCE_RESERVE, OrderSourceEnum::SOURCE_WUZHOU_CHAIN]];
  2102. }
  2103. $where[] = ['store_id' => 0];
  2104. if (!empty($search['mch_id'])) {
  2105. $where[] = ['mch_id' => $search['mch_id']];
  2106. } else {
  2107. $where[] = ['mch_id' => 0];
  2108. }
  2109. //配送类型搜索
  2110. if (!empty($search['shipping_type'])) $where[] = ['shipping_type'=>$search['shipping_type']];
  2111. if (isset($search['order_id'])) $where[] = ['in', 'id', explode(',', $search['order_id'])];
  2112. ($search['payment_type'] ?? false) && $where[] = ['=', 'payment_type', $search['payment_type']];
  2113. ($search['shipping_type'] ?? false) && $where[] = ['=', 'shipping_type', $search['shipping_type']];
  2114. isset($search['receiver_name']) && $search['receiver_name'] !== '' && $where[] = ['=', 'receiver_name', $search['receiver_name']];
  2115. if($search['marketing_type'] ?? false){
  2116. if($search['marketing_type'] != 'order_user_handle_finish'){
  2117. $where[] = ['=', 'marketing_type', $search['marketing_type']];
  2118. }else{
  2119. $order_user_handle = OrderUserHandle::lists(['where' => [['mall_id' => $mall_id], ['status' => StatusEnum::ENABLED]], 'select' => 'order_id']);
  2120. $where[] = ['id' => array_column($order_user_handle, 'order_id')];
  2121. }
  2122. }
  2123. if (isset($search['order_status']) && $search['order_status'] != 999) {
  2124. $where[] = ['=', 'order_status', $search['order_status']];
  2125. }
  2126. if (isset($search['is_use_coupon'])) {
  2127. if ($search['is_use_coupon'] == 1) {
  2128. $where[] = ['>', 'coupon_money', 0];
  2129. } else {
  2130. $where[] = ['=', 'coupon_money', 0];
  2131. }
  2132. }
  2133. // ($search['order_status'] ?? false) && $search['order_status'] != 999 && $where[] = ['=', 'order_status', $search['order_status']];
  2134. ($search['order_no'] ?? false) && $where[] = ['in', 'order_no', explode(',',$search['order_no'])];
  2135. ($search['start'] ?? false) && $where[] = ['>=', 'created_at', strtotime($search['start'])];
  2136. ($search['end'] ?? false) && $where[] = ['<=', 'created_at', strtotime($search['end'])];
  2137. if($search['province'] ?? false) {
  2138. $where[] =['IN', 'id', (array)self::find()->where(['mall_id' => $mall_id])
  2139. ->andWhere(['OR',['province' => $search['province']],['city' => $search['province']], ['area' => $search['province']]])
  2140. ->select('id')
  2141. ->asArray()
  2142. ->column()];
  2143. }
  2144. if($search['cate_id'] ?? false){
  2145. $goods_cate_ids = GoodsCate::getAllCate($mall_id, [$search['cate_id']]);
  2146. $order_ids = (array)OrderDetail::find()->where(['mall_id' => $mall_id])->andWhere(['IN', 'goods_id', (array)GoodsCateRelate::find()
  2147. ->select('goods_id')->andWhere(['IN', 'cate_id' ,$goods_cate_ids])
  2148. ->column()])->select('order_id')->column();
  2149. $where[] = ['id'=> $order_ids];
  2150. }
  2151. if ($search['type_value'] ?? false) {
  2152. switch ($search['type']) {
  2153. case 'mobile':
  2154. $uids = User::find()->select('id')->where(['like', 'mobile', $search['type_value'] . '%', false])->column();
  2155. !empty($uids) ? $where[] = ['in', 'user_id', $uids] : $where[] = ['=', 'user_id', 0];
  2156. break;
  2157. case 'username':
  2158. $uids = User::find()->select('id')->where(['username' => $search['type_value']])->column();
  2159. !empty($uids) && $where[] = ['in', 'user_id', $uids];
  2160. break;
  2161. case 'user_id':
  2162. $where[] = ['in', 'user_id', $search['type_value']];
  2163. break;
  2164. case 'order_id':
  2165. $where[] = ['=', 'id', $search['type_value']];
  2166. break;
  2167. case 'goods_name':
  2168. $order_detail_list = OrderDetail::lists([
  2169. 'where' => [
  2170. ['mall_id' => $mall_id],
  2171. ['store_id' => 0],
  2172. ['mch_id' => 0],
  2173. ['like', 'goods_name', '%' . $search['type_value'] . '%', false]
  2174. ],
  2175. 'select' => 'order_id'
  2176. ]);
  2177. $orderIds = array_column($order_detail_list, 'order_id');
  2178. $where[] = ['id' => $orderIds];
  2179. break;
  2180. // 查询交易单号
  2181. case 'trade_no':
  2182. $ids = PaymentTrade::find()->where(['mall_id' => $mall_id, 'out_trade_no' => $search['type_value']])->select('id')->column();
  2183. $order_nos = PaymentTradeOrder::find()->where(['trade_id' => $ids])->select('order_no')->column();
  2184. $where[] = ['order_no' => $order_nos];
  2185. break;
  2186. default:
  2187. }
  2188. }
  2189. return $where;
  2190. }
  2191. public static function updateOrderPayMoney($rand_fee_arr)
  2192. {
  2193. foreach ($rand_fee_arr as $order_no => $rand_fee) {
  2194. $order_model = Order::getOne([['order_no' => $order_no]], false, ['detail']);
  2195. if ($order_model) {
  2196. $extra_arr = json_decode($order_model->extra_info, true);
  2197. if (!is_array($extra_arr)) {
  2198. $extra_arr[] = $order_model->extra_info;
  2199. }
  2200. // $order_model->pay_money -= $rand_fee;
  2201. // $order_model->goods_price -= $rand_fee;// 随机减的金额不能减去商品实际售价金额
  2202. $order_detail_list = $order_model['detail'];
  2203. $total_goods_price = array_sum(array_column($order_detail_list, 'goods_price'));
  2204. $temp_rand_fee = 0;
  2205. $extra_arr['rand_fee']['order'] = ['desc' => '随机减', 'order_no' => $order_no, 'money' => $rand_fee];
  2206. $order_detail_extra_info = [];
  2207. foreach ($order_detail_list as $k => $order_detail) {
  2208. if (!isset($order_detail_list[$k + 1])) {
  2209. $order_detail_rand_fee = bcsub($rand_fee, $temp_rand_fee, 2);
  2210. } else {
  2211. $rate = bcdiv($order_detail['goods_price'], $total_goods_price, 2);
  2212. $order_detail_rand_fee = bcmul($rate, $rand_fee, 2);
  2213. $temp_rand_fee = bcadd($order_detail_rand_fee, $temp_rand_fee, 2);
  2214. }
  2215. // 商品优惠后的金额不包括随机减金额
  2216. // $order_detail->goods_price-=$order_detail_rand_fee;
  2217. // $order_detail->save();
  2218. $order_detail_extra_info = ['desc' => '随机减', 'order_detail_id' => $order_detail['id'], 'money' => $order_detail_rand_fee];
  2219. }
  2220. $extra_arr['rand_fee']['order_detail'] = $order_detail_extra_info;
  2221. $order_model->extra_info = json_encode($extra_arr);
  2222. $order_model->save();
  2223. }
  2224. }
  2225. }
  2226. public static function checkScoreMallIsCommission($marketing_type)
  2227. {
  2228. $join_commission = isset(\Yii::$app->params['is_score_mall_join_commission']) ? \Yii::$app->params['is_score_mall_join_commission'] : true;
  2229. return $marketing_type == AddonsEnum::ADDONS_NAME_SCORE_MALL && !$join_commission;
  2230. }
  2231. public static function userInitiativeComplete($params)
  2232. {
  2233. try{
  2234. $order = self::findOne(['id' => $params['id'], 'mall_id' => $params['mall_id'], 'status' => StatusEnum::ENABLED]);
  2235. if(empty($order)) throw new \Exception('订单参数错误');
  2236. if(!in_array($order->order_status ,[OrderStatusEnum::PAY,OrderStatusEnum::SHIPMENTS,OrderStatusEnum::SING])){
  2237. throw new \Exception('该订单不支持此操作');
  2238. }
  2239. if($order->order_status == OrderStatusEnum::PAY){
  2240. $new_params = $params;
  2241. $new_params['order_detail_ids'] = [];
  2242. $new_params['shipping_type'] = 0;
  2243. $new_params['express_id'] = $new_params['express_name'] = $new_params['customer_name']= $new_params['express_no'] = $new_params['memo']= '';
  2244. $details = ArrayHelper::toArray($order->detail);
  2245. foreach($details as $detail){
  2246. $new_params['order_detail_ids'][] = $detail['id'];
  2247. }
  2248. if(OrderExpress::delivery($new_params) == false){
  2249. throw new \Exception(OrderExpress::getStaticError());
  2250. }
  2251. $order->order_status = OrderStatusEnum::SHIPMENTS;
  2252. if(self::takeDelivery($params) == false){
  2253. throw new \Exception(self::getStaticError());
  2254. }
  2255. }
  2256. if(self::complete($params) == false){
  2257. throw new \Exception(self::getStaticError());
  2258. }
  2259. OrderUserHandle::setData([
  2260. 'mall_id' => $params['mall_id'],
  2261. 'user_id' => $params['user_id'],
  2262. 'order_id' => $params['id'],
  2263. 'order_status' => OrderStatusEnum::ACCOMPLISH
  2264. ]);
  2265. return true;
  2266. }catch(\Exception $e){
  2267. self::setStaticError($e->getMessage());
  2268. return false;
  2269. }
  2270. }
  2271. public static function handleVerifyOrder($params)
  2272. {
  2273. try{
  2274. $order = self::findOne(['id' => $params['id'], 'mall_id' => $params['mall_id'], 'status' => StatusEnum::ENABLED]);
  2275. if(empty($order)) throw new \Exception('订单参数错误');
  2276. if(!in_array($order->order_status ,[OrderStatusEnum::PAY,OrderStatusEnum::SHIPMENTS,OrderStatusEnum::SING])){
  2277. throw new \Exception('该订单不支持此操作');
  2278. }
  2279. if($order->order_status == OrderStatusEnum::PAY){
  2280. $new_params = $params;
  2281. $new_params['order_detail_ids'] = [];
  2282. $new_params['shipping_type'] = 0;
  2283. $new_params['express_id'] = $new_params['express_name'] = $new_params['customer_name']= $new_params['express_no'] = $new_params['memo']= '';
  2284. $details = ArrayHelper::toArray($order->detail);
  2285. foreach($details as $detail){
  2286. $new_params['order_detail_ids'][] = $detail['id'];
  2287. }
  2288. if(OrderExpress::delivery($new_params) == false){
  2289. throw new \Exception(OrderExpress::getStaticError());
  2290. }
  2291. $order->order_status = OrderStatusEnum::SHIPMENTS;
  2292. }
  2293. if($order->order_status == OrderStatusEnum::SHIPMENTS){
  2294. if(self::takeDelivery($params) == false){
  2295. throw new \Exception(self::getStaticError());
  2296. }
  2297. }
  2298. if(self::complete($params) == false){
  2299. throw new \Exception(self::getStaticError());
  2300. }
  2301. return true;
  2302. }catch(\Exception $e){
  2303. self::setStaticError($e->getMessage());
  2304. return false;
  2305. }
  2306. }
  2307. /**
  2308. * 批量添加备注
  2309. * @param $params
  2310. * @return bool
  2311. */
  2312. public static function batchRemark(array $params): bool
  2313. {
  2314. try {
  2315. $orderIds = explode(',', $params['order_ids']);
  2316. $res = self::updateAll(['seller_remark' => $params['content']], ['id' => $orderIds]);
  2317. if (!$res) {
  2318. throw new Exception('批量备注失败!');
  2319. }
  2320. return true;
  2321. } catch (Exception $e) {
  2322. if(isset($trans)) $trans->rollback();
  2323. self::$static_error = $e->getMessage();
  2324. return false;
  2325. }
  2326. }
  2327. /**
  2328. * 国内手机号验证
  2329. * @param $number
  2330. * @return bool
  2331. */
  2332. public static function isMobileNumber($number): bool
  2333. {
  2334. // 手机号正则表达式
  2335. $pattern = '/^1[3-9]\d{9}$/';
  2336. if (preg_match($pattern, $number)) {
  2337. return true;
  2338. } else {
  2339. return false;
  2340. }
  2341. }
  2342. }