month.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <?php
  2. /**
  3. * 任务计划 - 月执行的任务
  4. *
  5. *
  6. *
  7. *
  8. */
  9. defined('InShopNC') or exit('Access Invalid!');
  10. class monthControl extends BaseCronControl
  11. {
  12. /**
  13. * 默认方法
  14. */
  15. public function indexOp(){
  16. $this->_create_bill();
  17. }
  18. private function _create_bill() {
  19. //更新订单商品佣金值
  20. $this->_order_commis_rate_update();
  21. $model = Model('bill');
  22. //实物订单结算
  23. try {
  24. $trans = new trans_wapper($model,__METHOD__);
  25. $this->_real_order();
  26. $trans->commit();
  27. } catch (Exception $e) {
  28. $trans->rollback();
  29. $this->log('实物账单:'.$e->getMessage());
  30. }
  31. //虚拟订单结算
  32. try {
  33. $trans = new trans_wapper($model,__METHOD__);
  34. $this->_vr_order();
  35. $trans->commit();
  36. } catch (Exception $e) {
  37. $trans->rollback();
  38. $this->log('虚拟账单:'.$e->getMessage());
  39. }
  40. }
  41. /**
  42. * 生成上月账单[实物订单]
  43. */
  44. private function _real_order() {
  45. $model_order = Model('order');
  46. $model_bill = Model('bill');
  47. $order_statis_max_info = $model_bill->getOrderStatisInfo(array(),'os_end_date','os_month desc');
  48. //计算起始时间点,自动生成以月份为单位的空结算记录
  49. if (!$order_statis_max_info){
  50. $order_min_info = $model_order->getOrderInfo(array(),array(),'min(add_time) as add_time');
  51. $start_unixtime = is_numeric($order_min_info['add_time']) ? $order_min_info['add_time'] : time();
  52. } else {
  53. $start_unixtime = $order_statis_max_info['os_end_date'];
  54. }
  55. $data = array();
  56. $i = 1;
  57. $start_unixtime = strtotime(date('Y-m-01 00:00:00', $start_unixtime));
  58. $current_time = strtotime(date('Y-m-01 00:00:01',time()));
  59. while (($time = strtotime('-'.$i.' month',$current_time)) >= $start_unixtime) {
  60. if (date('Ym',$start_unixtime) == date('Ym',$time)) {
  61. //如果两个月份相等检查库是里否存在
  62. $order_statis = $model_bill->getOrderStatisInfo(array('os_month'=>date('Ym',$start_unixtime)));
  63. if ($order_statis) {
  64. break;
  65. }
  66. }
  67. $first_day_unixtime = strtotime(date('Y-m-01 00:00:00', $time)); //该月第一天0时unix时间戳
  68. $last_day_unixtime = strtotime(date('Y-m-01 23:59:59', $time)." +1 month -1 day"); //该月最后一天最后一秒时unix时间戳
  69. $key = count($data);
  70. $os_month = date('Ym',$first_day_unixtime);
  71. $data[$key]['os_month'] = $os_month;
  72. $data[$key]['os_year'] = date('Y',$first_day_unixtime);
  73. $data[$key]['os_start_date'] = $first_day_unixtime;
  74. $data[$key]['os_end_date'] = $last_day_unixtime;
  75. //生成所有店铺月订单出账单
  76. $this->_create_real_order_bill($data[$key]);
  77. $fileds = 'sum(ob_order_totals) as ob_order_totals,sum(ob_shipping_totals) as ob_shipping_totals,
  78. sum(ob_order_return_totals) as ob_order_return_totals,
  79. sum(ob_commis_totals) as ob_commis_totals,sum(ob_commis_return_totals) as ob_commis_return_totals,
  80. sum(ob_store_cost_totals) as ob_store_cost_totals,sum(ob_result_totals) as ob_result_totals';
  81. $order_bill_info = $model_bill->getOrderBillInfo(array('os_month'=>$os_month),$fileds);
  82. $data[$key]['os_order_totals'] = floatval($order_bill_info['ob_order_totals']);
  83. $data[$key]['os_shipping_totals'] = floatval($order_bill_info['ob_shipping_totals']);
  84. $data[$key]['os_order_return_totals'] = floatval($order_bill_info['ob_order_return_totals']);
  85. $data[$key]['os_commis_totals'] = floatval($order_bill_info['ob_commis_totals']);
  86. $data[$key]['os_commis_return_totals'] = floatval($order_bill_info['ob_commis_return_totals']);
  87. $data[$key]['os_store_cost_totals'] = floatval($order_bill_info['ob_store_cost_totals']);
  88. $data[$key]['os_result_totals'] = floatval($order_bill_info['ob_result_totals']);
  89. $i++;
  90. }
  91. krsort($data);
  92. foreach ($data as $v) {
  93. $insert = $model_bill->addOrderStatis($v);
  94. if (!$insert) {
  95. throw new Exception('生成平台月出账单['.$v['os_month'].']失败');
  96. }
  97. }
  98. }
  99. /**
  100. * 生成所有店铺月订单出账单[实物订单]
  101. *
  102. * @param int $data
  103. */
  104. private function _create_real_order_bill($data)
  105. {
  106. $model_order = Model('order');
  107. $model_bill = Model('bill');
  108. $model_store = Model('store');
  109. //批量插件order_bill表
  110. // $condition = array();
  111. // $condition['order_state'] = ORDER_STATE_SUCCESS;
  112. // $condition['finnshed_time'] = array(array('egt',$data['os_start_date']),array('elt',$data['os_end_date']),'and');
  113. // 取出有最终成交订单的店铺ID数量(ID不重复)
  114. // $store_count = $model_order->getOrderInfo($condition,array(),'count(DISTINCT store_id) as c');
  115. // $store_count = $store_count['c'];
  116. //取店铺表数量(因为可能存在无订单,但有店铺活动费用,所以不再从订单表取店铺数量)
  117. $store_count = $model_store->getStoreCount(array());
  118. //分批生成该月份的店铺空结算表,每批生成300个店铺
  119. $insert = false;
  120. for ($i=0;$i<=$store_count;$i=$i+300){
  121. // $store_list = $model_order->getOrderList($condition,'','DISTINCT store_id','',"{$i},300");
  122. $store_list = $model_store->getStoreList(array(),null,'','store_id',"{$i},300");
  123. if ($store_list){
  124. //自动生成以月份为单位的空结算记录
  125. $data_bill = array();
  126. foreach($store_list as $store_info){
  127. $data_bill['ob_no'] = $data['os_month'].$store_info['store_id'];
  128. $data_bill['ob_start_date'] = $data['os_start_date'];
  129. $data_bill['ob_end_date'] = $data['os_end_date'];
  130. $data_bill['os_month'] = $data['os_month'];
  131. $data_bill['ob_state'] = 0;
  132. $data_bill['ob_store_id'] = $store_info['store_id'];
  133. if (!$model_bill->getOrderBillInfo(array('ob_no'=>$data_bill['ob_no']))) {
  134. $insert = $model_bill->addOrderBill($data_bill);
  135. if (!$insert) {
  136. throw new Exception('生成账单['.$data_bill['ob_no'].']失败');
  137. }
  138. //对已生成空账单进行销量、退单、佣金统计
  139. $update = $this->_calc_real_order_bill($data_bill);
  140. if (!$update){
  141. throw new Exception('更新账单['.$data_bill['ob_no'].']失败');
  142. }
  143. // 发送店铺消息
  144. $param = array();
  145. $param['code'] = 'store_bill_affirm';
  146. $param['store_id'] = $store_info['store_id'];
  147. $param['param'] = array(
  148. 'state_time' => date('Y-m-d H:i:s', $data_bill['ob_start_date']),
  149. 'end_time' => date('Y-m-d H:i:s', $data_bill['ob_end_date']),
  150. 'bill_no' => $data_bill['ob_no']
  151. );
  152. QueueClient::push('sendStoreMsg', $param);
  153. }
  154. }
  155. }
  156. }
  157. }
  158. /**
  159. * 计算某月内,某店铺的销量,退单量,佣金[实物订单]
  160. *
  161. * @param array $data_bill
  162. */
  163. private function _calc_real_order_bill($data_bill){
  164. $model_order = Model('order');
  165. $model_bill = Model('bill');
  166. $model_store = Model('store');
  167. $order_condition = array();
  168. $order_condition['order_state'] = ORDER_STATE_SUCCESS;
  169. $order_condition['store_id'] = $data_bill['ob_store_id'];
  170. $order_condition['finnshed_time'] = array('between',"{$data_bill['ob_start_date']},{$data_bill['ob_end_date']}");
  171. $update = array();
  172. //订单金额
  173. $fields = 'sum(order_amount) as order_amount,sum(shipping_fee) as shipping_amount,store_name';
  174. $order_info = $model_order->getOrderInfo($order_condition,array(),$fields);
  175. $update['ob_order_totals'] = floatval($order_info['order_amount']);
  176. //运费
  177. $update['ob_shipping_totals'] = floatval($order_info['shipping_amount']);
  178. //店铺名字
  179. $store_info = $model_store->getStoreInfoByID($data_bill['ob_store_id']);
  180. $update['ob_store_name'] = $store_info['store_name'];
  181. //佣金金额
  182. $order_info = $model_order->getOrderInfo($order_condition,array(),'count(DISTINCT order_id) as count');
  183. $order_count = $order_info['count'];
  184. $commis_rate_totals_array = array();
  185. //分批计算佣金,最后取总和
  186. for ($i = 0; $i <= $order_count; $i = $i + 300){
  187. $order_list = $model_order->getOrderList($order_condition,'','order_id','',"{$i},300");
  188. $order_id_array = array();
  189. foreach ($order_list as $order_info) {
  190. $order_id_array[] = $order_info['order_id'];
  191. }
  192. if (!empty($order_id_array)){
  193. $order_goods_condition = array();
  194. $order_goods_condition['order_id'] = array('in',$order_id_array);
  195. $field = 'SUM(ROUND(goods_pay_price*commis_rate/100,2)) as commis_amount';
  196. $order_goods_info = $model_order->getOrderGoodsInfo($order_goods_condition,$field);
  197. $commis_rate_totals_array[] = $order_goods_info['commis_amount'];
  198. }else{
  199. $commis_rate_totals_array[] = 0;
  200. }
  201. }
  202. $update['ob_commis_totals'] = floatval(array_sum($commis_rate_totals_array));
  203. //退款总额
  204. $model_refund = Model('refund_return');
  205. $refund_condition = array();
  206. $refund_condition['seller_state'] = 2;
  207. $refund_condition['store_id'] = $data_bill['ob_store_id'];
  208. $refund_condition['goods_id'] = array('gt',0);
  209. $refund_condition['admin_time'] = array(array('egt',$data_bill['ob_start_date']),array('elt',$data_bill['ob_end_date']),'and');
  210. $refund_info = $model_refund->getRefundReturnInfo($refund_condition,'sum(refund_amount) as amount');
  211. $update['ob_order_return_totals'] = floatval($refund_info['amount']);
  212. //退款佣金
  213. $refund = $model_refund->getRefundReturnInfo($refund_condition,'sum(ROUND(refund_amount*commis_rate/100,2)) as amount');
  214. if ($refund) {
  215. $update['ob_commis_return_totals'] = floatval($refund['amount']);
  216. } else {
  217. $update['ob_commis_return_totals'] = 0;
  218. }
  219. //店铺活动费用
  220. $model_store_cost = Model('store_cost');
  221. $cost_condition = array();
  222. $cost_condition['cost_store_id'] = $data_bill['ob_store_id'];
  223. $cost_condition['cost_state'] = 0;
  224. $cost_condition['cost_time'] = array(array('egt',$data_bill['ob_start_date']),array('elt',$data_bill['ob_end_date']),'and');
  225. $cost_info = $model_store_cost->getStoreCostInfo($cost_condition,'sum(cost_price) as cost_amount');
  226. $update['ob_store_cost_totals'] = floatval($cost_info['cost_amount']);
  227. //本期应结
  228. $update['ob_result_totals'] = $update['ob_order_totals'] - $update['ob_order_return_totals'] -
  229. $update['ob_commis_totals'] + $update['ob_commis_return_totals']-
  230. $update['ob_store_cost_totals'];
  231. $update['ob_create_date'] = time();
  232. $update['ob_state'] = 1;
  233. return $model_bill->editOrderBill($update,array('ob_no'=>$data_bill['ob_no']));
  234. }
  235. /**
  236. * 生成上月账单[虚拟订单]
  237. */
  238. private function _vr_order() {
  239. $model_order = Model('vr_order');
  240. $model_bill = Model('vr_bill');
  241. $order_statis_max_info = $model_bill->getOrderStatisInfo(array(),'os_end_date','os_month desc');
  242. //计算起始时间点,自动生成以月份为单位的空结算记录
  243. if (!$order_statis_max_info){
  244. $order_min_info = $model_order->getOrderInfo(array(),'min(add_time) as add_time');
  245. $start_unixtime = is_numeric($order_min_info['add_time']) ? $order_min_info['add_time'] : time();
  246. } else {
  247. $start_unixtime = $order_statis_max_info['os_end_date'];
  248. }
  249. $data = array();
  250. $i = 1;
  251. $start_unixtime = strtotime(date('Y-m-01 00:00:00', $start_unixtime));
  252. $current_time = strtotime(date('Y-m-01 00:00:01',time()));
  253. while (($time = strtotime('-'.$i.' month',$current_time)) >= $start_unixtime) {
  254. if (date('Ym',$start_unixtime) == date('Ym',$time)) {
  255. //如果两个月份相等检查库是里否存在
  256. $order_statis = $model_bill->getOrderStatisInfo(array('os_month'=>date('Ym',$start_unixtime)));
  257. if ($order_statis) {
  258. break;
  259. }
  260. }
  261. $first_day_unixtime = strtotime(date('Y-m-01 00:00:00', $time)); //该月第一天0时unix时间戳
  262. $last_day_unixtime = strtotime(date('Y-m-01 23:59:59', $time)." +1 month -1 day"); //该月最后一天最后一秒时unix时间戳
  263. $key = count($data);
  264. $os_month = date('Ym',$first_day_unixtime);
  265. $data[$key]['os_month'] = $os_month;
  266. $data[$key]['os_year'] = date('Y',$first_day_unixtime);
  267. $data[$key]['os_start_date'] = $first_day_unixtime;
  268. $data[$key]['os_end_date'] = $last_day_unixtime;
  269. //生成所有店铺月订单出账单
  270. $this->_create_vr_order_bill($data[$key]);
  271. $fileds = 'sum(ob_order_totals) as ob_order_totals,
  272. sum(ob_commis_totals) as ob_commis_totals,sum(ob_result_totals) as ob_result_totals';
  273. $order_bill_info = $model_bill->getOrderBillInfo(array('os_month'=>$os_month),$fileds);
  274. $data[$key]['os_order_totals'] = floatval($order_bill_info['ob_order_totals']);
  275. $data[$key]['os_commis_totals'] = floatval($order_bill_info['ob_commis_totals']);
  276. $data[$key]['os_result_totals'] = floatval($order_bill_info['ob_result_totals']);
  277. $i++;
  278. }
  279. krsort($data);
  280. foreach ($data as $v) {
  281. $insert = $model_bill->addOrderStatis($v);
  282. if (!$insert) {
  283. throw new Exception('生成平台月出账单['.$v['os_month'].']失败');
  284. }
  285. }
  286. }
  287. /**
  288. * 生成所有店铺月订单出账单[虚拟订单]
  289. *
  290. * @param int $data
  291. */
  292. private function _create_vr_order_bill($data){
  293. $model_order = Model('vr_order');
  294. $model_bill = Model('vr_bill');
  295. $model_store = Model('store');
  296. //批量插入order_bill表
  297. $condition = array();
  298. $condition['order_state'] = array('egt',ORDER_STATE_PAY);
  299. $condition['payment_time'] = array(array('egt',$data['os_start_date']),array('elt',$data['os_end_date']),'and');
  300. //取出有最终成交订单的店铺ID数量(ID不重复)
  301. $order_info = $model_order->getOrderInfo($condition,'count(DISTINCT store_id) as store_count');
  302. $store_count = $order_info['store_count'];
  303. //分批生成该月份的店铺空结算表,每批生成300个店铺
  304. $insert = false;
  305. for ($i=0;$i<=$store_count;$i=$i+300){
  306. $store_list = $model_order->getOrderList($condition,'','DISTINCT store_id','',"{$i},300");
  307. if ($store_list){
  308. //自动生成以月份为单位的空结算记录
  309. $data_bill = array();
  310. foreach($store_list as $store_info){
  311. $data_bill['ob_no'] = $data['os_month'].$store_info['store_id'];
  312. $data_bill['ob_start_date'] = $data['os_start_date'];
  313. $data_bill['ob_end_date'] = $data['os_end_date'];
  314. $data_bill['os_month'] = $data['os_month'];
  315. $data_bill['ob_state'] = 0;
  316. $data_bill['ob_store_id'] = $store_info['store_id'];
  317. if (!$model_bill->getOrderBillInfo(array('ob_no'=>$data_bill['ob_no']))) {
  318. $insert = $model_bill->addOrderBill($data_bill);
  319. if (!$insert) {
  320. throw new Exception('生成账单['.$data_bill['ob_no'].']失败');
  321. }
  322. //对已生成空账单进行销量、佣金统计
  323. $update = $this->_calc_vr_order_bill($data_bill);
  324. if (!$update){
  325. throw new Exception('更新账单['.$data_bill['ob_no'].']失败');
  326. }
  327. // 发送店铺消息
  328. $param = array();
  329. $param['code'] = 'store_bill_affirm';
  330. $param['store_id'] = $store_info['store_id'];
  331. $param['param'] = array(
  332. 'state_time' => date('Y-m-d H:i:s', $data_bill['ob_start_date']),
  333. 'end_time' => date('Y-m-d H:i:s', $data_bill['ob_end_date']),
  334. 'bill_no' => $data_bill['ob_no']
  335. );
  336. QueueClient::push('sendStoreMsg', $param);
  337. }
  338. }
  339. }
  340. }
  341. }
  342. /**
  343. * 计算某月内,某店铺的销量,佣金
  344. *
  345. * @param array $data_bill
  346. */
  347. private function _calc_vr_order_bill($data_bill){
  348. $model_order = Model('vr_order');
  349. $model_bill = Model('vr_bill');
  350. $model_store = Model('store');
  351. //计算已使用兑换码
  352. $order_condition = array();
  353. $order_condition['vr_state'] = 1;
  354. $order_condition['store_id'] = $data_bill['ob_store_id'];
  355. $order_condition['vr_usetime'] = array('between',"{$data_bill['ob_start_date']},{$data_bill['ob_end_date']}");
  356. $update = array();
  357. //订单金额
  358. $fields = 'sum(pay_price) as order_amount,SUM(ROUND(pay_price*commis_rate/100,2)) as commis_amount';
  359. $order_info = $model_order->getOrderCodeInfo($order_condition, $fields);
  360. $update['ob_order_totals'] = floatval($order_info['order_amount']);
  361. //佣金金额
  362. $update['ob_commis_totals'] = $order_info['commis_amount'];
  363. //计算已过期不退款兑换码
  364. $order_condition = array();
  365. $order_condition['vr_state'] = 0;
  366. $order_condition['store_id'] = $data_bill['ob_store_id'];
  367. $order_condition['vr_invalid_refund'] = 0;
  368. $order_condition['vr_indate'] = array('between',"{$data_bill['ob_start_date']},{$data_bill['ob_end_date']}");
  369. //订单金额
  370. $fields = 'sum(pay_price) as order_amount,SUM(ROUND(pay_price*commis_rate/100,2)) as commis_amount';
  371. $order_info = $model_order->getOrderCodeInfo($order_condition, $fields);
  372. $update['ob_order_totals'] += floatval($order_info['order_amount']);
  373. //佣金金额
  374. $update['ob_commis_totals'] += $order_info['commis_amount'];
  375. //店铺名
  376. $store_info = $model_store->getStoreInfoByID($data_bill['ob_store_id']);
  377. $update['ob_store_name'] = $store_info['store_name'];
  378. //本期应结
  379. $update['ob_result_totals'] = $update['ob_order_totals'] - $update['ob_commis_totals'];
  380. $update['ob_create_date'] = time();
  381. $update['ob_state'] = 1;
  382. return $model_bill->editOrderBill($update,array('ob_no'=>$data_bill['ob_no']));
  383. }
  384. }