Order.php 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types = 1);
  12. namespace app\store\model;
  13. use app\store\model\OrderGoods as OrderGoodsModel;
  14. use think\facade\Request;
  15. use app\common\model\Order as OrderModel;
  16. use app\common\model\OrderAddress as OrderAddressModel;
  17. use app\common\service\Order as OrderService;
  18. use app\common\service\Message as MessageService;
  19. use app\common\service\order\Refund as RefundService;
  20. use app\common\enum\order\OrderStatus as OrderStatusEnum;
  21. use app\common\enum\order\PayStatus as PayStatusEnum;
  22. use app\common\enum\order\DeliveryType as DeliveryTypeEnum;
  23. use app\common\enum\order\ReceiptStatus as ReceiptStatusEnum;
  24. use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
  25. use app\common\library\helper;
  26. /**
  27. * 订单管理
  28. * Class Order
  29. * @package app\store\model
  30. */
  31. class Order extends OrderModel
  32. {
  33. // 全部订单
  34. const LIST_TYPE_ALL = 'all';
  35. // 待发货订单
  36. const LIST_TYPE_DELIVERY = 'delivery';
  37. // 待收货订单
  38. const LIST_TYPE_RECEIPT = 'receipt';
  39. // 待付款订单
  40. const LIST_TYPE_PAY = 'pay';
  41. // 已完成订单
  42. const LIST_TYPE_COMPLETE = 'complete';
  43. // 已取消
  44. const LIST_TYPE_CANCEL = 'cancel';
  45. /**
  46. * 订单详情页数据
  47. * @param int $orderId
  48. * @return Order|array|false|null
  49. */
  50. public function getDetail(int $orderId)
  51. {
  52. return static::detail($orderId, [
  53. 'user',
  54. 'address',
  55. 'goods' => ['image'],
  56. // 'express',
  57. 'coupon',
  58. 'shops',
  59. 'commissionsDetail',
  60. 'commissionsDetail.user'
  61. ]) ?: false;
  62. }
  63. /**
  64. * 订单列表
  65. * @param string $dataType 订单类型
  66. * @param array $param
  67. * @return mixed
  68. */
  69. public function getList(string $dataType = self::LIST_TYPE_ALL, array $param = [],$size = 15)
  70. {
  71. // $size =15;
  72. // 检索查询条件
  73. $filter = $this->getQueryFilter($param);
  74. // 设置订单类型条件
  75. $dataTypeFilter = $this->getFilterDataType($dataType);
  76. $kw = $param['kw']??'';
  77. // 获取数据列表
  78. $query = $this->with(['goods'=>['image', 'provider', 'shop'], 'user.avatar', 'address'])//'commissionsDetail.user', 'commissionsUser',
  79. ->alias('order')
  80. ->field('order.*')
  81. ->leftJoin('user', 'user.user_id = order.user_id')
  82. ->leftJoin('order_address','order_address.order_id = order.order_id')
  83. ->leftJoin('shops', 'shops.shop_id = order.staff_shop_id')
  84. ->where($dataTypeFilter)
  85. ->where($filter)->where(function($query)use ($kw) {
  86. if(!empty($kw)){
  87. $query->where('user.mobile','like','%'.$kw.'%');
  88. $query->whereOr('user.nick_name','like','%'.$kw.'%');
  89. }
  90. });
  91. //店铺ID搜索
  92. if (!empty($param['providerId'])) {
  93. $query->whereFindInSet('order.provider_ids', (int)$param['providerId']);
  94. }
  95. return $query->where('order.is_delete', '=', 0)
  96. ->order(['order.create_time' => 'desc'])
  97. ->paginate($size)
  98. ->each(function($e){
  99. $res = [];
  100. foreach ($e['goods'] as &$goods){
  101. //获取平台让利的 分润金额
  102. $goods['pool_money'] = 0;
  103. $goods['commissions_content'] = '';
  104. $goods['pool_money'] = '分润金额:¥ '.helper::bcadd($goods['pool_money'],0,4);
  105. $res[$goods['provider_id']]['provider_name'] = $goods['provider_name'];
  106. $res[$goods['provider_id']]['goods'][] = $goods;
  107. }
  108. $res = array_values($res);
  109. $e['goods_list'] = $res;
  110. unset($e['goods']);
  111. });
  112. }
  113. /**
  114. * 订单列表
  115. * @param string $dataType 订单类型
  116. * @param array $param
  117. * @return mixed
  118. */
  119. public function getFinanceList(string $dataType = self::LIST_TYPE_ALL, array $param = [])
  120. {
  121. // 检索查询条件
  122. $filter = $this->getQueryFilter($param);
  123. // 设置订单类型条件
  124. $dataTypeFilter = $this->getFilterDataType($dataType);
  125. // 获取数据列表
  126. $query = $this->with(['goods'=>['image', 'provider']])
  127. ->alias('order')
  128. ->field('order.*')
  129. ->where('order.pay_status',20)
  130. ->where($dataTypeFilter)
  131. ->where($filter);
  132. return $query->where('order.is_delete', '=', 0)
  133. ->order(['order.create_time' => 'desc'])
  134. ->paginate()
  135. ->each(function($e){
  136. $res = [];
  137. foreach ($e['goods'] as &$goods){
  138. //获取平台让利的 分润金额
  139. $res[$goods['provider_id']]['provider_name'] = $goods['provider_name'];
  140. $res[$goods['provider_id']]['goods'][] = $goods;
  141. }
  142. $res = array_values($res);
  143. $e['goods_list'] = $res;
  144. $e['cal_order_price'] = helper::bcadd($e['pay_price'],$e['rice_card_money'],2);
  145. unset($e['goods']);
  146. });
  147. }
  148. public function getListssss($goods){
  149. //获取平台让利的 分润金额
  150. $goods['pool_money'] = helper::bcadd(OrderService::getPoolMoney($goods),0,4);
  151. $goods['commissions_content'] = '';
  152. $goods['commissions_role_one'] = $goods['commissions_role_two'] = $goods['commissions_role_'] = $goods['commissions_role_one'] = $goods['commissions_role_one'] = '';
  153. foreach ($goods['commissionsDetail'] as $detail){
  154. switch ($detail['role']){
  155. case 1:
  156. $goods['commissions_content'] .= '普通用户佣金:¥ '.$detail['clearing_money'].' '.$detail['user']['nick_name']??''.$detail['user']['mobile']??'';
  157. break;
  158. case 2:
  159. $goods['commissions_content'] .= '店员佣金:¥ '.$detail['clearing_money'].' '.$detail['user']['nick_name']??''.$detail['user']['mobile']??'';
  160. break;
  161. case 3:
  162. $goods['commissions_content'] .= ' | 店长佣金:¥ '.$detail['clearing_money'].' '.$detail['user']['nick_name']??''.$detail['user']['mobile']??'';
  163. break;
  164. case 4:
  165. $goods['commissions_content'] .= ' 店老板佣金:¥ '.$detail['clearing_money'].' '.$detail['user']['nick_name']??''.$detail['user']['mobile']??'';
  166. break;
  167. }
  168. }
  169. }
  170. /**
  171. * 订单列表(全部)
  172. * @param string $dataType 订单类型
  173. * @param array $query
  174. * @return mixed
  175. */
  176. public function getListAll(string $dataType = self::LIST_TYPE_ALL, array $query = [])
  177. {
  178. // 检索查询条件
  179. $queryFilter = $this->getQueryFilter($query);
  180. // 设置订单类型条件
  181. $dataTypeFilter = $this->getFilterDataType($dataType);
  182. // var_dump($query);javascript:;
  183. // die();
  184. // 获取数据列表
  185. return $this->with(['goods.image', 'address', 'user.avatar'])
  186. ->alias('order')
  187. ->field('order.*')
  188. ->join('user', 'user.user_id = order.user_id')
  189. ->where($dataTypeFilter)
  190. ->where($queryFilter)
  191. ->where('order.is_delete', '=', 0)
  192. ->order(['order.create_time' => 'desc'])
  193. ->select();
  194. }
  195. /**
  196. * 设置检索查询条件
  197. * @param array $param
  198. * @return array
  199. */
  200. private function getQueryFilter(array $param): array
  201. {
  202. // 默认参数
  203. $params = $this->setQueryDefaultValue($param, [
  204. 'orderSource' => -1, // 订单来源
  205. 'payType' => -1, // 支付方式
  206. 'deliveryType' => -1, // 配送方式
  207. 'betweenTime' => [], // 起止时间
  208. 'userId' => 0, // 会员ID
  209. 'delivery_type'=>-1, //配送方式
  210. 'shop_id'=>-1, //门店id
  211. 'kw'=>''
  212. ]);
  213. // 检索查询条件
  214. $filter = [];
  215. if(!empty($params['nickName'])){
  216. $filter[] = ['user.nick_name','like',"%{$params['nickName']}%"];
  217. }
  218. //用户手机
  219. !empty($params['mobile']) && $filter[] = ['user.mobile', 'like', "%{$params['mobile']}%"];
  220. //
  221. // if(!empty($params['user_kw'])){
  222. // $filter[] = ['user.nick_name','like',"%{$params['kw']}%"];
  223. // $filter[] = ['user.mobile', 'like', "%{$params['kw']}%"];
  224. // }
  225. // 订单号
  226. if (!empty($params['orderNo'])) {
  227. $filter[] = ['order.order_no', 'like', "%{$params['orderNo']}%"];
  228. }
  229. if(isset($params['delivery_type'])&&$params['delivery_type']>-1){
  230. $filter[] = ['order.delivery_type','=',$params['delivery_type']];
  231. }
  232. //发货状态
  233. if(isset($params['delivery_status'])&&$params['delivery_status']>-1){
  234. $filter[] = ['order.delivery_status','=',$params['delivery_status']];
  235. }
  236. if(isset($params['shop_id'])&&$params['shop_id']>-1){
  237. $filter[] = ['order.shop_id','=',$params['shop_id']];
  238. }
  239. // 下单起止时间
  240. if (!empty($params['betweenTime'])) {
  241. $times = between_time_format($params['betweenTime']);
  242. $filter[] = ['order.create_time', '>=', $times['start_time']];
  243. $filter[] = ['order.create_time', '<', $times['end_time']];
  244. }
  245. // 付款起止时间
  246. if (!empty($params['betweenPayTime'])) {
  247. $times = between_time_format($params['betweenPayTime']);
  248. $filter[] = ['order.pay_time', '>=', $times['start_time']];
  249. $filter[] = ['order.pay_time', '<', $times['end_time'] ];
  250. }
  251. // 微信支付时间
  252. if (!empty($params['wxPayTime'])) {
  253. $times = between_time_format($params['wxPayTime']);
  254. $filter[] = ['order.pay_time', '>=', $times['start_time']];
  255. $filter[] = ['order.pay_time', '<', $times['end_time'] ];
  256. $filter[] = ['order.pay_type', '=', 20];
  257. $filter[] = ['order.pay_status', '=', 20];
  258. }
  259. // 完成起止时间
  260. if (!empty($params['betweenReceiptTime'])) {
  261. $times = between_time_format($params['betweenReceiptTime']);
  262. $filter[] = ['order.receipt_time', '>=', $times['start_time']];
  263. $filter[] = ['order.receipt_time', '<', $times['end_time']];
  264. }
  265. // 订单来源
  266. $params['orderSource'] > -1 && $filter[] = ['order_source', '=', (int)$params['orderSource']];
  267. // 支付方式
  268. $params['payType'] > -1 && $filter[] = ['pay_type', '=', (int)$params['payType']];
  269. //支付状态10未付款,20已付款
  270. !empty($params['payStatus']) && $params['payStatus'] > -1 && $filter[] = ['pay_status', '=', (int)$params['payStatus']];
  271. // 配送方式
  272. $params['deliveryType'] > -1 && $filter[] = ['delivery_type', '=', (int)$params['deliveryType']];
  273. // 用户id
  274. $params['userId'] > 0 && $filter[] = ['order.user_id', '=', (int)$params['userId']];
  275. //标记颜色
  276. if(isset($params['color'])&&$params['color']!='-1'){
  277. $filter[] = ['order.color', 'like', "%{$params['color']}%"];
  278. }
  279. //微信支付交易号
  280. if(!empty($params['transactionId'])){
  281. $filter[] = ['order.transaction_id', 'like', "%{$params['transactionId']}%"];
  282. }
  283. //门店搜索--v1.3.7添加2022年3月31日 14:14:44
  284. if (isset($params['shopName']) && !empty($params['shopName'])) {
  285. $filter[] = ['shops.shop_name', 'like', "%{$params['shopName']}%"];
  286. }
  287. //收件人姓名或手机
  288. if(isset($params['addressKw'])&&!empty($params['addressKw'])){
  289. $filter[] = ['order_address.phone|order_address.name', 'like', '%' . trim($params['addressKw']) . '%'];
  290. }
  291. //订单状态
  292. if (isset($params['stateValue']) && $params['stateValue'] > 0) {
  293. switch ($params['stateValue']) {
  294. case 11://'待支付';
  295. $filter[] = ['order.pay_status', '=', 10];
  296. $filter[] = ['order.order_status','=',10];
  297. break;
  298. case 12://'已付款待发货';
  299. $filter[] = ['order.pay_status', '=', 20];
  300. $filter[] = ['order.delivery_status', '=', 10];
  301. $filter[] = ['order.order_status','=',10];
  302. break;
  303. case 13://'已付款待收货';
  304. $filter[] = ['order.pay_status', '=', 20]; //已付款
  305. $filter[] = ['order.delivery_status', '=', 20];//已发货
  306. $filter[] = ['order.receipt_status', '=', 10];//未收货
  307. $filter[] = ['order.order_status','=',10];
  308. break;
  309. case 20://'已取消';
  310. $filter[] = ['order.order_status','=',20];
  311. break;
  312. case 30://'已完成';
  313. $filter[] = ['order.order_status','=',30];
  314. break;
  315. case 40://'已关闭';
  316. $filter[] = ['order.order_status','=',40];
  317. break;
  318. default:
  319. # code...
  320. break;
  321. }
  322. }
  323. $result = [];
  324. //商品名称 店铺名称 合并在一个参数搜索
  325. if (isset($params['goodsName']) && !empty($params['goodsName'])) {
  326. $ogm = new OrderGoodsModel;
  327. $result = array_values(array_unique(array_merge($result,$ogm->searchGoodName($params['goodsName']))));
  328. }
  329. //快递单号
  330. if (isset($params['expressNo']) && !empty($params['expressNo'])) {
  331. $ogm = new OrderGoodsModel;
  332. $result = array_values(array_unique(array_merge($result,$ogm->searchExpressNo($params['expressNo']))));
  333. }
  334. if(count($result)){
  335. $filter[] = ['order.order_id', 'in', $result];
  336. }
  337. return $filter;
  338. }
  339. /**
  340. * 设置订单类型条件
  341. * @param string $dataType
  342. * @return array
  343. */
  344. private function getFilterDataType(string $dataType = self::LIST_TYPE_ALL): array
  345. {
  346. // 数据类型
  347. $filter = [];
  348. switch ($dataType) {
  349. case self::LIST_TYPE_ALL:
  350. $filter = [];
  351. break;
  352. case self::LIST_TYPE_DELIVERY:
  353. $filter = [
  354. ['pay_status', '=', PayStatusEnum::SUCCESS],
  355. ['delivery_status', '=', DeliveryStatusEnum::NOT_DELIVERED],
  356. ['order_status', 'in', [OrderStatusEnum::NORMAL, OrderStatusEnum::APPLY_CANCEL]]
  357. ];
  358. break;
  359. case self::LIST_TYPE_RECEIPT:
  360. $filter = [
  361. ['pay_status', '=', PayStatusEnum::SUCCESS],
  362. ['delivery_status', '=', DeliveryStatusEnum::DELIVERED],
  363. ['receipt_status', '=', ReceiptStatusEnum::NOT_RECEIVED]
  364. ];
  365. break;
  366. case self::LIST_TYPE_PAY:
  367. $filter[] = ['pay_status', '=', PayStatusEnum::PENDING];
  368. $filter[] = ['order_status', '=', OrderStatusEnum::NORMAL];
  369. break;
  370. case self::LIST_TYPE_COMPLETE:
  371. $filter[] = ['order_status', '=', OrderStatusEnum::COMPLETED];
  372. break;
  373. case self::LIST_TYPE_CANCEL:
  374. $filter[] = ['order_status', '=', OrderStatusEnum::CANCELLED];
  375. break;
  376. }
  377. return $filter;
  378. }
  379. /**
  380. * 确认发货(单独订单)
  381. * @param $data
  382. * @return array|bool|false
  383. * @throws \Exception
  384. */
  385. public function delivery($data)
  386. {
  387. // 转义为订单列表
  388. $orderList = [$this];
  389. // 验证订单是否满足发货条件
  390. if (!$this->verifyDelivery($orderList)) {
  391. return false;
  392. }
  393. // 整理更新的数据
  394. $updateList = [[
  395. 'order_id' => $this['order_id'],
  396. 'express_id' => $data['express_id'],
  397. 'express_no' => $data['express_no']
  398. ]];
  399. // 更新订单发货状态
  400. $this->updateToDelivery($updateList);
  401. // 获取已发货的订单
  402. $completed = self::detail($this['order_id'], ['user', 'address', 'goods', 'express']);
  403. // 发送消息通知
  404. $this->sendDeliveryMessage([$completed]);
  405. return true;
  406. }
  407. /**
  408. * 确认发货后发送消息通知
  409. * @param $orderList
  410. * @return bool
  411. */
  412. private function sendDeliveryMessage($orderList)
  413. {
  414. // 发送消息通知
  415. foreach ($orderList as $item) {
  416. MessageService::send('order.delivery', ['order' => $item], self::$storeId);
  417. }
  418. return true;
  419. }
  420. /**
  421. * 更新订单发货状态(批量)
  422. * @param $orderList
  423. * @return bool
  424. */
  425. private function updateToDelivery($orderList)
  426. {
  427. // 整理更新的数据
  428. $data = [];
  429. foreach ($orderList as $item) {
  430. $data[] = [
  431. 'data' => [
  432. 'express_no' => $item['express_no'],
  433. 'express_id' => $item['express_id'],
  434. 'delivery_status' => 20,
  435. 'delivery_time' => time(),
  436. ],
  437. 'where' => ['order_id' => $item['order_id']]
  438. ];
  439. }
  440. // 批量更新
  441. $this->updateAll($data);
  442. return true;
  443. }
  444. /**
  445. * 验证订单是否满足发货条件
  446. * @param $orderList
  447. * @return bool
  448. */
  449. private function verifyDelivery($orderList)
  450. {
  451. foreach ($orderList as $order) {
  452. if (
  453. $order['pay_status'] != PayStatusEnum::SUCCESS
  454. || $order['delivery_type'] != DeliveryTypeEnum::EXPRESS
  455. || $order['delivery_status'] != DeliveryStatusEnum::NOT_DELIVERED
  456. ) {
  457. $this->error = "订单号[{$order['order_no']}] 不满足发货条件!";
  458. return false;
  459. }
  460. }
  461. return true;
  462. }
  463. /**
  464. * 修改订单价格
  465. * @param array $data
  466. * @return bool
  467. */
  468. public function updatePrice(array $data)
  469. {
  470. if ($this['pay_status'] != PayStatusEnum::PENDING) {
  471. $this->error = '该订单不合法';
  472. return false;
  473. }
  474. // 实际付款金额
  475. $payPrice = helper::bcadd($data['order_price'], $data['express_price']);
  476. if ($payPrice <= 0) {
  477. $this->error = '订单实付款价格不能为0.00元';
  478. return false;
  479. }
  480. // 改价的金额差价
  481. $updatePrice = helper::bcsub($data['order_price'], $this['order_price']);
  482. // 更新订单记录
  483. return $this->save([
  484. 'order_no' => $this->orderNo(), // 修改订单号, 否则微信支付提示重复
  485. 'pay_price' => $payPrice,
  486. 'update_price' => $updatePrice,
  487. 'express_price' => $data['express_price']
  488. ]) !== false;
  489. }
  490. /**
  491. * 审核:用户取消订单
  492. * @param array $data
  493. * @return bool|mixed
  494. */
  495. public function confirmCancel(array $data)
  496. {
  497. // 判断订单是否有效
  498. if ($this['pay_status'] != PayStatusEnum::SUCCESS) {
  499. $this->error = '该订单不合法';
  500. return false;
  501. }
  502. // 订单取消事件
  503. return $this->transaction(function () use ($data) {
  504. if ($data['status'] == true) {
  505. // 执行退款操作
  506. (new RefundService)->execute($this);
  507. // 订单取消事件
  508. OrderService::cancelEvent($this);
  509. }
  510. // 更新订单状态
  511. return $this->save(['order_status' => $data['status'] ? OrderStatusEnum::CANCELLED : OrderStatusEnum::NORMAL]);
  512. });
  513. }
  514. /**
  515. * 获取已付款订单总数 (可指定某天)
  516. * @param null $startDate
  517. * @param null $endDate
  518. * @return int|string
  519. */
  520. public function getPayOrderTotal($startDate = null, $endDate = null)
  521. {
  522. $filter = [
  523. ['pay_status', '=', PayStatusEnum::SUCCESS],
  524. ['order_status', '<>', OrderStatusEnum::CANCELLED]
  525. ];
  526. if (!is_null($startDate) && !is_null($endDate)) {
  527. $filter[] = ['pay_time', '>=', strtotime($startDate)];
  528. $filter[] = ['pay_time', '<', strtotime($endDate) + 86400];
  529. }
  530. return $this->getOrderTotal($filter);
  531. }
  532. /**
  533. * 获取已付款订单商品总数( (可指定某天))
  534. * @param null $startDate
  535. * @param null $endDate
  536. * @return int
  537. */
  538. public function getPayOrderGoodsTotal($startDate = null, $endDate = null)
  539. {
  540. $filter = [
  541. ['order.pay_status', '=', PayStatusEnum::SUCCESS],
  542. ['order.order_status', '<>', OrderStatusEnum::CANCELLED],
  543. ['og.goods_type', '<>', 20], // 排除赠品
  544. ];
  545. if (!is_null($startDate) && !is_null($endDate)) {
  546. $filter[] = ['order.pay_time', '>=', strtotime($startDate)];
  547. $filter[] = ['order.pay_time', '<', strtotime($endDate) + 86400];
  548. }
  549. return $this->getOrderGoodsTotal($filter);
  550. }
  551. /**
  552. * 获取本月已付款订单总数
  553. * @return mixed
  554. */
  555. public function getMonthPayOrderTotal()
  556. {
  557. return $this->whereTime('pay_time', 'month')
  558. ->where('pay_status', '=',PayStatusEnum::SUCCESS)
  559. ->where('order_status', '<>', OrderStatusEnum::CANCELLED)
  560. ->where('is_delete', '=', '0')
  561. ->count();
  562. }
  563. /**
  564. * 获取本月已付款用户总数
  565. * @return mixed
  566. */
  567. public function getMonthPayUserTotal()
  568. {
  569. return $this->field('user_id')
  570. ->whereTime('pay_time', 'month')
  571. ->where('pay_status', '=', PayStatusEnum::SUCCESS)
  572. ->where('order_status', '<>', OrderStatusEnum::CANCELLED)
  573. ->where('is_delete', '=', '0')
  574. ->group('user_id')
  575. ->count();
  576. }
  577. /**
  578. * 获取未发货订单数量
  579. * @return int
  580. */
  581. public function getNotDeliveredOrderTotal()
  582. {
  583. $filter = [
  584. ['pay_status', '=', PayStatusEnum::SUCCESS],
  585. ['delivery_status', '=', DeliveryStatusEnum::NOT_DELIVERED],
  586. ['order_status', 'in', [OrderStatusEnum::NORMAL, OrderStatusEnum::APPLY_CANCEL]]
  587. ];
  588. return $this->getOrderTotal($filter);
  589. }
  590. /**
  591. * 获取未付款订单数量
  592. * @return int
  593. */
  594. public function getNotPayOrderTotal()
  595. {
  596. $filter = [
  597. ['pay_status', '=', PayStatusEnum::PENDING],
  598. ['order_status', '=', OrderStatusEnum::NORMAL]
  599. ];
  600. return $this->getOrderTotal($filter);
  601. }
  602. /**
  603. * 获取订单总数
  604. * @param array $filter
  605. * @return int
  606. */
  607. private function getOrderTotal(array $filter = [])
  608. {
  609. // 获取订单总数量
  610. return $this->where($filter)
  611. ->where('is_delete', '=', 0)
  612. ->count();
  613. }
  614. /**
  615. * 获取订单商品总数
  616. * @param array $filter
  617. * @return int
  618. */
  619. private function getOrderGoodsTotal(array $filter = [])
  620. {
  621. // 获取订单商品总数量
  622. return OrderModel::alias('order')->where($filter)
  623. ->leftJoin('order_goods og', 'og.order_id=order.order_id')
  624. ->where('order.is_delete', '=', 0)
  625. ->sum('og.total_num');
  626. }
  627. /**
  628. * 获取某天的总销售额
  629. * @param null $startDate
  630. * @param null $endDate
  631. * @return float|int
  632. */
  633. public function getOrderTotalPrice($startDate = null, $endDate = null)
  634. {
  635. // 查询对象
  636. $query = $this->getNewQuery();
  637. // 设置查询条件
  638. if (!is_null($startDate) && !is_null($endDate)) {
  639. $query->where('pay_time', '>=', strtotime($startDate))
  640. ->where('pay_time', '<', strtotime($endDate) + 86400);
  641. }
  642. // 总销售额
  643. $data = $query->where('pay_status', '=', PayStatusEnum::SUCCESS)
  644. ->where('order_status', '<>', OrderStatusEnum::CANCELLED)
  645. ->where('is_delete', '=', 0)
  646. ->field('sum(pay_price+rice_card_money) as c')
  647. ->find();
  648. return $data->c ?? 0;
  649. }
  650. /**
  651. * 获取某批订单的总销售额
  652. * @param null $startDate
  653. * @param null $endDate
  654. * @return float|int
  655. */
  656. public function getOrderSellPrice($order_id_arr)
  657. {
  658. // 总销售额
  659. $query = $this->getNewQuery();
  660. $query->where('order_id', 'in', $order_id_arr);
  661. // return $query->where('pay_status', '=', PayStatusEnum::SUCCESS)
  662. // ->where('order_status', '<>', OrderStatusEnum::CANCELLED)
  663. // ->where('is_delete', '=', 0)
  664. // ->sum('pay_price');
  665. $one = $query->field('sum(pay_price)+sum(rice_card_money)-sum(express_price) as c')->where('pay_status', '=', PayStatusEnum::SUCCESS)
  666. ->where('order_status', '<>', OrderStatusEnum::CANCELLED)
  667. ->where('is_delete', '=', 0)
  668. ->find();
  669. return $one->c??0;
  670. }
  671. /**
  672. * 获取某天的下单用户数
  673. * @param string $day
  674. * @return float|int
  675. */
  676. public function getPayOrderUserTotal(string $day)
  677. {
  678. $startTime = strtotime($day);
  679. return $this->field('user_id')
  680. ->where('pay_time', '>=', $startTime)
  681. ->where('pay_time', '<', $startTime + 86400)
  682. ->where('pay_status', '=', PayStatusEnum::SUCCESS)
  683. ->where('is_delete', '=', '0')
  684. ->group('user_id')
  685. ->count();
  686. }
  687. /**
  688. * 添加或修改标签备注
  689. * @param array $param
  690. * @return int
  691. */
  692. public function updColor(array $param)
  693. {
  694. return $this->updateBase([
  695. 'color' => $param['color'],
  696. 'color_remark' => $param['color_remark'],
  697. ],['order_id' => $param['order_id']]);
  698. }
  699. /**
  700. * 修改下单用户收货信息
  701. * @param array $param
  702. * @return int
  703. */
  704. public function updAddress(array $param)
  705. {
  706. $OrderAddress = OrderAddressModel::find($param['order_address_id']);
  707. // 判断订单是否有效
  708. $order = $this->getDetail($OrderAddress['order_id']);
  709. if ($order['pay_status'] != PayStatusEnum::PENDING || $order['order_status'] != OrderStatusEnum::NORMAL) {
  710. $this->error = '待付款的订单才能修改收货地址';
  711. return false;
  712. }
  713. return OrderAddressModel::updateBase([
  714. 'name' => $param['name'],
  715. 'phone' => $param['phone'],
  716. 'province_id' => $param['province_id'],
  717. 'city_id' => $param['city_id'],
  718. 'region_id' => $param['region_id'],
  719. 'detail' => $param['detail'],
  720. ],['order_address_id' => $param['order_address_id']]);
  721. }
  722. public function listdtExport($param,$dataType=self::LIST_TYPE_ALL){
  723. // 获取列表数据
  724. $filter = $this->getQueryFilter($param);
  725. // 设置订单类型条件
  726. $dataTypeFilter = $this->getFilterDataType($dataType);
  727. // 获取数据列表
  728. $query = $this->with(['goods'=>['image', 'provider']])
  729. ->alias('order')
  730. ->field('order.order_id,order.order_no,order.create_time,order.order_status,order.pay_status,order.delivery_status,order.delivery_type,order.receipt_status,order.pay_price ,order.express_price,order.total_price,order.transaction_id,order.coupon_money,order.order_source,order.activity_discount_total_price,order.bargain_money,order.groupbuy_money,order.distributor_total_money,order.rice_card_money,(order.pay_price + rice_card_money) as cal_order_price')
  731. ->where('order.pay_status',20)
  732. ->where($dataTypeFilter)
  733. ->where($filter);
  734. $list = $query->where('order.is_delete', '=', 0)
  735. ->order(['order.create_time' => 'desc'])//->limit(0,1000)
  736. ->select();
  737. $data['header'] = ['序号', '订单编号','下单时间','订单状态', '商品名称','商品编号','商品规格','供应商品牌','单价','数量',
  738. '配送方式', '运费','订单总金额','实付金额','专属折扣优惠','活动优惠','优惠券优惠','现金卡抵扣','微信交易流水号'];
  739. $data['filename'] = '销售明细列表导出';
  740. $data['data'] = [];
  741. foreach ($list as $key=>$arr){
  742. /* if (count($arr['goods']) == 1){
  743. $new_list = [];
  744. $new_list['key'] = $key+1;
  745. $new_list['order_no'] = $arr['order_no'];
  746. $new_list['create_time'] = $arr['create_time'];
  747. $new_list['state_text'] = $arr['state_text'];
  748. $new_list['goods_name'] = $arr['goods'][0]['goods_name'];
  749. $new_list['goods_no'] = $arr['goods'][0]['goods_no'];
  750. $new_list['goods_props'] = $arr['goods'][0]['specs']??'-';
  751. $new_list['supplier'] = $arr['goods'][0]['supplier'] ?: '-';
  752. $new_list['goods_price'] = $arr['goods'][0]['goods_price'];
  753. $new_list['total_num'] = $arr['goods'][0]['total_num'];
  754. $new_list['delivery_type'] = ($arr['delivery_type']==10)?'普通配送':'门店自提';
  755. $new_list['express_price'] = $arr['express_price'];
  756. $new_list['total_price'] = $arr['total_price'];
  757. $new_list['pay_price'] = $arr['pay_price'];
  758. $new_list['distributor_total_money'] = $arr['distributor_total_money'];
  759. $new_list['act_discount_money'] = ($arr['order_source'] == 10)?$arr['activity_discount_total_price']:($arr['order_source'] == 30?$arr['bargain_money']:($arr['order_source'] == 40?$arr['groupbuy_money']:0));
  760. $new_list['coupon_money'] = $arr['coupon_money'];
  761. $new_list['rice_card_money'] = $arr['rice_card_money'];
  762. $new_list['transaction_id'] = $arr['transaction_id'] ?: '-';
  763. $data['data'][] = $new_list;
  764. }*/
  765. if (count($arr['goods']) > 0){
  766. foreach ($arr['goods'] as $i=>$g){
  767. if ($i == 0){
  768. $new_list = [];
  769. $new_list['key'] = $key+1;
  770. $new_list['order_no'] = $arr['order_no'];
  771. $new_list['create_time'] = $arr['create_time'];
  772. $new_list['state_text'] = $arr['state_text'];
  773. $new_list['goods_name'] = $arr['goods'][0]['goods_name'];
  774. $new_list['goods_no'] = $arr['goods'][0]['goods_no'];
  775. $new_list['goods_props'] = $arr['goods'][0]['specs']??'-';
  776. $new_list['supplier'] = $arr['goods'][0]['supplier'] ?: '-';
  777. $new_list['goods_price'] = $arr['goods'][0]['goods_price'];
  778. $new_list['total_num'] = $arr['goods'][0]['total_num'];
  779. $new_list['delivery_type'] = ($arr['delivery_type']==10)?'普通配送':'门店自提';
  780. $new_list['express_price'] = $arr['express_price'];
  781. $new_list['total_price'] = $arr['total_price'];
  782. $new_list['pay_price'] = $arr['pay_price'];
  783. $new_list['distributor_total_money'] = $arr['distributor_total_money'];
  784. $new_list['act_discount_money'] = ($arr['order_source'] == 10)?$arr['activity_discount_total_price']:($arr['order_source'] == 30?$arr['bargain_money']:($arr['order_source'] == 40?$arr['groupbuy_money']:0));
  785. $new_list['coupon_money'] = $arr['coupon_money'];
  786. $new_list['rice_card_money'] = $arr['rice_card_money'];
  787. $new_list['transaction_id'] = $arr['transaction_id'] ?: '-';
  788. $data['data'][] = $new_list;
  789. }else{
  790. $new_list = [];
  791. $new_list['key'] = '';
  792. $new_list['order_no'] = '';
  793. $new_list['create_time'] = '';
  794. $new_list['state_text'] = '';
  795. $new_list['goods_name'] = $g['goods_name'];
  796. $new_list['goods_no'] = $g['goods_no'];
  797. $new_list['goods_props'] = $g['specs']??'-';
  798. $new_list['supplier'] = $g['supplier'] ?: '-';
  799. $new_list['goods_price'] = $g['goods_price'];
  800. $new_list['total_num'] = $g['total_num'];
  801. $new_list['delivery_type'] = '';
  802. $new_list['express_price'] = '';
  803. $new_list['total_price'] = '';
  804. $new_list['pay_price'] = '';
  805. $new_list['distributor_total_money'] = '';
  806. $new_list['act_discount_money'] = '';
  807. $new_list['coupon_money'] = '';
  808. $new_list['rice_card_money'] = '';
  809. $new_list['transaction_id'] = '';
  810. $data['data'][] = $new_list;
  811. }
  812. }
  813. }
  814. }
  815. return $data;
  816. }
  817. /**
  818. * 导出全部订单列表
  819. * @param array $param
  820. * @return mixed
  821. * @author: zjwhust
  822. * @Time: 2022/6/28 15:41
  823. */
  824. public function orderExport(array $param)
  825. {
  826. $order_ids = $param['order_ids']??[];
  827. //$data['header'] = ['序号', '订单编号', '商品名称', '商品编码', '商品数量', '供应商名称', '收件人', '联系方式', '收货地址', '物流公司', '物流单号'];
  828. $data['header'] = ['序号', '订单编号', '商品信息','商品规格','数量','订单总额','实付金额','收件人', '买家信息','地址','手机号','配送方式', '支付状态','发货状态','订单状态', '下单时间'];
  829. $data['filename'] = '订单导出';
  830. $data['data'] = [];
  831. if(isset($order_ids)&&count($order_ids)>0){
  832. $list = $this->with(['goods'=>['image', 'provider', 'shop'], 'user.avatar', 'address'])
  833. ->whereIn('order_id',$order_ids)->order('order_id','desc')->select();
  834. }else{
  835. $p = $param['queryParam']??[];
  836. $slist = $this->getList( self::LIST_TYPE_ALL ,$p,100000);
  837. foreach($slist as $row){
  838. $order_ids[] = $row['order_id'];
  839. $list = $this->with(['goods'=>['image', 'provider', 'shop'], 'user.avatar', 'address'])
  840. ->whereIn('order_id',$order_ids)->order('order_id','desc')->select();
  841. }
  842. }
  843. //->where('total_num','=',1)//导出限制:商品件数>1 时 不支持批量导出,导出的数据中不含件数>1的商品
  844. foreach ($list as $key => $arr){
  845. $new_list['order_id'] = $arr['order_id'];//序号
  846. $new_list['order_no'] = (string)$arr['order_no'];//订单编号
  847. $new_list['goods_name'] = '';
  848. $new_list['goods_sku'] = '';
  849. $new_list['goods_num'] = '';
  850. $count = count($arr['goods'])-1;
  851. foreach ($arr['goods'] as $key2=>$good){
  852. $eol = PHP_EOL;
  853. if($key2==$count){
  854. $eol = '';
  855. }
  856. //商品信息
  857. $new_list['goods_name'] .= $good['goods_name']. $eol;
  858. //商品规格
  859. if($good['spec_type']==20){
  860. $new_list['goods_sku'] .= ($good['goods_prop']?$good['goods_prop'][0]['value']['name']:'--'). $eol;
  861. }else{
  862. $new_list['goods_sku'] .= ($good['specs']?$good['specs']:'--'). $eol;
  863. }
  864. //数量
  865. $new_list['goods_num'] .= $good['total_num']. $eol;
  866. }
  867. $new_list['total_price'] = $arr['total_price'];//订单总额
  868. $new_list['pay_price'] = $arr['pay_price']+$arr['rice_card_money'];//实付金额
  869. $address_name = $arr['address']['name']??'';
  870. $address_phone = $arr['address']['phone']??'';
  871. $new_list['address'] = $address_name;//收件人
  872. $new_list['nick_name'] = $arr['user']['nick_name']??'';//买家信息
  873. $new_list['detail_address'] = '';
  874. if($arr['address']){
  875. $new_list['detail_address'] = implode(" ",array_values($arr['address']['region'])).$arr['address']['detail'];
  876. }
  877. $new_list['address_phone'] = $address_phone;
  878. //配送方式
  879. if($arr['delivery_type']==10){
  880. $new_list['delivery_type'] = '普通配送';
  881. }else{
  882. $new_list['delivery_type'] = '门店自提';
  883. }
  884. //支付状态
  885. if($arr['pay_status']==10){
  886. $new_list['pay_status'] = '待付款';
  887. }else{
  888. $new_list['pay_status'] = '已付款';
  889. }
  890. // //发货状态
  891. if($arr['pay_status']==20 && $arr['delivery_status']==10){
  892. $new_list['delivery_status '] = '待发货';
  893. }elseif($arr['delivery_status']==20 && $arr['delivery_status']==20){
  894. $new_list['delivery_status'] = '已发货';
  895. }else{
  896. $new_list['delivery_status'] = '--';
  897. }
  898. // //订单状态'11':'待支付','12':'已付款待发货','13':'已付款待收货','20':'已取消','30':'已完成','40':'已关闭'
  899. $new_list['state_value'] = '--';
  900. switch ($arr['state_value']){
  901. case 11: $new_list['state_value'] = '待支付';break;
  902. case 12: $new_list['state_value'] = '已付款待发货';break;
  903. case 13: $new_list['state_value'] = '已付款待收货';break;
  904. case 20: $new_list['state_value'] = '已取消';break;
  905. case 30: $new_list['state_value'] = '已完成';break;
  906. case 40: $new_list['state_value'] = '已关闭';break;
  907. }
  908. $new_list['create_time'] = $arr['create_time'];
  909. $data['data'][] = $new_list;
  910. }
  911. return $data;
  912. }
  913. }