ShareFinancialListForm.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\models;
  8. use app\models\BonusPoolDetail;
  9. use app\models\Level;
  10. use app\models\LevelOrder;
  11. use app\models\MdProfit;
  12. use app\models\Order;
  13. use app\models\OrderDetail;
  14. use app\models\OrderTransit;
  15. use app\models\SaasUser;
  16. use app\models\ShareDetail;
  17. use app\models\SharingReceiver;
  18. use app\models\User;
  19. use app\models\UserShareMoney;
  20. use Spatie\SimpleExcel\SimpleExcelWriter;
  21. use yii\base\Model;
  22. class ShareFinancialListForm extends Model
  23. {
  24. public $status; //状态 1全部 2待收货 3已收货 4已完成
  25. public $order_no;//订单号
  26. public $user_name;//用户名称
  27. public $order_start_time;//订单开始时间
  28. public $order_end_time;//订单结束时间
  29. public $confirm_start_time;//收货开始时间
  30. public $confirm_end_time;//收货结束时间
  31. public $isExport;//是否为导出
  32. public $has_refund;
  33. public function rules()
  34. {
  35. return [
  36. [['order_no'], 'trim'],
  37. [['status', 'isExport'], 'integer'],
  38. [['order_no', 'user_name', 'order_start_time', 'order_end_time', 'confirm_start_time', 'confirm_end_time'], 'string'],
  39. [['has_refund'], 'safe'],
  40. ];
  41. }
  42. /*
  43. * 财务列表
  44. */
  45. public function financialList() {
  46. try {
  47. $field = [
  48. 'total_price', 'pay_price', 'share_money', 'md_profit', 'share_detail_sub', 'share_detail', 'sharing_receiver'
  49. //订单总额, 实际付款总额, 分销支出总额, 门店支出总额, 极差支出总额, 股东分红总额, 平台抽成总额
  50. ];
  51. $data = [];
  52. $all_data = [];
  53. if (!$this->isExport) {
  54. //获取统计数据
  55. foreach ($field as $index => $value) {
  56. $result = $this->getSql($value);
  57. if ($result['code'] !== 0) {
  58. return $result;
  59. }
  60. $sql = $result['data'];
  61. if (in_array($value, ['md_profit', 'share_detail_sub', 'share_detail'])) {
  62. $data_sub = \Yii::$app->db->createCommand($sql)->queryAll();
  63. $data_id = array_column($data_sub, 'md_profit');
  64. $data_id = array_diff($data_id, ['0']);
  65. if ($value === 'md_profit') {
  66. $data[$index] = MdProfit::find()->where(['order_id' => $data_id])->select('total_profit')->sum('total_profit') ?: '0.00';
  67. }
  68. if ($value === 'share_detail_sub') {
  69. $data[$index] = ShareDetail::find()->where(['store_id' => get_store_id(), 'type' =>
  70. [
  71. ShareDetail::TYPE_RANGE_PROFIT,
  72. ShareDetail::TYPE_SHARE_PROFIT,
  73. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_PROFIT,
  74. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT,
  75. ShareDetail::TYPE_RANGE_PROFIT_OLD,
  76. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD,
  77. ShareDetail::TYPE_FROST_PROFIT,
  78. ], 'type_id' => $data_id
  79. ])->select('money')->sum('money') ?: '0.00';
  80. }
  81. if ($value === 'share_detail') {
  82. $data[$index] = BonusPoolDetail::find()->where(['order_id' => $data_id])->select('money')->sum('money') ?: '0.00';
  83. $query = Order::find()->where(['id' => $data_id])->andWhere(['not in', 'id', BonusPoolDetail::find()->where(['order_id' => $data_id])->select('order_id')]);
  84. $query->select('sum(old_holder_first_price), sum(old_holder_second_price), sum(old_holder_third_price), sum(holder_first_price), sum(holder_second_price), sum(holder_third_price)');
  85. $data[$index] += array_sum($query->asArray()->one());
  86. // $data[$index] = ShareDetail::find()->where(['store_id' => get_store_id(), 'type' =>ShareDetail::TYPE_HOLDER_PROFIT,
  87. // 'type_id' => $data_id
  88. // ])->select('money')->sum('money') ?: '0.00';
  89. }
  90. } elseif ($value === 'sharing_receiver') {
  91. $data_sub = \Yii::$app->db->createCommand($sql)->queryAll();
  92. $data_order_no = array_column($data_sub, 'order_no');
  93. //让利比例
  94. $data[$index] = SharingReceiver::find()->where(['order_no' => $data_order_no, 'is_delete' => 0])->select('amount')->sum('amount') ?: '0.00';
  95. } else {
  96. $data_sub = \Yii::$app->db->createCommand($sql)->queryColumn();
  97. $data[$index] = array_sum($data_sub) ?: '0.00';
  98. }
  99. $data[$index] = sprintf('%.2f', $data[$index]);
  100. }
  101. $all_data = array_combine($field, $data);
  102. }
  103. // $query->select('o.id, o.pay_price, o.coupon_sub_price, o.level_order_id, su.mobile,
  104. // o.integral_difference_price, o.order_no, o.created_at, o.confirm_time, o.trade_status, su.name, su.avatar,
  105. // o.first_price, o.second_price, o.third_price');
  106. $result = $this->getSql();
  107. if ($result['code'] !== 0) {
  108. return $result;
  109. }
  110. $sql = $result['data'];
  111. $pageNo = get_params('pageNo', get_params('page', 1));
  112. $pageSize = get_params('pageSize', \Yii::$app->params['pageSize']);
  113. $pageInitNum = ($pageNo - 1) * $pageSize;
  114. $count = \Yii::$app->db->createCommand($sql)->query()->count();
  115. $sql .= " ORDER BY o.created_at desc ";
  116. if (!$this->isExport) {
  117. $sql .= " LIMIT {$pageSize} OFFSET {$pageInitNum}";
  118. }
  119. $list = \Yii::$app->db->createCommand($sql)->queryAll();
  120. $total_data = [
  121. 'totalCount' => $count
  122. ];
  123. $all_data = array_merge($total_data, $all_data);
  124. foreach ($list as &$value) {
  125. $order = Order::findOne($value['id']);
  126. $value['order'] = $order;
  127. $value['send_type_name'] = $order['is_delivery'] ? '同城' : ($order['is_offline'] ? '自提' :'快递');
  128. $value['mch'] = $order['mch_id'] ? \app\models\Mch::findOne($order['mch_id']) : null;
  129. $value['mch_name'] = $value['mch'] ? $value['mch']['name'] : '';
  130. if ($value['created_at']) {
  131. $value['created_at'] = date('Y-m-d H:i:s', $value['created_at']);
  132. }
  133. if ($value['confirm_time']) {
  134. $value['confirm_time'] = date('Y-m-d H:i:s', $value['confirm_time']);
  135. } else {
  136. $value['confirm_time'] = '-';
  137. }
  138. $value['total_price'] = sprintf('%.2f', ($value['pay_price'] + $value['integral_difference_price'] + $value['coupon_sub_price']));
  139. //让利比例
  140. $SharingReceiver = SharingReceiver::find()->where(['order_no' => $value['order_no'], 'is_delete' => 0])->select('amount')->column();
  141. $value['sharing_receiver'] = sprintf('%.2f', array_sum($SharingReceiver));
  142. //分销金额
  143. // $value['share_money'] = sprintf('%.2f', ($value['first_price'] + $value['second_price'] + $value['third_price']));
  144. $share_detail_list = [];
  145. $share_detail_holder_list = [];
  146. //转单金额
  147. $order_transit = [];
  148. $md_profit = 0;
  149. if ((int)$value['order_type'] === 1) {
  150. //转单
  151. $order_transit = OrderTransit::find()->where(['order_id' => $value['id'], 'is_delete' => 0])->select('order_price')->column();
  152. //极差分红
  153. $share_detail_list = ShareDetail::find()->where(['store_id' => get_store_id(), 'type' =>
  154. [
  155. ShareDetail::TYPE_RANGE_PROFIT,
  156. ShareDetail::TYPE_SHARE_PROFIT,
  157. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_PROFIT,
  158. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT,
  159. ShareDetail::TYPE_RANGE_PROFIT_OLD,
  160. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD,
  161. ShareDetail::TYPE_FROST_PROFIT,
  162. ], 'type_id' => $value['id']
  163. ])->select('money')->column();
  164. //股东分红
  165. $share_detail_holder_list = BonusPoolDetail::find()->where(['order_id' => $value['id']])->select('money')->column();
  166. // $share_detail_holder_list = ShareDetail::find()->where(['store_id' => get_store_id(), 'type' =>ShareDetail::TYPE_HOLDER_PROFIT,
  167. // 'type_id' => $value['id']
  168. // ])->select('money')->column();
  169. $order = Order::findOne($value['id']);
  170. $share_holder_price = bcadd($order['old_holder_first_price'],
  171. bcadd($order['old_holder_second_price'],
  172. bcadd($order['old_holder_third_price'],
  173. bcadd($order['holder_first_price'],
  174. bcadd($order['holder_second_price'], $order['holder_third_price'], 2)
  175. , 2)
  176. , 2)
  177. , 2)
  178. , 2);
  179. //门店收益
  180. $md_profit = MdProfit::findOne(['order_id' => $value['id']])->total_profit ?: 0.00;
  181. }
  182. if ((int)$value['trade_status'] === 3 && (int)$value['is_sale'] === 1) {
  183. $value['trade_status'] = '4';
  184. }
  185. $value['status'] = '';
  186. switch ($value['trade_status']) {
  187. case 2:
  188. $value['status'] = '待收货';
  189. break;
  190. case 3:
  191. $value['status'] = '已收货';
  192. break;
  193. case 4:
  194. $value['status'] = '已完成';
  195. break;
  196. }
  197. unset($value['is_sale']);
  198. //成本价
  199. $value['cost_price'] = OrderDetail::find()->where(['order_id' => $value['id'], 'is_delete' => 0])->sum('cost_price') ?: 0.00;
  200. $value['OrderRefund'] = \app\models\OrderRefund::find()->where(['order_id' => $value['id'], 'is_delete' => 0])->orderBy('id DESC')->one();
  201. $value['md_profit'] = sprintf('%.2f', $md_profit);
  202. $value['transit_price'] = sprintf('%.2f', array_sum($order_transit));
  203. $value['share_detail_sub'] = sprintf('%.2f', array_sum($share_detail_list));
  204. $value['share_detail'] = sprintf('%.2f', array_sum($share_detail_holder_list));
  205. $value['share_detail'] = $value['share_detail'] > 0 ? $value['share_detail'] : $share_holder_price;
  206. $value['finally_price'] = sprintf('%.2f', round($value['pay_price'] - $value['transit_price'] - $value['md_profit'] - $value['share_detail_sub'] - $value['share_detail'] - $value['sharing_receiver'] - $value['share_money'], 2));//最终金额
  207. }
  208. if ($this->isExport) {
  209. $export_field = [
  210. 'id' => 'ID',
  211. 'pay_price' => '实际支付金额',
  212. 'cost_price' => '成本价',
  213. 'order_no' => '订单号',
  214. 'created_at' => '下单时间',
  215. 'user_id' => '用户id',
  216. 'confirm_time' => '收货时间',
  217. 'trade_status' => '状态',
  218. 'level_order_id' => '等级订单id',
  219. 'share_money' => '分销支出',
  220. 'coupon_sub_price' => '优惠券优惠金额',
  221. 'integral_difference_price' => '积分抵扣金额',
  222. 'order_type' => '订单类型序号',
  223. 'name' => '用户名称',
  224. 'avatar' => '用户头像',
  225. 'mobile' => '用户手机号',
  226. 'total_price' => '订单金额',
  227. 'sharing_receiver' => '平台抽成',
  228. 'status' => '状态',
  229. 'md_profit' => '门店支出',
  230. 'transit_price' => '转单支出',
  231. 'share_detail_sub' => '极差支出',
  232. 'share_detail' => '股东支出',
  233. 'finally_price' => '结余金额',
  234. ];
  235. $file_name = '财务列表';
  236. $data = [];
  237. foreach ($list as $item) {
  238. $row = [];
  239. foreach ($export_field as $key => $label) {
  240. $row[$key] = $item[$key] ?? '';
  241. }
  242. $data[] = $row;
  243. }
  244. return SimpleExcelWriter::streamDownload($file_name . time() . '.csv')
  245. ->noHeaderRow()
  246. ->addRow(array_values($export_field))
  247. ->addRows($data)
  248. ->toBrowser();
  249. }
  250. return [
  251. 'code' => 0,
  252. 'msg' => 'success',
  253. 'data' => [
  254. 'data' => $list,
  255. 'all_data' => $all_data,
  256. 'pageNo' => (int)$pageNo,
  257. 'totalCount' => (int)$count,
  258. ]
  259. ];
  260. } catch (\Exception $e) {
  261. return [
  262. 'code' => 1,
  263. 'msg' => $e->getMessage()
  264. ];
  265. }
  266. }
  267. public function getSql($field = '') {
  268. try {
  269. $other_field = ", 0 as level_order_id, 0 as integral_difference_price, 0 as share_money";
  270. if ($field !== '') {
  271. //计算总额的sql
  272. switch ($field) {
  273. case 'total_price':
  274. $field2 = $field3 = $field1 = ' total_price, user_id';//cyy_order 与 cyy_order_pospal表存在此字段 支付金额+积分抵扣金额
  275. $field4 = "pay_price as total_price, user_id";
  276. break;
  277. case 'pay_price':
  278. $field4 = $field5 = $field2 = $field3 = $field1 = ' pay_price, user_id';
  279. break;
  280. case 'share_money':
  281. $field3 = $field1 = ' IF (share_send_type = 1, first_price + second_price + third_price + limit_price + rebate, limit_price + rebate) as share_money, user_id';
  282. $field4 = $field5 = $field2 = ' 0 as share_money ,user_id';
  283. break;
  284. case 'sharing_receiver':
  285. $field4 = $field5 = $field2 = $field3 = $field1 = ' order_no, user_id';
  286. break;
  287. default ://md_profit - share_detail_sub - share_detail
  288. $field1 = ' id as md_profit, user_id';
  289. $field3 = $field4 = $field5 = $field2 = ' 0 as md_profit, user_id';
  290. break;
  291. }
  292. } else {
  293. $field = ' id, pay_price, order_no, created_at, user_id';
  294. $field4 = $field2 = $field3 = $field1 = $field;
  295. $field1 .= ", confirm_time, trade_status, level_order_id, IF (share_send_type = 1, first_price + second_price + third_price + limit_price + rebate, limit_price + rebate) as share_money, coupon_sub_price, integral_difference_price, is_sale ";
  296. $field2 .= ", confirm_time, trade_status, coupon_sub_price {$other_field}, is_sale";
  297. $field3 .= ", confirm_time, trade_status, 0 as level_order_id, IF (share_send_type = 1, first_price + second_price + third_price + limit_price + rebate, limit_price + rebate) as share_money, coupon_sub_price, integral_difference_price, is_sale ";
  298. $field5 = $field4 .= ", pay_time as confirm_time, (2 + is_pay) as trade_status {$other_field}, 0 as coupon_sub_price, 1 as is_sale ";
  299. }
  300. $where = ' store_id = ' . get_store_id() . ' AND is_delete = 0 AND is_recycle = 0 AND trade_status NOT IN (-1, 1)';
  301. $re_where = ' store_id = ' . get_store_id() . ' AND is_delete = 0 AND is_recycle = 0';
  302. if ((int)$this->status > 1) {
  303. if (in_array((int)$this->status, [1, 2, 3])) {
  304. $where .= " AND trade_status = {$this->status}";
  305. }
  306. if (in_array((int)$this->status, [2, 3])) {
  307. $re_where .= " AND is_pay = 1";
  308. }
  309. if ((int)$this->status === 4) {
  310. $where .= " AND is_sale = 1";
  311. } else {
  312. $where .= " AND is_sale = 0";
  313. }
  314. }
  315. //下单开始日期
  316. if ($this->order_start_time) {
  317. $order_start_time = strtotime($this->order_start_time);
  318. $where .= " AND created_at >= {$order_start_time}";
  319. $re_where .= " AND created_at >= {$order_start_time}";
  320. }
  321. //下单结束日期
  322. if ($this->order_end_time) {
  323. $order_end_time = strtotime($this->order_end_time);
  324. $where .= " AND created_at <= {$order_end_time}";
  325. $re_where .= " AND created_at <= {$order_end_time}";
  326. }
  327. //确认收货开始时间
  328. if ($this->confirm_start_time) {
  329. $confirm_start_time = strtotime($this->confirm_start_time);
  330. $where .= " AND confirm_time >= {$confirm_start_time}";
  331. $re_where .= " AND created_at >= {$confirm_start_time}";
  332. }
  333. //确认收货结束时间
  334. if ($this->confirm_end_time) {
  335. $confirm_end_time = strtotime($this->confirm_end_time);
  336. $where .= " AND confirm_time <= {$confirm_end_time}";
  337. $re_where .= " AND created_at <= {$confirm_end_time}";
  338. }
  339. //订单号
  340. if ($this->order_no) {
  341. $where .= " AND order_no LIKE '%{$this->order_no}%'";
  342. $re_where .= " AND order_no LIKE '%{$this->order_no}%'";
  343. }
  344. //订单号
  345. $whereRefund = '';
  346. if (isset($this->has_refund) && $this->has_refund > -1) {
  347. $ref = 'SELECT order_id FROM cyy_order_refund WHERE store_id = ' . get_store_id();
  348. if($this->has_refund){
  349. $whereRefund .= ' AND id IN (' . $ref . ')';
  350. }else{
  351. $whereRefund .= ' AND id NOT IN (' . $ref . ')';
  352. }
  353. }
  354. $sql = "SELECT o.*, su.name, su.avatar, su.mobile FROM (SELECT {$field1}, 1 as order_type FROM cyy_order where {$where}{$whereRefund}";
  355. if(!$whereRefund){
  356. $sql .= " UNION ALL SELECT {$field2}, 2 as order_type FROM cyy_adopt_cost_order where {$where}";
  357. $sql .= " UNION ALL SELECT {$field3}, 3 as order_type FROM cyy_order_pospal where {$where}";
  358. $sql .= " UNION ALL SELECT {$field4}, 4 as order_type FROM cyy_level_order where {$re_where} AND is_pay = 1";
  359. }
  360. // $sql .= " UNION ALL SELECT {$field5}, 5 as order_type FROM cyy_re_order where {$re_where} AND is_pay = 1";
  361. $sql .= " ) as o LEFT JOIN cyy_user u ON o.user_id = u.id LEFT JOIN cyy_saas_user su ON su.mobile = u.binding";
  362. // $query = Order::find()->alias('o')->leftJoin(['u' => User::tableName()], 'o.user_id = u.id')
  363. // ->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile')
  364. // ->where(['o.store_id' => get_store_id(), 'o.trade_status' => [2, 3], 'o.is_delete' => 0]);
  365. //状态 1全部 2待收货 3收货
  366. // if ((int)$this->status > 1) {
  367. // $query->andWhere(['o.trade_status' => $this->status]);
  368. // }
  369. //用户名称
  370. if ($this->user_name) {
  371. $sql .= " where su.name LIKE '%{$this->user_name}%'";
  372. }
  373. return [
  374. 'code' => 0,
  375. 'msg' => 'success',
  376. 'data' => $sql
  377. ];
  378. } catch (\Exception $e) {
  379. return [
  380. 'code' => 1,
  381. 'msg' => $e->getMessage()
  382. ];
  383. }
  384. }
  385. }