TradeStatisticServices.php 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\services\statistic;
  12. use app\services\BaseServices;
  13. use app\services\order\StoreOrderRefundServices;
  14. use app\services\other\export\ExportServices;
  15. use app\services\order\OtherOrderServices;
  16. use app\services\order\StoreOrderServices;
  17. use app\services\user\UserExtractServices;
  18. use app\services\user\UserMoneyServices;
  19. use app\services\user\UserRechargeServices;
  20. /**
  21. * Class TradeStatisticServices
  22. * @package app\services\statistic
  23. */
  24. class TradeStatisticServices extends BaseServices
  25. {
  26. public $_day = ['00时', '01时', '02时', '03时', '04时', '05时', '06时', '07时', '08时', '09时', '10时', '11时', '12时', '13时', '14时', '15时', '16时', '17时', '18时', '19时', '20时', '21时', '22时', '23时', '24时'];
  27. /**
  28. * 基本概况
  29. * @param $where
  30. * @return mixed
  31. */
  32. public function getTopLeftTrade($where)
  33. {
  34. //总交易额
  35. $selectType = "sum";
  36. $tradeTotalMoney = $this->tradeTotalMoney($where, $selectType);
  37. //交易曲线
  38. $selectType = "group";
  39. $hourTotalMoney = $this->tradeGroupMoney($where, $selectType);
  40. return ['total_money' => $tradeTotalMoney, 'curve' => $hourTotalMoney];
  41. }
  42. public function getTopRightOneTrade()
  43. {
  44. /** @var StoreOrderServices $orderService */
  45. $orderService = app()->make(StoreOrderServices::class);
  46. /** day订单数 */
  47. //今日订单数
  48. $orderCountWhere['is_del'] = 0;
  49. $orderCountWhere['paid'] = 1;
  50. $orderCountWhere['pid'] = 0;
  51. $orderCountWhere['timeKey'] = $this->TimeConvert("today");
  52. $todayOrderCount = $orderService->getOrderCountByWhere($orderCountWhere);
  53. //今日订单数曲线
  54. $todayHourOrderCount = $orderService->getOrderGroupCountByWhere($orderCountWhere);
  55. $todayHourOrderCount = $this->trendYdata($todayHourOrderCount, $orderCountWhere['timeKey']);
  56. //昨日订单数
  57. $yestodayWhere['is_del'] = 0;
  58. $yestodayWhere['paid'] = 1;
  59. $yestodayWhere['pid'] = 0;
  60. $yestodayWhere['timeKey'] = $this->TimeConvert("yestoday");
  61. $yesTodayOrderCount = $orderService->getOrderCountByWhere($yestodayWhere);
  62. //昨日订单曲线
  63. // $yestodayHourOrderCount = $orderService->getOrderGroupCountByWhere($yestodayWhere);
  64. // $yestodayHourOrderCount = $this->trendYdata($yestodayHourOrderCount, 'day');
  65. //订单数环比增长率
  66. $orderCountDayChain = $this->countRate($todayOrderCount, $yesTodayOrderCount);
  67. $data[] = [
  68. 'name' => "今日订单数",
  69. 'now_value' => $todayOrderCount,
  70. 'last_value' => $yesTodayOrderCount,
  71. 'rate' => $orderCountDayChain,
  72. 'curve' => $todayHourOrderCount
  73. ];
  74. /** day支付人数 */
  75. //今日支付人数
  76. $orderPeopleWhere['timeKey'] = $this->TimeConvert("today");
  77. $orderPeopleWhere['paid'] = 1;
  78. $orderPeopleWhere['pid'] = 0;
  79. $todayPayOrderPeople = count($orderService->getPayOrderPeopleByWhere($orderPeopleWhere));
  80. //今日支付人数曲线
  81. $todayHourOrderPeople = $orderService->getPayOrderGroupPeopleByWhere($orderPeopleWhere);
  82. $todayHourOrderPeople = $this->trendYdata($todayHourOrderPeople, $orderPeopleWhere['timeKey']);
  83. //昨日支付人数
  84. $yestodayOrderPeopleWhere['timeKey'] = $this->TimeConvert("yestoday");
  85. $yestodayOrderPeopleWhere['paid'] = 1;
  86. $yestodayPayOrderPeople = count($orderService->getPayOrderPeopleByWhere($yestodayOrderPeopleWhere));
  87. //昨日支付曲线
  88. // $yestodayHourOrderPeople = $orderService->getPayOrderGroupPeopleByWhere($yestodayOrderPeopleWhere);
  89. // $yestodayHourOrderPeople = $this->trendYdata($yestodayHourOrderPeople, 'day');
  90. //订单支付人数环比
  91. $orderPeopleDayChain = $this->countRate($todayPayOrderPeople, $yestodayPayOrderPeople);
  92. $data[] = [
  93. 'name' => "今日支付人数",
  94. 'now_value' => $todayPayOrderPeople,
  95. 'last_value' => $yestodayPayOrderPeople,
  96. 'rate' => $orderPeopleDayChain,
  97. 'curve' => $todayHourOrderPeople
  98. ];
  99. $new_data = [];
  100. foreach ($data as $k => $v) {
  101. $new_data['x'] = $v['curve']['x'];
  102. $new_data['series'][$k]['name'] = $v['name'];
  103. $new_data['series'][$k]['now_money'] = $v['now_value'];
  104. $new_data['series'][$k]['last_money'] = $v['last_value'];
  105. $new_data['series'][$k]['rate'] = $v['rate'];
  106. $new_data['series'][$k]['value'] = array_values($v['curve']['y']);
  107. }
  108. return $new_data;
  109. }
  110. public function getTopRightTwoTrade()
  111. {
  112. /** @var StoreOrderServices $orderService */
  113. $orderService = app()->make(StoreOrderServices::class);
  114. /** month订单数 */
  115. $monthOrderCountWhere['is_del'] = 0;
  116. $monthOrderCountWhere['paid'] = 1;
  117. $monthOrderCountWhere['pid'] = 0;
  118. $monthOrderCountWhere['timeKey'] = $this->TimeConvert("month");
  119. $monthOrderCount = $orderService->getOrderCountByWhere($monthOrderCountWhere);
  120. //本月订单数曲线
  121. $monthCurveOrderCount = $orderService->getOrderGroupCountByWhere($monthOrderCountWhere);
  122. $monthCurveOrderCount = $this->trendYdata($monthCurveOrderCount, $monthOrderCountWhere['timeKey']);
  123. //上月订单数
  124. $lastOrderCountWhere['timeKey'] = $this->TimeConvert("last_month");
  125. $lastOrderCountWhere['is_del'] = 0;
  126. $lastOrderCountWhere['paid'] = 1;
  127. $lastOrderCountWhere['pid'] = 0;
  128. $lastOrderCount = $orderService->getOrderCountByWhere($lastOrderCountWhere);
  129. //上月订单曲线
  130. // $lastCurveOrderCount = $orderService->getOrderGroupCountByWhere($lastOrderCountWhere);
  131. // $lastCurveOrderCount = $this->trendYdata($lastCurveOrderCount, 'month');
  132. //订单数环比增长率
  133. // $orderCountMonthChain = (($monthOrderCount - $lastOrderCount) / $lastOrderCount) * 100;
  134. $orderCountMonthChain = $this->countRate($monthOrderCount, $lastOrderCount);
  135. $data[] = [
  136. 'name' => "本月订单数",
  137. 'now_value' => $monthOrderCount,
  138. 'last_value' => $lastOrderCount,
  139. 'rate' => $orderCountMonthChain,
  140. 'curve' => $monthCurveOrderCount
  141. ];
  142. /** month下单人数 */
  143. //本月支付人数
  144. $monthOrderPeopleWhere['timeKey'] = $this->TimeConvert("month");;
  145. $monthOrderPeopleWhere['paid'] = 1;
  146. $monthPayOrderPeople = count($orderService->getPayOrderPeopleByWhere($monthOrderPeopleWhere));
  147. //本月支付人数曲线
  148. $monthCurveOrderPeople = $orderService->getPayOrderGroupPeopleByWhere($monthOrderPeopleWhere);
  149. $monthCurveOrderPeople = $this->trendYdata($monthCurveOrderPeople, $monthOrderPeopleWhere['timeKey']);
  150. //上月支付人数
  151. $lastOrderPeopleWhere['timeKey'] = $this->TimeConvert("last_month");
  152. $lastOrderPeopleWhere['paid'] = 1;
  153. $lastPayOrderPeople = count($orderService->getPayOrderPeopleByWhere($lastOrderPeopleWhere));
  154. //上月支付曲线
  155. // $lastCurveOrderPeople = $orderService->getPayOrderGroupPeopleByWhere($lastOrderPeopleWhere);
  156. // $lastCurveOrderPeople = $this->trendYdata($lastCurveOrderPeople, 'month');
  157. //订单支付人数环比
  158. $orderPeopleDayChain = $this->countRate($monthPayOrderPeople, $lastPayOrderPeople);
  159. $data[] = [
  160. 'name' => "本月支付人数",
  161. 'now_value' => $monthPayOrderPeople,
  162. 'last_value' => $lastPayOrderPeople,
  163. 'rate' => $orderPeopleDayChain,
  164. 'curve' => $monthCurveOrderPeople
  165. ];
  166. $new_data = [];
  167. foreach ($data as $k => $v) {
  168. $new_data[$k]['name'] = $v['name'];
  169. $new_data[$k]['now_money'] = $v['now_value'];
  170. $new_data[$k]['last_money'] = $v['last_value'];
  171. $new_data[$k]['rate'] = $v['rate'];
  172. $new_data[$k]['value'] = $v['curve']['y'];
  173. }
  174. return $new_data;
  175. }
  176. /**
  177. * 交易总额
  178. * @param $where
  179. * @param $selectType
  180. * @return array|float|int|mixed
  181. */
  182. public function tradeTotalMoney($where, $selectType, $isNum = false)
  183. {
  184. /** 收入营业额 */
  185. //商品订单收入
  186. $inOrderMoney = $this->getOrderTotalMoney($where, $selectType, "", $isNum);
  187. //用户充值收入
  188. $inRechargeMoneyHome = $this->getRechargeTotalMoney($where, $selectType, "", $isNum);
  189. $inrechgeMoneyAdmin = $this->getBillYeTotalMoney($where, $selectType, '', $isNum);
  190. $inRechargeMoney = bcadd($inRechargeMoneyHome, $inrechgeMoneyAdmin, 2);
  191. //购买会员收入
  192. $inMemberMoney = $this->getMemberTotalMoney($where, $selectType, "", $isNum);
  193. //线下收款收入
  194. $inOfflineMoney = $this->getOfflineTotalMoney($where, $selectType, "", $isNum);
  195. //总交易额
  196. $inTotalMoney = bcadd(bcadd($inOrderMoney, $inRechargeMoney, 2), bcadd($inMemberMoney, $inOfflineMoney, 2), 2);/* - $outExtractUserMoney*/
  197. return $inTotalMoney;
  198. }
  199. /**
  200. * 交易额曲线图
  201. * @param $where
  202. * @param $selectType
  203. * @return array
  204. */
  205. public function tradeGroupMoney($where, $selectType)
  206. {
  207. //商品订单收入
  208. $orderGroup = "add_time";
  209. $OrderMoney = $this->getOrderTotalMoney($where, $selectType, $orderGroup);
  210. //用户充值收入
  211. $rechargeGroup = "add_time";
  212. $RechargeMoneyHome = $this->getRechargeTotalMoney($where, $selectType, $rechargeGroup);
  213. $RechargeMoneyAdmin = $this->getBillYeTotalMoney($where, $selectType, $rechargeGroup);
  214. $RechargeMoney = $this->totalArrData([$RechargeMoneyHome, $RechargeMoneyAdmin]);
  215. //购买会员收入
  216. $memberGroup = "add_time";
  217. $MemberMoney = $this->getMemberTotalMoney($where, $selectType, $memberGroup);
  218. //线下收款收入
  219. $offlineGroup = "add_time";
  220. $OfflineMoney = $this->getOfflineTotalMoney($where, $selectType, $offlineGroup);
  221. return $this->totalArrData([$OrderMoney, $RechargeMoney, $MemberMoney, $OfflineMoney]);
  222. }
  223. /**
  224. * 底部数据
  225. * @param $where
  226. * @return array
  227. * @throws \Exception
  228. */
  229. public function getBottomTrade($where)
  230. {
  231. if (!$where['data']) {
  232. $where['time'] = ['start_time' => date('Y-m-d 00:00:00', time()), "end_time" => date('Y-m-d 23:59:59', time())];
  233. } else {
  234. $time = explode("-", $where['data']);
  235. $where['time'] = ['start_time' => date('Y-m-d 00:00:00', strtotime($time[0])), "end_time" => date('Y-m-d 23:59:59', strtotime($time[1]))];
  236. }
  237. unset($where['data']);
  238. /** @var ExportServices $exportService */
  239. $exportService = app()->make(ExportServices::class);
  240. $chainTime = $this->chainTime($where['time']);
  241. $isNum = false;
  242. if ($chainTime == "other") $isNum = true;
  243. $dateWhere['time'] = $isNum ? $where['time'] : $chainTime;
  244. $topData = array();
  245. $Chain = array();
  246. /** 商品支付金额 */
  247. $OrderMoney = $this->getOrderTotalMoney($where, "sum");
  248. $lastOrderMoney = $this->getOrderTotalMoney($dateWhere, "sum", "", $isNum);
  249. $OrderCurve = $this->getOrderTotalMoney($where, "group", "add_time");
  250. $OrderChain = $this->countRate($OrderMoney, $lastOrderMoney);
  251. $topData[1] = [
  252. 'title' => '商品支付金额',
  253. 'desc' => '选定条件下,用户购买商品的实际支付金额,包括微信支付、余额支付、支付宝支付、线下支付金额(拼团商品在成团之后计入,线下支付订单在后台确认支付后计入)',
  254. 'total_money' => $OrderMoney,
  255. 'rate' => $OrderChain,
  256. 'value' => $OrderCurve['y'],
  257. 'type' => 1,
  258. 'sign' => 'goods',
  259. ];
  260. $Chain['goods'] = $OrderCurve;
  261. /** 购买会员金额 */
  262. $memberMoney = $this->getMemberTotalMoney($where, 'sum');
  263. $lastMemberMoney = $this->getMemberTotalMoney($dateWhere, 'sum', "", $isNum);
  264. $memberCurve = $this->getMemberTotalMoney($where, 'group', "pay_time");
  265. $MemberChain = $this->countRate($memberMoney, $lastMemberMoney);
  266. $topData[2] = [
  267. 'title' => '购买会员金额',
  268. 'desc' => '选定条件下,用户成功购买付费会员的金额',
  269. 'total_money' => $memberMoney,
  270. 'rate' => $MemberChain,
  271. 'value' => $memberCurve['y'],
  272. 'type' => 1,
  273. 'sign' => 'member',
  274. ];
  275. $Chain['member'] = $memberCurve;
  276. /** 充值金额 */
  277. $rechgeMoneyHome = $this->getRechargeTotalMoney($where, 'sum');
  278. $rechgeMoneyAdmin = $this->getBillYeTotalMoney($where, 'sum');
  279. $rechgeMoneyTotal = bcadd($rechgeMoneyHome, $rechgeMoneyAdmin, 2);
  280. $lastRechgeMoneyHome = $this->getRechargeTotalMoney($dateWhere, 'sum', "", $isNum);
  281. $lastRechgeMoneyAdmin = $this->getBillYeTotalMoney($dateWhere, 'sum', "", $isNum);
  282. $lastRechgeMoneyTotal = bcadd($lastRechgeMoneyHome, $lastRechgeMoneyAdmin, 2);
  283. $RechgeHomeCurve = $this->getRechargeTotalMoney($where, 'group', "pay_time");
  284. $RechgeAdminCurve = $this->getBillYeTotalMoney($where, 'group', "add_time");
  285. $RechgeTotalCurve = $this->totalArrData([$RechgeHomeCurve, $RechgeAdminCurve]);
  286. $RechgeChain = $this->countRate($rechgeMoneyTotal, $lastRechgeMoneyTotal);
  287. $topData[3] = [
  288. 'title' => '充值金额',
  289. 'desc' => '选定条件下,用户成功充值的金额',
  290. 'total_money' => $rechgeMoneyTotal,
  291. 'rate' => $RechgeChain,
  292. 'value' => $RechgeTotalCurve['y'],
  293. 'type' => 1,
  294. 'sign' => 'rechge',
  295. ];
  296. $Chain['rechage'] = $RechgeTotalCurve;
  297. /** 线下收银 */
  298. $offlineMoney = $this->getOfflineTotalMoney($where, 'sum');
  299. $lastOfflineMoney = $this->getOfflineTotalMoney($dateWhere, 'sum', "", $isNum);
  300. $offlineCurve = $this->getOfflineTotalMoney($where, 'group', "pay_time");
  301. $offlineChain = $this->countRate($offlineMoney, $lastOfflineMoney);
  302. $topData[4] = [
  303. 'title' => '线下收银金额',
  304. 'desc' => '选定条件下,用户在线下扫码支付的金额',
  305. 'total_money' => $offlineMoney,
  306. 'rate' => $offlineChain,
  307. 'value' => $offlineCurve['y'],
  308. 'type' => 0,
  309. 'sign' => 'offline',
  310. ];
  311. $Chain['offline'] = $offlineCurve;
  312. /** 支出*/
  313. //余额支付商品
  314. $outYeOrderMoney = $this->getOrderTotalMoney(['pay_type' => "yue", 'time' => $where['time']], 'sum');
  315. $lastOutYeOrderMoney = $this->getOrderTotalMoney(['pay_type' => "yue", 'time' => $dateWhere['time']], 'sum', "", $isNum);
  316. $outYeOrderCurve = $this->getOrderTotalMoney(['pay_type' => "yue", 'time' => $where['time']], 'group', 'pay_time');
  317. $outYeOrderChain = $this->countRate($outYeOrderMoney, $lastOutYeOrderMoney);
  318. //余额购买会员
  319. $outYeMemberMoney = $this->getMemberTotalMoney(['pay_type' => "yue", 'time' => $where['time']], 'sum');
  320. $lastOutYeMemberMoney = $this->getMemberTotalMoney(['pay_type' => "yue", 'time' => $dateWhere['time']], 'sum', "", $isNum);
  321. $outYeMemberCurve = $this->getMemberTotalMoney(['pay_type' => "yue", 'time' => $where['time']], 'group', "pay_time");
  322. $outYeMemberChain = $this->countRate($outYeMemberMoney, $lastOutYeMemberMoney);
  323. //余额支付
  324. $outYeMoney = bcadd($outYeOrderMoney, $outYeMemberMoney, 2);
  325. $lastOutYeMoney = bcadd($lastOutYeOrderMoney, $lastOutYeMemberMoney, 2);
  326. $outYeCurve = $this->totalArrData([$outYeOrderCurve, $outYeMemberCurve]);
  327. $outYeChain = $this->countRate($outYeOrderChain, $outYeMemberChain);
  328. $topData[6] = [
  329. 'title' => '余额支付金额',
  330. 'desc' => '用户下单时使用余额实际支付的金额',
  331. 'total_money' => $outYeMoney,
  332. 'rate' => $outYeChain,
  333. 'value' => $outYeCurve['y'],
  334. 'type' => 0,
  335. 'sign' => 'yue',
  336. ];
  337. $Chain['out_ye'] = $outYeCurve;
  338. //支付佣金金额
  339. $outExtractMoney = $this->getExtractTotalMoney($where, 'sum');
  340. $lastOutExtractMoney = $this->getExtractTotalMoney($dateWhere, 'sum', "", $isNum);
  341. $OutExtractCurve = $this->getExtractTotalMoney($where, 'group', "add_time");
  342. $OutExtractChain = $this->countRate($outExtractMoney, $lastOutExtractMoney);
  343. $topData[7] = [
  344. 'title' => '支付佣金金额',
  345. 'desc' => '后台给推广员支付的推广佣金,以实际支付为准',
  346. 'total_money' => $outExtractMoney,
  347. 'rate' => $OutExtractChain,
  348. 'value' => $OutExtractCurve['y'],
  349. 'type' => 0,
  350. 'sign' => 'yong',
  351. ];
  352. $Chain['extract'] = $OutExtractCurve;
  353. //商品退款金额
  354. $outOrderRefund = $this->getOrderRefundTotalMoney(['refund_type' => 6, 'time' => $where['time']], 'sum');
  355. $lastOutOrderRefund = $this->getOrderRefundTotalMoney(['refund_type' => 6, 'time' => $dateWhere['time']], 'sum', "", $isNum);
  356. $outOrderRefundCurve = $this->getOrderRefundTotalMoney(['refund_type' => 6, 'time' => $where['time']], 'group', 'add_time');
  357. $orderRefundChain = $this->countRate($outOrderRefund, $lastOutOrderRefund);
  358. $topData[8] = [
  359. 'title' => '商品退款金额',
  360. 'desc' => '用户成功退款的商品金额',
  361. 'total_money' => $outOrderRefund,
  362. 'rate' => $orderRefundChain,
  363. 'value' => $outOrderRefundCurve['y'],
  364. 'type' => 0,
  365. 'sign' => 'refund',
  366. ];
  367. $Chain['refund'] = $outOrderRefundCurve;
  368. //支出金额
  369. $outTotalMoney = bcadd(bcadd($outYeMoney, $outExtractMoney, 2), $outOrderRefund, 2);
  370. $lastOutTotalMoney = bcadd(bcadd($lastOutYeMoney, $lastOutExtractMoney, 2), $lastOutOrderRefund, 2);
  371. $outTotalCurve = $this->totalArrData([$outYeCurve, $OutExtractCurve, $outOrderRefundCurve]);
  372. $outTotalChain = $this->countRate($outTotalMoney, $lastOutTotalMoney);
  373. $topData[5] = [
  374. 'title' => '支出金额',
  375. 'desc' => '余额支付金额、支付佣金金额、商品退款金额',
  376. 'total_money' => $outTotalMoney,
  377. 'rate' => $outTotalChain,
  378. 'value' => $outTotalCurve['y'],
  379. 'type' => 1,
  380. 'sign' => 'out',
  381. ];
  382. $Chain['out'] = $outTotalCurve;
  383. // /** 交易毛利金额*/
  384. // $jiaoyiMoney = $this->tradeTotalMoney($where, "sum");
  385. //
  386. // $jiaoyiMoney = bcsub($jiaoyiMoney, $outTotalMoney, 2);
  387. // $lastJiaoyiMoney = $this->tradeTotalMoney($dateWhere, "sum", $isNum);
  388. // $lastJiaoyiMoney = bcsub($lastJiaoyiMoney, $lastOutTotalMoney, 2);
  389. // $jiaoyiCurve = $this->tradeGroupMoney($where, "group");
  390. // $jiaoyiCurve = $this->subdutionArrData($jiaoyiCurve, $outTotalCurve);
  391. // $jiaoyiChain = $this->countRate($jiaoyiMoney, $lastJiaoyiMoney);
  392. // $topData[1] = [
  393. // 'title' => '交易毛利金额',
  394. // 'desc' => '交易毛利金额 = 营业额 - 支出金额',
  395. // 'total_money' => $jiaoyiMoney,
  396. // 'rate' => $jiaoyiChain,
  397. // 'value' => $jiaoyiCurve['y'],
  398. // 'type' => 1,
  399. // 'sign' => 'jiaoyi',
  400. // ];
  401. // $Chain['jiaoyi'] = $jiaoyiCurve;
  402. /** @var 营业额 $inTotalMoney */
  403. $inTotalMoney = $this->tradeTotalMoney($where, "sum");
  404. $lastInTotalMoney = $this->tradeTotalMoney($dateWhere, "sum", $isNum);
  405. $inTotalCurve = $this->tradeGroupMoney($where, "group");
  406. $inTotalChain = $this->countRate($inTotalMoney, $lastInTotalMoney);
  407. $topData[0] = [
  408. 'title' => '营业额',
  409. 'desc' => '商品支付金额、充值金额、购买付费会员金额、线下收银金额',
  410. 'total_money' => $inTotalMoney,
  411. 'rate' => $inTotalChain,
  412. 'value' => $inTotalCurve['y'],
  413. 'type' => 1,
  414. 'sign' => 'in',
  415. ];
  416. ksort($topData);
  417. $data = [];
  418. foreach ($topData as $k => $v) {
  419. $data['x'] = $Chain['out']['x'];
  420. $data['series'][$k]['name'] = $v['title'];
  421. $data['series'][$k]['desc'] = $v['desc'];
  422. $data['series'][$k]['money'] = $v['total_money'];
  423. $data['series'][$k]['type'] = $v['type'];
  424. $data['series'][$k]['rate'] = $v['rate'];
  425. $data['series'][$k]['value'] = array_values($v['value']);
  426. }
  427. $export = $exportService->tradeData($data, '交易统计', 2);
  428. $data['export'] = $export[0];
  429. return $data;
  430. }
  431. /**
  432. * 多个数组相加
  433. * @param array $arr
  434. * @return array|false
  435. */
  436. public function totalArrData(array $arr)
  437. {
  438. if (!$arr || !is_array($arr)) return false;
  439. $item = array();
  440. $y = array_column($arr, "y");
  441. $x = array_column($arr, "x")[0];
  442. foreach ($y as $key => $value) {
  443. foreach ($value as $k => $v) {
  444. if (isset($item[$k])) {
  445. $item[$k] = bcadd($item[$k], $v, 2);
  446. } else {
  447. $item[$k] = $v;
  448. }
  449. }
  450. }
  451. return ['x' => $x, 'y' => $item];
  452. }
  453. /**
  454. * 数组相减
  455. * @param array $arr1
  456. * @param array $arr2
  457. * @return array
  458. */
  459. public function subdutionArrData(array $arr1, array $arr2)
  460. {
  461. $item = array();
  462. foreach ($arr1['y'] as $key => $value) {
  463. $item['y'][$key] = bcsub($value, $arr2['y'][$key], 2);
  464. }
  465. $item['x'] = $arr1['x'];
  466. return $item;
  467. }
  468. /**
  469. * 搜索时间转换
  470. * @param $timeKey
  471. * @param false $isNum
  472. * @return array
  473. * @throws \Exception
  474. */
  475. public function TimeConvert($timeKey, $isNum = false)
  476. {
  477. switch ($timeKey) {
  478. case "today" :
  479. $data['start_time'] = date('Y-m-d 00:00:00', time());
  480. $data['end_time'] = date('Y-m-d 23:59:59', time());
  481. $data['days'] = 1;
  482. break;
  483. case "yestoday" :
  484. $data['start_time'] = date('Y-m-d 00:00:00', strtotime('-1 day'));
  485. $data['end_time'] = date('Y-m-d 23:59:59', strtotime('-1 day'));
  486. $data['days'] = 1;
  487. break;
  488. case "last_month" :
  489. $data['start_time'] = date('Y-m-01 00:00:00', strtotime('-1 month'));
  490. $data['end_time'] = date('Y-m-t 23:59:59', strtotime('-1 month'));
  491. $data['days'] = 30;
  492. break;
  493. case "month" :
  494. $data['start_time'] = $month_start_time = date('Y-m-01 00:00:00', strtotime(date("Y-m-d")));
  495. $data['end_time'] = date('Y-m-d 23:59:59', strtotime("$month_start_time +1 month -1 day"));
  496. $data['days'] = 30;
  497. break;
  498. case "year" :
  499. $data['start_time'] = date('Y-01-01 00:00:00', time());
  500. $data['end_time'] = date('Y-12-t 23:59:59', time());
  501. $data['days'] = 365;
  502. break;
  503. case "last_year" :
  504. $data['start_time'] = date('Y-01-01 00:00:00', strtotime('-1 year'));
  505. $data['end_time'] = date('Y-12-t 23:59:59', strtotime('-1 year'));
  506. $data['days'] = 365;
  507. break;
  508. case 30 :
  509. case 15 :
  510. case 7 :
  511. if (!$isNum) {
  512. $data['start_time'] = date("Y-m-d 00:00:00", strtotime("-$timeKey day"));
  513. $data['end_time'] = date('Y-m-d 23:59:59', time());
  514. $data['days'] = $timeKey;
  515. } else {
  516. $day = $timeKey * 2;
  517. $data['start_time'] = date("Y-m-d 00:00:00", strtotime("-$day day"));
  518. $data['end_time'] = date("Y-m-d 23:59:59", strtotime("-$timeKey day"));
  519. $data['days'] = $timeKey;
  520. }
  521. break;
  522. default:
  523. $datetime_start = new \DateTime($timeKey['start_time']);
  524. $datetime_end = new \DateTime($timeKey['end_time']);
  525. $days = $datetime_start->diff($datetime_end)->days;
  526. $days = $days > 0 ? $days : 1;
  527. if (!$isNum) {
  528. $data['start_time'] = $timeKey['start_time'];
  529. $data['end_time'] = $timeKey['end_time'];
  530. $data['days'] = $days;
  531. } else {
  532. $data['start_time'] = date("Y-m-d 00:00:00", strtotime("-$days day"));
  533. $data['end_time'] = $timeKey['start_time'];
  534. $data['days'] = $days;
  535. }
  536. }
  537. return $data;
  538. }
  539. /**
  540. * 获取订单退款
  541. * @param $where
  542. * @param string $selectType
  543. * @param string $group
  544. * @param bool $isNum
  545. * @return array|float|int
  546. * @throws \Exception
  547. */
  548. public function getOrderRefundTotalMoney($where, string $selectType, string $group = '', bool $isNum = false)
  549. {
  550. $orderSumField = isset($where['refund_type']) ? "refunded_price" : "refund_price";
  551. $whereOrderMoner['refund_type'] = isset($where['refund_type']) ? $where['refund_type'] : 6;
  552. $whereOrderMoner['is_cancel'] = 0;
  553. $whereOrderMoner['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  554. /** @var StoreOrderRefundServices $storeOrderRefundServices */
  555. $storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
  556. $totalMoney = $storeOrderRefundServices->getOrderRefundMoneyByWhere($whereOrderMoner, $orderSumField, $selectType, $group);
  557. if ($group) {
  558. $totalMoney = $this->trendYdata($totalMoney, $whereOrderMoner['timeKey']);
  559. }
  560. return $totalMoney;
  561. }
  562. /**
  563. * 获取商品营收
  564. * @param $where
  565. * @param string $selectType
  566. * @param string $group
  567. * @param bool $isNum
  568. * @return array|float|int
  569. * @throws \Exception
  570. */
  571. public function getOrderTotalMoney($where, string $selectType, string $group = "", bool $isNum = false)
  572. {
  573. /** 普通商品订单支付金额 */
  574. /** @var StoreOrderServices $storeOrderService */
  575. $storeOrderService = app()->make(StoreOrderServices::class);
  576. $orderSumField = isset($where['refund_status']) ? "refund_price" : "pay_price";
  577. $whereOrderMoner['refund_status'] = isset($where['refund_status']) ? $where['refund_status'] : 0;
  578. $whereOrderMoner['paid'] = 1;
  579. $whereOrderMoner['pid'] = 0;
  580. if (isset($where['pay_type'])) {
  581. $whereOrderMoner['pay_type'] = $where['pay_type'];
  582. }
  583. $whereOrderMoner['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  584. $totalMoney = $storeOrderService->getOrderMoneyByWhere($whereOrderMoner, $orderSumField, $selectType, $group);
  585. if ($group) {
  586. $totalMoney = $this->trendYdata($totalMoney, $whereOrderMoner['timeKey']);
  587. }
  588. return $totalMoney;
  589. }
  590. /**
  591. * 支付佣金
  592. * @param $where
  593. * @param string $selectType
  594. * @param string $group
  595. * @param bool $isNum
  596. * @return array|float|mixed
  597. * @throws \Exception
  598. */
  599. public function getExtractTotalMoney($where, string $selectType, string $group = "", bool $isNum = false)
  600. {
  601. /** 普通商品订单支付金额 */
  602. /** @var UserExtractServices $extractService */
  603. $extractService = app()->make(UserExtractServices::class);
  604. $orderSumField = "extract_price";
  605. $whereData['status'] = 1;
  606. $whereData['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  607. $totalMoney = $extractService->getOutMoneyByWhere($whereData, $orderSumField, $selectType, $group);
  608. if ($group) {
  609. $totalMoney = $this->trendYdata($totalMoney, $whereData['timeKey']);
  610. }
  611. return $totalMoney;
  612. }
  613. /**
  614. * 获取用户充值营收
  615. * @param array $where
  616. * @param string $selectType
  617. * @param string $group
  618. * @param bool $isNum
  619. * @return array|float|int
  620. * @throws \Exception
  621. */
  622. public function getRechargeTotalMoney(array $where, string $selectType, string $group = "", bool $isNum = false)
  623. {
  624. /** @var UserRechargeServices $userRechageService */
  625. $userRechageService = app()->make(UserRechargeServices::class);
  626. $rechargeSumField = "price";
  627. $whereInRecharge['paid'] = 1;
  628. $whereInRecharge['refund_price'] = '0.00';
  629. $whereInRecharge['no_recharge_type'] = 'system';
  630. $whereInRecharge['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  631. $whereInRecharge['store_id'] = 0;
  632. $totalMoney = $userRechageService->getRechargeMoneyByWhere($whereInRecharge, $rechargeSumField, $selectType, $group);
  633. if ($group) {
  634. $totalMoney = $this->trendYdata($totalMoney, $whereInRecharge['timeKey']);
  635. }
  636. return $totalMoney;
  637. }
  638. /**
  639. * 后台手动充值
  640. * @param array $where
  641. * @param string $selectType
  642. * @param string $group
  643. * @param bool $isNum
  644. * @return array|float|int
  645. * @throws \Exception
  646. */
  647. public function getBillYeTotalMoney(array $where, string $selectType, string $group = "", bool $isNum = false)
  648. {
  649. /** 后台用户充值金额 */
  650. $rechargeSumField = "number";
  651. $whereInRecharge['pm'] = 1;
  652. $whereInRecharge['type'] = 'system_add';
  653. $whereInRecharge['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  654. $whereInRecharge['store_id'] = 0;
  655. /** @var UserMoneyServices $userMoneyServices */
  656. $userMoneyServices = app()->make(UserMoneyServices::class);
  657. $totalMoney = $userMoneyServices->getRechargeMoneyByWhere($whereInRecharge, $rechargeSumField, $selectType, $group);
  658. if ($group) {
  659. $totalMoney = $this->trendYdata($totalMoney, $whereInRecharge['timeKey']);
  660. }
  661. return $totalMoney;
  662. }
  663. /**
  664. * 购买会员总额
  665. * @param array $where
  666. * @param string $selectType
  667. * @param string $group
  668. * @param bool $isNum
  669. * @return array|mixed
  670. * @throws \Exception
  671. */
  672. public function getMemberTotalMoney(array $where, string $selectType, string $group = "", bool $isNum = false)
  673. {
  674. /** 购买会员 */
  675. /** @var OtherOrderServices $otherOrderService */
  676. $otherOrderService = app()->make(OtherOrderServices::class);
  677. $memberSumField = "pay_price";
  678. $whereInMember['type'] = 1;
  679. $whereInMember['paid'] = 1;
  680. $whereInMember['store_id'] = 0;
  681. if (isset($where['pay_type'])) {
  682. $whereInMember['pay_type'] = $where['pay_type'];
  683. } else {
  684. //$whereInMember['pay_type_no'] = 'yue';
  685. }
  686. $whereInMember['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  687. $totalMoney = $otherOrderService->getMemberMoneyByWhere($whereInMember, $memberSumField, $selectType, $group);
  688. if ($group) {
  689. $totalMoney = $this->trendYdata($totalMoney, $whereInMember['timeKey']);
  690. }
  691. return $totalMoney;
  692. }
  693. /**
  694. * 线下付款总额
  695. * @param array $where
  696. * @param string $selectType
  697. * @param string $group
  698. * @param bool $isNum
  699. * @return array|mixed
  700. * @throws \Exception
  701. */
  702. public function getOfflineTotalMoney(array $where, string $selectType, string $group = "", bool $isNum = false)
  703. {
  704. /** 线下付款总额 */
  705. /** @var OtherOrderServices $otherOrderService */
  706. $otherOrderService = app()->make(OtherOrderServices::class);
  707. $offlineSumField = "pay_price";
  708. $whereOffline['type'] = 3;
  709. $whereOffline['paid'] = 1;
  710. $whereOffline['store_id'] = 0;
  711. // $whereOffline['pay_type_no'] = 'yue';
  712. $whereOffline['timeKey'] = $this->TimeConvert($where['time'], $isNum);
  713. $totalMoney = $otherOrderService->getMemberMoneyByWhere($whereOffline, $offlineSumField, $selectType, $group);
  714. if ($group) {
  715. $totalMoney = $this->trendYdata($totalMoney, $whereOffline['timeKey']);
  716. }
  717. return $totalMoney;
  718. }
  719. /**
  720. * 处理Y坐标数据
  721. * @param array $data
  722. * @param array $timeKey
  723. * @return array
  724. * @throws \Exception
  725. */
  726. public function trendYdata(array $data, array $timeKey)
  727. {
  728. $hourMoney = array();
  729. $timeData = array();
  730. //获取日期之间的天数
  731. $getDayRange = function ($date, $timeKey) {
  732. $datearr = [];
  733. $stime = strtotime($timeKey['start_time']);
  734. $etime = strtotime($timeKey['end_time']);
  735. while ($stime <= $etime) {
  736. $datearr['x'][] = date($date, $stime);
  737. $datearr['y'][] = date($date, $stime);
  738. $stime = $stime + 86400;
  739. }
  740. return $datearr;
  741. };
  742. //获取日期之间的月份
  743. $getMonthRange = function ($date, $timeKey) {
  744. $datearr = [];
  745. $stime = date('Y-m-d', strtotime($timeKey['start_time']));
  746. $etime = date('Y-m-d', strtotime($timeKey['end_time']));
  747. $start = new \DateTime($stime);
  748. $end = new \DateTime($etime);
  749. $interval = \DateInterval::createFromDateString('1 month');
  750. $period = new \DatePeriod($start, $interval, $end);
  751. foreach ($period as $dt) {
  752. $datearr['x'][] = $dt->format($date);
  753. $datearr['y'][] = $dt->format($date);
  754. }
  755. return $datearr;
  756. };
  757. if ($timeKey['days'] == 1) {
  758. for ($i = 0; $i <= 24; $i++) {
  759. $timeData['x'][] = (string)($i < 10 ? ('0' . $i) : $i);
  760. $timeData['y'][] = $i < 10 ? ('0' . $i) : $i;
  761. //$timeData['y'][] = $i < 10 ? ('0' . $i . ":00") : $i . ":00";
  762. //$timeData['x'][] = $i < 10 ? ('0' . $i . ":00") : $i . ":00";
  763. }
  764. } elseif ($timeKey['days'] == 30) {
  765. $timeData = $getDayRange('Y-m-d', $timeKey);
  766. } elseif ($timeKey['days'] == 365) {
  767. $timeData = $getMonthRange('Y-m', $timeKey);
  768. } elseif ($timeKey['days'] > 1 && $timeKey['days'] < 30) {
  769. $timeData = $getDayRange('Y-m-d', $timeKey);
  770. } elseif ($timeKey['days'] > 30 && $timeKey['days'] < 365) {
  771. $timeData = $getMonthRange('Y-m', $timeKey);
  772. }
  773. if ($data) {
  774. $hourMoney = array_column($data, 'number', 'time');
  775. }
  776. $y = array();
  777. foreach ($timeData['y'] as $k => $v) {
  778. if (array_key_exists($v, $hourMoney)) {
  779. $y[$v] = $hourMoney[$v];
  780. } else {
  781. $y[$v] = 0;
  782. }
  783. }
  784. return ['x' => $timeData['x'], 'y' => $y];
  785. }
  786. /**
  787. * 计算环比增长率
  788. * @param $nowValue
  789. * @param $lastValue
  790. * @return float|int|string
  791. */
  792. public function countRate($nowValue, $lastValue)
  793. {
  794. if ($lastValue == 0 && $nowValue == 0) return 0;
  795. if ($lastValue == 0) return round(bcmul(bcdiv($nowValue, 1, 4), 100, 2), 2);
  796. if ($nowValue == 0) return -100;
  797. return bcmul(bcdiv((bcsub($nowValue, $lastValue, 2)), $lastValue, 2), 100, 2);
  798. }
  799. /**
  800. * 获取环比时间类型
  801. * @param $timeKey
  802. * @return string
  803. */
  804. public function chainTime($timeKey)
  805. {
  806. switch ($timeKey) {
  807. case "today" :
  808. return "yestoday";
  809. case "month" :
  810. return "last_month";
  811. case "year" :
  812. return "last_year";
  813. default :
  814. return "other";
  815. }
  816. }
  817. }