Date.php 84 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  1. <?php
  2. namespace app\crontab\controller;
  3. use think\facade\Db;
  4. /**
  5. *
  6. *
  7. * ----------------------------------------------------------------------------
  8. *
  9. * 定时器
  10. */
  11. class Date extends BaseCron
  12. {
  13. /**
  14. * 该文件中所有任务执行频率,默认1天,单位:秒
  15. * @var int
  16. */
  17. const EXE_TIMES = 86400;
  18. /**
  19. * 优惠券即将到期提醒时间,单位:天
  20. * @var int
  21. */
  22. const VOUCHER_INTERVAL = 5;
  23. /**
  24. * 兑换码即将到期提醒时间,单位:天
  25. * @var int
  26. */
  27. const VR_CODE_INTERVAL = 5;
  28. /**
  29. * 订单结束后可评论时间,15天,60*60*24*15
  30. * @var int
  31. */
  32. const ORDER_EVALUATE_TIME = 1296000;
  33. /**
  34. * 每次到货通知消息数量
  35. * @var int
  36. */
  37. const ARRIVAL_NOTICE_NUM = 100;
  38. /**
  39. * 默认方法
  40. */
  41. public function index()
  42. {
  43. //小程序直播商品状态查询
  44. $this->_minipro_live_goods_state();
  45. //小程序直播商品删除
  46. $this->_minipro_live_goods_delete();
  47. //小程序直播商品创建
  48. $this->_minipro_live_goods_add();
  49. //小程序直播商品更新
  50. $this->_minipro_live_goods_update();
  51. //订单超期后不允许评价
  52. $this->_order_eval_expire_update();
  53. //未付款订单超期自动关闭
  54. $this->_order_timeout_cancel();
  55. //增加会员积分和经验值
  56. $this->_add_points();
  57. //订单自动完成
  58. $this->_order_auto_complete();
  59. //更新订单扩展表收货人所在省份ID
  60. $this->_order_reciver_provinceid_update();
  61. //更新退款申请超时处理
  62. model('trade')->editRefundConfirm();
  63. //店铺到期关闭
  64. $this->_store_auto_close();
  65. //生成店铺结算单
  66. $this->_creat_bill();
  67. //代金券即将过期提醒
  68. $this->_voucher_will_expire();
  69. //虚拟兑换码即将过期提醒
  70. $this->_vr_code_will_expire();
  71. //更新商品访问量
  72. $this->_goods_click_update();
  73. //更新商品促销到期状态
  74. $this->_goods_promotion_state_update();
  75. //商品到货通知提醒
  76. $this->_arrival_notice();
  77. //更新浏览量
  78. $this->_goods_browse_update();
  79. //缓存订单及订单商品相关数据
  80. $this->_order_goods_cache();
  81. //会员相关数据统计
  82. $this->_member_stat();
  83. }
  84. /*
  85. * 小程序直播商品创建(调用额度:500次/一天)
  86. */
  87. function _minipro_live_goods_add()
  88. {
  89. if (intval(config('ds_config.live_type')) != 1) {
  90. return;
  91. }
  92. $goods_list = Db::name('goodscommon')->alias('goodscommon')->join('minipro_live_goods minipro_live_goods', 'minipro_live_goods.goods_commonid=goodscommon.goods_commonid', 'LEFT')->field('goodscommon.gc_id,goodscommon.gc_id_1,goodscommon.gc_id_2,goodscommon.gc_id_3,goodscommon.gc_name,goodscommon.goods_name,goodscommon.goods_image,goodscommon.goods_price,goodscommon.goods_commonid,goodscommon.store_id,goodscommon.store_name')->where(array(array('minipro_live_goods.goods_commonid', 'null')))->limit(100)->select()->toArray();
  93. $wechat_model = model('wechat');
  94. $wechat_model->getOneWxconfig();
  95. $accessToken = $wechat_model->getAccessToken('miniprogram', 0);
  96. if ($wechat_model->error_code) {
  97. $this->log('获取小程序AccessToken失败' . $wechat_model->error_message);
  98. return;
  99. }
  100. $minipro_live_goods_model = model('minipro_live_goods');
  101. foreach ($goods_list as $goods_info) {
  102. $goods_id = Db::name('goods')->where(array(array('goods_commonid', '=', $goods_info['goods_commonid'])))->order('goods_id asc')->value('goods_id');
  103. if (!$goods_id) {
  104. $this->log('商品不存在');
  105. continue;
  106. }
  107. //上传临时素材
  108. $goods_image = str_replace(UPLOAD_SITE_URL, BASE_UPLOAD_PATH, goods_thumb($goods_info));
  109. $image_path = pathinfo($goods_image, PATHINFO_DIRNAME);
  110. $image_name = pathinfo($goods_image, PATHINFO_BASENAME);
  111. if (!strstr($image_name, '_240')) {
  112. create_albumpic_thumb($image_path, $image_name);
  113. $goods_image = str_ireplace('.', '_240.', $image_name);
  114. }
  115. $res = $wechat_model->uploadMedia('image', $goods_image, "image/jpeg", $image_name);
  116. if (!$res['code']) {
  117. $this->log('上传临时素材失败' . $res['msg']);
  118. continue;
  119. }
  120. $coverImgUrl = $res['data'];
  121. $data = array(
  122. 'goodsInfo' => array(
  123. 'coverImgUrl' => $coverImgUrl,
  124. 'name' => mb_substr($goods_info['goods_name'], 0, 14), //商品名称,最长14个汉字
  125. 'priceType' => 1,
  126. 'price' => $goods_info['goods_price'],
  127. 'url' => 'pages/index/index?ret_url=' . urlencode(config('ds_config.h5_site_url') . '/pages/home/goodsdetail/Goodsdetail?goods_id=' . $goods_id)
  128. )
  129. );
  130. $res = http_request('https://api.weixin.qq.com/wxaapi/broadcast/goods/add?access_token=' . $accessToken, 'POST', $data);
  131. $res = json_decode($res, true);
  132. if (!$res || $res['errcode']) {
  133. $this->log(isset($res['errmsg']) ? $res['errmsg'] : '添加商品出错,错误码:' . $res['errcode']);
  134. continue;
  135. }
  136. $minipro_live_goods_model->addMiniproLiveGoods(array(
  137. 'store_id' => $goods_info['store_id'],
  138. 'store_name' => $goods_info['store_name'],
  139. 'goods_id' => $goods_id,
  140. 'goods_commonid' => $goods_info['goods_commonid'],
  141. 'goods_name' => $goods_info['goods_name'],
  142. 'goods_price' => $goods_info['goods_price'],
  143. 'goods_image' => $goods_info['goods_image'],
  144. 'minipro_live_goods_add_time' => TIMESTAMP,
  145. 'minipro_live_goods_state' => 0,
  146. 'minipro_live_goods_result_id' => $res['goodsId'],
  147. 'minipro_live_goods_verify_id' => $res['auditId'],
  148. ));
  149. }
  150. }
  151. /*
  152. * 小程序直播商品删除(调用额度:1000次/一天)
  153. */
  154. function _minipro_live_goods_delete()
  155. {
  156. if (intval(config('ds_config.live_type')) != 1) {
  157. return;
  158. }
  159. $wechat_model = model('wechat');
  160. $wechat_model->getOneWxconfig();
  161. $accessToken = $wechat_model->getAccessToken('miniprogram', 0);
  162. if ($wechat_model->error_code) {
  163. $this->log('获取小程序AccessToken失败' . $wechat_model->error_message);
  164. return;
  165. }
  166. $minipro_live_goods_model = model('minipro_live_goods');
  167. //商品不存在的删除,审核中的、已审核的商品名称、商品图片不一致的删除
  168. $minipro_live_goods_result_ids = Db::name('minipro_live_goods')->alias('minipro_live_goods')->join('goodscommon goodscommon', 'minipro_live_goods.goods_commonid=goodscommon.goods_commonid', 'LEFT')->where(array(array('minipro_live_goods_close', '=', 0), array('goodscommon.goods_commonid', 'null')))->whereOr(function ($query) {
  169. $query->where(array(array('minipro_live_goods_state', '<>', 0)))->where(function ($query) {
  170. $query->whereOr(array(array('goodscommon.goods_name', '<>', Db::raw('minipro_live_goods.goods_name'))))->whereOr(array(array('goodscommon.goods_image', '<>', Db::raw('minipro_live_goods.goods_image'))));
  171. });
  172. })->limit(100)->column('minipro_live_goods_result_id');
  173. foreach ($minipro_live_goods_result_ids as $minipro_live_goods_result_id) {
  174. $data = array(
  175. 'goodsId' => $minipro_live_goods_result_id
  176. );
  177. $res = http_request('https://api.weixin.qq.com/wxaapi/broadcast/goods/delete?access_token=' . $accessToken, 'POST', $data);
  178. $res = json_decode($res, true);
  179. if (!$res || $res['errcode']) {
  180. $this->log(isset($res['errmsg']) ? $res['errmsg'] : '删除商品出错,错误码:' . $res['errcode']);
  181. continue;
  182. }
  183. $minipro_live_goods_model->delMiniproLiveGoods(array(array('minipro_live_goods_result_id', '=', $minipro_live_goods_result_id)));
  184. }
  185. //审核中的、已审核的商品ID不存在的删除
  186. $subQuery = Db::name('goods')->field('goods_id')->where('1=1')->buildSql();
  187. $minipro_live_goods_result_ids = Db::name('minipro_live_goods')->where(array(array('minipro_live_goods_close', '=', 0), array('minipro_live_goods_state', '<>', 0), array('goods_id', 'not in', Db::raw($subQuery))))->limit(100)->column('minipro_live_goods_result_id');
  188. foreach ($minipro_live_goods_result_ids as $minipro_live_goods_result_id) {
  189. $data = array(
  190. 'goodsId' => $minipro_live_goods_result_id
  191. );
  192. $res = http_request('https://api.weixin.qq.com/wxaapi/broadcast/goods/delete?access_token=' . $accessToken, 'POST', $data);
  193. $res = json_decode($res, true);
  194. if (!$res || $res['errcode']) {
  195. $this->log(isset($res['errmsg']) ? $res['errmsg'] : '删除商品出错,错误码:' . $res['errcode']);
  196. continue;
  197. }
  198. $minipro_live_goods_model->delMiniproLiveGoods(array(array('minipro_live_goods_result_id', '=', $minipro_live_goods_result_id)));
  199. }
  200. }
  201. /*
  202. * 小程序直播商品更新(调用额度:1000次/一天)
  203. */
  204. function _minipro_live_goods_update()
  205. {
  206. if (intval(config('ds_config.live_type')) != 1) {
  207. return;
  208. }
  209. $wechat_model = model('wechat');
  210. $wechat_model->getOneWxconfig();
  211. $accessToken = $wechat_model->getAccessToken('miniprogram', 0);
  212. if ($wechat_model->error_code) {
  213. $this->log('获取小程序AccessToken失败' . $wechat_model->error_message);
  214. return;
  215. }
  216. $minipro_live_goods_model = model('minipro_live_goods');
  217. //未审核的商品、已审核的商品价格不一致的更新
  218. $goods_list = Db::name('minipro_live_goods')->alias('minipro_live_goods')->field('minipro_live_goods_result_id,goodscommon.goods_name,goodscommon.goods_image,minipro_live_goods.goods_image as goods_image2,goodscommon.goods_price,goodscommon.goods_commonid,goodscommon.store_id,goodscommon.store_name')->join('goodscommon goodscommon', 'minipro_live_goods.goods_commonid=goodscommon.goods_commonid')->where(array(array('minipro_live_goods_close', '=', 0)))->where(function ($query) {
  219. $query->where(array(array('minipro_live_goods_state', '=', 2)))->where(array(array('goodscommon.goods_price', '<>', Db::raw('minipro_live_goods.goods_price'))));
  220. })->whereOr(function ($query) {
  221. $query->where(array(array('minipro_live_goods_state', '=', 0)))->where(function ($query) {
  222. $query->whereOr(array(array('goodscommon.goods_price', '<>', Db::raw('minipro_live_goods.goods_price'))))->whereOr(array(array('goodscommon.goods_name', '<>', Db::raw('minipro_live_goods.goods_name'))))->whereOr(array(array('goodscommon.goods_image', '<>', Db::raw('minipro_live_goods.goods_image'))));
  223. });
  224. })->limit(100)->select()->toArray();
  225. foreach ($goods_list as $goods_info) {
  226. $goods_data = array(
  227. 'goodsId' => $goods_info['minipro_live_goods_result_id'],
  228. 'priceType' => 1,
  229. );
  230. if ($goods_info['minipro_live_goods_state'] == 2) {
  231. $goods_data['price'] = $goods_info['goods_price'];
  232. }
  233. if ($goods_info['minipro_live_goods_state'] == 0) {
  234. if ($goods_info['goods_image'] != $goods_info['goods_image2']) {
  235. //上传临时素材
  236. $goods_image = str_replace(UPLOAD_SITE_URL, BASE_UPLOAD_PATH, goods_thumb($goods_info));
  237. $image_path = pathinfo($goods_image, PATHINFO_DIRNAME);
  238. $image_name = pathinfo($goods_image, PATHINFO_BASENAME);
  239. if (!strstr($image_name, '_240')) {
  240. create_albumpic_thumb($image_path, $image_name);
  241. $goods_image = str_ireplace('.', '_240.', $image_name);
  242. }
  243. $res = $wechat_model->uploadMedia('image', $goods_image, "image/jpeg", $image_name);
  244. if (!$res['code']) {
  245. $this->log('上传临时素材失败' . $res['msg']);
  246. continue;
  247. }
  248. $coverImgUrl = $res['data'];
  249. $goods_data['coverImgUrl'] = $coverImgUrl;
  250. }
  251. $goods_data['name'] = mb_substr($goods_info['goods_name'], 0, 14); //商品名称,最长14个汉字
  252. $goods_data['price'] = $goods_info['goods_price'];
  253. }
  254. $data = array(
  255. 'goodsInfo' => $goods_data
  256. );
  257. $res = http_request('https://api.weixin.qq.com/wxaapi/broadcast/goods/update?access_token=' . $accessToken, 'POST', $data);
  258. $res = json_decode($res, true);
  259. if (!$res || $res['errcode']) {
  260. $this->log(isset($res['errmsg']) ? $res['errmsg'] : '更新商品出错,错误码:' . $res['errcode']);
  261. continue;
  262. }
  263. $minipro_live_goods_model->editMiniproLiveGoods(array(
  264. 'goods_name' => $goods_info['goods_name'],
  265. 'goods_price' => $goods_info['goods_price'],
  266. 'goods_image' => $goods_info['goods_image'],
  267. ), array(array('minipro_live_goods_result_id', '=', $goods_info['minipro_live_goods_result_id'])));
  268. }
  269. //未审核的商品ID不存在的更新
  270. $subQuery = Db::name('goods')->field('goods_id')->where('1=1')->buildSql();
  271. $goods_list = Db::name('minipro_live_goods')->where(array(array('minipro_live_goods_close', '=', 0), array('minipro_live_goods_state', '=', 0), array('goods_id', 'not in', Db::raw($subQuery))))->limit(100)->select()->toArray();
  272. foreach ($goods_list as $goods_info) {
  273. $goods_id = Db::name('goods')->where(array(array('goods_commonid', '=', $goods_info['goods_commonid'])))->order('goods_id asc')->value('goods_id');
  274. if (!$goods_id) {
  275. $this->log('商品不存在');
  276. continue;
  277. }
  278. $goods_data = array(
  279. 'goodsId' => $goods_info['minipro_live_goods_result_id'],
  280. 'url' => 'pages/index/index?ret_url=' . urlencode(config('ds_config.h5_site_url') . '/pages/home/goodsdetail/Goodsdetail?goods_id=' . $goods_id)
  281. );
  282. $data = array(
  283. 'goodsInfo' => $goods_data
  284. );
  285. $res = http_request('https://api.weixin.qq.com/wxaapi/broadcast/goods/update?access_token=' . $accessToken, 'POST', $data);
  286. $res = json_decode($res, true);
  287. if (!$res || $res['errcode']) {
  288. $this->log(isset($res['errmsg']) ? $res['errmsg'] : '更新商品出错,错误码:' . $res['errcode']);
  289. continue;
  290. }
  291. $minipro_live_goods_model->editMiniproLiveGoods(array(
  292. 'goods_id' => $goods_id,
  293. ), array(array('minipro_live_goods_result_id', '=', $goods_info['minipro_live_goods_result_id'])));
  294. }
  295. }
  296. /*
  297. * 小程序直播商品状态查询(调用额度:1000次/一天)
  298. */
  299. function _minipro_live_goods_state()
  300. {
  301. if (intval(config('ds_config.live_type')) != 1) {
  302. return;
  303. }
  304. //审核时间为1~7天
  305. $wechat_model = model('wechat');
  306. $wechat_model->getOneWxconfig();
  307. $accessToken = $wechat_model->getAccessToken('miniprogram', 0);
  308. if ($wechat_model->error_code) {
  309. $this->log('获取小程序AccessToken失败' . $wechat_model->error_message);
  310. return;
  311. }
  312. $ids = Db::name('minipro_live_goods')->where(array(array('minipro_live_goods_close', '=', 0), array('minipro_live_goods_state', '=', 0)))->limit(200)->column('minipro_live_goods_result_id');
  313. if (!empty($ids)) {
  314. $data = array(
  315. 'goods_ids' => $ids
  316. );
  317. $res = http_request('https://api.weixin.qq.com/wxa/business/getgoodswarehouse?access_token=' . $accessToken, 'POST', json_encode($data));
  318. $res = json_decode($res, true);
  319. if (!$res || $res['errcode']) {
  320. $this->log('小程序直播商品状态查询失败' . (isset($res['errmsg']) ? $res['errmsg'] : ',错误码:' . $res['errcode']));
  321. return;
  322. }
  323. $minipro_live_goods_model = model('minipro_live_goods');
  324. foreach ($res['goods'] as $val) {
  325. if (in_array($val['audit_status'], array(2, 3))) {
  326. $minipro_live_goods_model->editMiniproLiveGoods(array('minipro_live_goods_state' => $val['audit_status']), array(array('minipro_live_goods_result_id', '=', $val['goods_id'])));
  327. }
  328. }
  329. }
  330. }
  331. /*
  332. * 店铺到期关闭
  333. */
  334. function _store_auto_close()
  335. {
  336. $store_model = model('store');
  337. $condition = array();
  338. $condition[] = array('store_state', '=', 1);
  339. $condition[] = array('store_endtime', '>', 0);
  340. $condition[] = array('store_endtime', '<', TIMESTAMP);
  341. $store_ids = Db::name('store')->where($condition)->limit(100)->column('store_id');
  342. $goods_model = model('goods');
  343. foreach ($store_ids as $store_id) {
  344. Db::startTrans();
  345. try {
  346. $store_model->editStore(array('store_state' => 0, 'store_recommend' => 0), array(array('store_id', '=', $store_id)));
  347. //根据店铺状态修改该店铺所有商品状态
  348. $goods_model->editProducesOffline(array(array('store_id', '=', $store_id)));
  349. } catch (\Exception $e) {
  350. Db::rollback();
  351. $this->log('到期店铺关闭失败[店铺ID:' . $store_id . ']' . $e->getMessage());
  352. }
  353. Db::commit();
  354. }
  355. }
  356. /*
  357. * 生成店铺结算单
  358. */
  359. public function _creat_bill()
  360. {
  361. //搜索商家结算日期小于当前时间减结算周期的所有商家,每次100个
  362. $store_ids = Db::name('store')->where(array(array('store_bill_time', '<', strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400)))->limit(100)->column('store_id');
  363. $storemoneylog_mod = model('storemoneylog');
  364. $orderinviter_model = model('orderinviter');
  365. $bill_model = model('bill');
  366. $trade_model = model('trade');
  367. $order_refund_day = intval($trade_model->getMaxDay('order_refund'));
  368. $order_refund_time = strtotime(date('Y-m-d 0:0:0')) - $order_refund_day * 86400;
  369. $vr_order_refund_day = intval(config('ds_config.code_invalid_refund'));
  370. $vr_order_refund_time = strtotime(date('Y-m-d 0:0:0')) - $vr_order_refund_day * 86400;
  371. foreach ($store_ids as $store_id) {
  372. Db::startTrans();
  373. $store_info = Db::name('store')->where('store_id', $store_id)->field('store_id,store_name,seller_name,is_platform_store,store_bill_time')->lock(true)->find();
  374. if ($store_info) {
  375. try {
  376. $data = array();
  377. //如果店铺没有结算过,则查询与结算单相关项目的最小时间作为结算单开始时间
  378. if (!$store_info['store_bill_time']) {
  379. $ob_startdate = 0;
  380. $storecost_time = Db::name('storecost')->where(array(array('storecost_store_id', '=', $store_id), array('storecost_state', '=', 0), array('storecost_time', '<', strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400)))->order('storecost_time asc')->lock(true)->value('storecost_time');
  381. //取结算时间和退款过期时间的较小者
  382. $temp_time = $order_refund_time;
  383. if ($temp_time > (strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400)) {
  384. $temp_time = strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400;
  385. }
  386. $order_time = Db::name('order')->where(array(array('store_id', '=', $store_id), array('order_state', '=', ORDER_STATE_SUCCESS), array('delay_time', '<', $temp_time), array('payment_code', '<>', 'offline'), array('ob_no', '=', 0)))->order('add_time asc')->lock(true)->value('add_time');
  387. //不允许退款且超过使用期限的、允许退款且超过可退款期限、允许退款并且全部完成退款的虚拟订单
  388. $vr_order_time = Db::name('vrorder')->where(array(array('store_id', '=', $store_id), array('order_state', '=', ORDER_STATE_SUCCESS), array('finnshed_time', '<', strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400), array('ob_no', '=', 0)))->where('((vr_invalid_refund=0) || (vr_invalid_refund=1 AND vr_indate<' . $vr_order_refund_time . ') || (vr_invalid_refund=1 AND refund_state=2))')->order('add_time asc')->lock(true)->value('add_time');
  389. $ob_startdate = (!$ob_startdate || ($ob_startdate && $storecost_time && $storecost_time < $ob_startdate)) ? $storecost_time : $ob_startdate;
  390. $ob_startdate = (!$ob_startdate || ($ob_startdate && $order_time && $order_time < $ob_startdate)) ? $order_time : $ob_startdate;
  391. $ob_startdate = (!$ob_startdate || ($ob_startdate && $vr_order_time && $vr_order_time < $ob_startdate)) ? $vr_order_time : $ob_startdate;
  392. } else {
  393. $ob_startdate = $store_info['store_bill_time'];
  394. }
  395. if ($ob_startdate) {
  396. //零点开始
  397. $ob_startdate = strtotime(date('Y-m-d 0:0:0', $ob_startdate));
  398. $ob_enddate = $ob_startdate + intval(config('ds_config.store_bill_cycle')) * 86400;
  399. //店铺促销活动费用
  400. $storecost_sum = Db::name('storecost')->where(array(array('storecost_store_id', '=', $store_id), array('storecost_state', '=', 0), array('storecost_time', '<', $ob_enddate)))->field('SUM(storecost_price) AS ob_store_cost_totals,COUNT(*) AS count')->lock(true)->find();
  401. //取结算时间和退款过期时间的较小者
  402. $temp_time = $order_refund_time;
  403. if ($temp_time > $ob_enddate) {
  404. $temp_time = $ob_enddate;
  405. }
  406. $order_ids = Db::name('order')->where(array(array('store_id', '=', $store_id), array('order_state', '=', ORDER_STATE_SUCCESS), array('delay_time', '<', $temp_time), array('payment_code', '<>', 'offline'), array('ob_no', '=', 0)))->lock(true)->column('order_id');
  407. $vr_order_ids = Db::name('vrorder')->where(array(array('store_id', '=', $store_id), array('order_state', '=', ORDER_STATE_SUCCESS), array('finnshed_time', '<', $temp_time), array('ob_no', '=', 0)))->where('((vr_invalid_refund=0) || (vr_invalid_refund=1 AND vr_indate<' . $vr_order_refund_time . ') || (vr_invalid_refund=1 AND refund_state=2))')->lock(true)->column('order_id');
  408. if ($storecost_sum && $storecost_sum['count']) {
  409. $data['ob_store_cost_totals'] = $storecost_sum['ob_store_cost_totals'];
  410. }
  411. if ($order_ids) {
  412. //查看相关订单是否有未完成的退款
  413. $r_order_ids = Db::name('refundreturn')->where('order_id', 'in', $order_ids)->where('refund_state', 'not in', [3, 4])->lock(true)->column('order_id');
  414. if ($r_order_ids) {
  415. $order_ids = array_diff($order_ids, $r_order_ids);
  416. }
  417. //如果全部为待处理退款的订单,则不生成结算单,等退款完成再处理
  418. if ($order_ids) {
  419. //结算订单金额,结算运费,结算退单金额
  420. $order_sum = Db::name('order')->where('order_id', 'in', $order_ids)->field('SUM(order_amount) AS ob_order_totals,SUM(shipping_fee) AS ob_shipping_totals,SUM(refund_amount) AS ob_order_return_totals')->lock(true)->find();
  421. //结算平台代金券金额
  422. $ob_mall_voucher_totals = Db::name('ordercommon')->where('order_id', 'in', $order_ids)->field('SUM(mallvoucher_price) AS ob_mall_voucher_totals')->lock(true)->find();
  423. //结算佣金金额
  424. $ordergoods_sum = Db::name('ordergoods')->where('order_id', 'in', $order_ids)->field('SUM(ROUND(goods_pay_price*commis_rate/100,2)) AS ob_commis_totals')->lock(true)->find();
  425. //结算退还佣金,部分退款的
  426. $refundreturn_sum_1 = Db::name('refundreturn')->alias('refundreturn')->join('ordergoods ordergoods', 'refundreturn.order_goods_id = ordergoods.rec_id')->where('refundreturn.order_id', 'in', $order_ids)->where('refundreturn.refund_state', 3)->where('refundreturn.seller_state', 2)->where('refundreturn.order_goods_id', '>', 0)->field('SUM(ROUND(refundreturn.refund_amount*ordergoods.commis_rate/100,2)) AS ob_commis_return_totals')->lock(true)->find();
  427. $refundreturn_sum_2 = array();
  428. $refundreturn_rec_ids_2 = Db::name('refundreturn')->where('order_id', 'in', $order_ids)->where('refund_state', 3)->where('seller_state', 2)->where('order_goods_id', 0)->lock(true)->column('order_id');
  429. if ($refundreturn_rec_ids_2) {
  430. $refundreturn_sum_2 = Db::name('ordergoods')->where('order_id', 'in', $refundreturn_rec_ids_2)->field('SUM(ROUND(goods_pay_price*commis_rate/100,2)) AS ob_commis_return_totals')->lock(true)->find();
  431. }
  432. foreach ($order_ids as $order_id) {
  433. $orderinviter_model->giveMoney($order_id, 0);
  434. }
  435. //分销的佣金
  436. $orderinviter_sum = Db::name('orderinviter')->where('orderinviter_order_id', 'in', $order_ids)->where('orderinviter_valid', 1)->where('orderinviter_order_type', 0)->field('SUM(orderinviter_money) AS ob_inviter_totals')->lock(true)->find();
  437. $data['ob_order_totals'] = $order_sum['ob_order_totals'];
  438. $data['ob_shipping_totals'] = $order_sum['ob_shipping_totals'];
  439. $data['ob_order_return_totals'] = $order_sum['ob_order_return_totals'];
  440. $data['ob_commis_totals'] = $ordergoods_sum['ob_commis_totals'];
  441. $data['ob_commis_return_totals'] = bcadd(((!empty($refundreturn_sum_1)) ? $refundreturn_sum_1['ob_commis_return_totals'] : 0), ((!empty($refundreturn_sum_2)) ? $refundreturn_sum_2['ob_commis_return_totals'] : 0), 2);
  442. $data['ob_inviter_totals'] = (!empty($orderinviter_sum)) ? $orderinviter_sum['ob_inviter_totals'] : 0;
  443. }
  444. }
  445. if ($vr_order_ids) {
  446. foreach ($vr_order_ids as $order_id) {
  447. $orderinviter_model->giveMoney($order_id, 1);
  448. }
  449. //分销的佣金
  450. $orderinviter_sum = Db::name('orderinviter')->where('orderinviter_order_id', 'in', $vr_order_ids)->where('orderinviter_valid', 1)->where('orderinviter_order_type', 1)->field('SUM(orderinviter_money) AS ob_vr_inviter_totals')->lock(true)->find();
  451. $vr_order_sum = Db::name('vrorder')->where('order_id', 'in', $vr_order_ids)->field('SUM(order_amount) AS ob_vr_order_totals,SUM(ROUND(order_amount*commis_rate/100,2)) AS ob_vr_commis_totals,SUM(refund_amount) AS ob_vr_order_return_totals,SUM(ROUND(refund_amount*commis_rate/100,2)) AS ob_vr_commis_return_totals')->lock(true)->find();
  452. $data['ob_vr_order_totals'] = $vr_order_sum['ob_vr_order_totals'];
  453. $data['ob_vr_commis_totals'] = $vr_order_sum['ob_vr_commis_totals'];
  454. $data['ob_vr_order_return_totals'] = $vr_order_sum['ob_vr_order_return_totals'];
  455. $data['ob_vr_commis_return_totals'] = $vr_order_sum['ob_vr_commis_return_totals'];
  456. $data['ob_vr_inviter_totals'] = (!empty($orderinviter_sum)) ? $orderinviter_sum['ob_vr_inviter_totals'] : 0;
  457. }
  458. if (!empty($data)) {
  459. $data['ob_createdate'] = TIMESTAMP;
  460. $data['ob_startdate'] = $ob_startdate;
  461. $data['ob_enddate'] = $ob_enddate;
  462. $data['ob_store_id'] = $store_id;
  463. $data['ob_store_name'] = $store_info['store_name']; //平台自营店铺不需要增加店铺资金
  464. $data['ob_state'] = ($store_info['is_platform_store'] == 1) ? 4 : 1;
  465. $data['ob_mall_voucher_totals'] = 0;
  466. if (!isset($data['ob_order_totals'])) {
  467. $data['ob_order_totals'] = 0;
  468. }
  469. if (!isset($data['ob_store_cost_totals'])) {
  470. $data['ob_store_cost_totals'] = 0;
  471. }
  472. if (!isset($data['ob_inviter_totals'])) {
  473. $data['ob_inviter_totals'] = 0;
  474. }
  475. if (!isset($data['ob_order_return_totals'])) {
  476. $data['ob_order_return_totals'] = 0;
  477. }
  478. if (!isset($data['ob_commis_totals'])) {
  479. $data['ob_commis_totals'] = 0;
  480. }
  481. if (!isset($data['ob_commis_return_totals'])) {
  482. $data['ob_commis_return_totals'] = 0;
  483. }
  484. if (!isset($data['ob_vr_order_totals'])) {
  485. $data['ob_vr_order_totals'] = 0;
  486. }
  487. if (!isset($data['ob_vr_order_return_totals'])) {
  488. $data['ob_vr_order_return_totals'] = 0;
  489. }
  490. if (!isset($data['ob_vr_commis_totals'])) {
  491. $data['ob_vr_commis_totals'] = 0;
  492. }
  493. if (!isset($data['ob_vr_commis_return_totals'])) {
  494. $data['ob_vr_commis_return_totals'] = 0;
  495. }
  496. if (!isset($data['ob_vr_inviter_totals'])) {
  497. $data['ob_vr_inviter_totals'] = 0;
  498. }
  499. if (!isset($ob_mall_voucher_totals) && !isset($vr_order_sum['ob_vr_mall_voucher_totals'])) {
  500. $data['ob_mall_voucher_totals'] = 0;
  501. } else {
  502. $data['ob_mall_voucher_totals'] = bcadd($ob_mall_voucher_totals['ob_mall_voucher_totals'], $vr_order_sum['ob_vr_mall_voucher_totals'], 2);
  503. }
  504. //计算实际可得金额
  505. $data['ob_result_totals'] = round($data['ob_order_totals'] - $data['ob_store_cost_totals'] - $data['ob_inviter_totals'] - $data['ob_order_return_totals'] - $data['ob_commis_totals'] + $data['ob_commis_return_totals'] + $data['ob_vr_order_totals'] - $data['ob_vr_order_return_totals'] - $data['ob_vr_commis_totals'] + $data['ob_vr_commis_return_totals'] - $data['ob_vr_inviter_totals'] + $data['ob_mall_voucher_totals'], 2);
  506. //插入到结算账单
  507. $ob_no = $bill_model->addOrderbill($data);
  508. if (!$ob_no) {
  509. throw new \think\Exception('新增结算单失败', 10006);
  510. }
  511. if ($order_ids) {
  512. //订单更新结算单号
  513. if (!Db::name('order')->where('order_id', 'in', $order_ids)->update(array('ob_no' => $ob_no))) {
  514. throw new \think\Exception('更新实物订单结算单号失败', 10006);
  515. }
  516. }
  517. if ($vr_order_ids) {
  518. //订单更新结算单号
  519. if (!Db::name('vrorder')->where('order_id', 'in', $vr_order_ids)->update(array('ob_no' => $ob_no))) {
  520. throw new \think\Exception('更新虚拟订单结算单号失败', 10006);
  521. }
  522. }
  523. }
  524. //店铺活动改成已结算
  525. if (!empty($storecost_sum) && $storecost_sum['count'] && !Db::name('storecost')->where(array(array('storecost_store_id', '=', $store_id), array('storecost_state', '=', 0), array('storecost_time', '<', $ob_enddate)))->update(array('storecost_state' => 1))) {
  526. throw new \think\Exception('更新店铺活动结算单号失败', 10006);
  527. }
  528. } else {
  529. $ob_enddate = strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400;
  530. }
  531. //更新店铺结算时间
  532. if (!Db::name('store')->where('store_id', $store_id)->update(array('store_bill_time' => $ob_enddate))) {
  533. throw new \think\Exception('更新店铺结算时间失败', 10006);
  534. }
  535. } catch (\Exception $e) {
  536. Db::rollback();
  537. $this->log('[店铺名称:' . $store_info['store_name'] . ']' . $e->getMessage());
  538. }
  539. }
  540. Db::commit();
  541. }
  542. //如果还有未更新结算日期的店铺,则重定向继续生产结算单
  543. if (Db::name('store')->where(array(array('store_bill_time', '<', strtotime(date('Y-m-d 0:0:0')) - intval(config('ds_config.store_bill_cycle')) * 86400)))->count() > 0) {
  544. $this->redirect('date/index');
  545. }
  546. }
  547. /**
  548. * 未付款订单超期自动关闭
  549. */
  550. private function _order_timeout_cancel()
  551. {
  552. //实物订单超期未支付系统自动关闭
  553. $_break = false;
  554. $chain_order_model = model('chain_order');
  555. $order_model = model('order');
  556. $logic_order = model('order', 'logic');
  557. $condition = array();
  558. $condition[] = array('order_state', '=', ORDER_STATE_NEW);
  559. $condition[] = array('add_time', '<', TIMESTAMP - config('ds_config.order_auto_cancel_day') * self::EXE_TIMES);
  560. //分批,每批处理100个订单,最多处理5W个订单
  561. for ($i = 0; $i < 500; $i++) {
  562. if ($_break) {
  563. break;
  564. }
  565. $order_list = $order_model->getOrderList($condition, '', '*', '', 100);
  566. if (empty($order_list))
  567. break;
  568. foreach ($order_list as $order_info) {
  569. try {
  570. Db::startTrans();
  571. $logic_order->changeOrderStateCancel($order_info, 'system', '系统', '超期未支付系统自动关闭订单', true, false);
  572. } catch (\Exception $e) {
  573. Db::rollback();
  574. $this->log('实物订单超期未支付关闭失败SN:' . $order_info['order_sn']);
  575. $_break = true;
  576. break;
  577. }
  578. Db::commit();
  579. }
  580. }
  581. //虚拟订单超期未支付系统自动关闭
  582. $_break = false;
  583. $vrorder_model = model('vrorder');
  584. $logic_vrorder = model('vrorder', 'logic');
  585. $condition = array();
  586. $condition[] = array('order_state', '=', ORDER_STATE_NEW);
  587. $condition[] = array('add_time', '<', TIMESTAMP - config('ds_config.order_auto_cancel_day') * self::EXE_TIMES);
  588. //分批,每批处理100个订单,最多处理5W个订单
  589. for ($i = 0; $i < 500; $i++) {
  590. if ($_break) {
  591. break;
  592. }
  593. $order_list = $vrorder_model->getVrorderList($condition, '', '*', '', 100);
  594. if (empty($order_list))
  595. break;
  596. foreach ($order_list as $order_info) {
  597. $result = $logic_vrorder->changeOrderStateCancel($order_info, 'system', '超期未支付系统自动关闭订单', false);
  598. }
  599. if (!$result['code']) {
  600. $this->log('虚拟订单超期未支付关闭失败SN:' . $order_info['order_sn']);
  601. $_break = true;
  602. break;
  603. }
  604. }
  605. }
  606. /**
  607. * 订单自动完成
  608. */
  609. private function _order_auto_complete()
  610. {
  611. //虚拟订单过使用期自动完成
  612. $_break = false;
  613. $vrorder_model = model('vrorder');
  614. $logic_vrorder = model('vrorder', 'logic');
  615. $condition = array();
  616. $condition[] = array('order_state', '=', ORDER_STATE_PAY);
  617. $condition[] = array('vr_indate', '<', TIMESTAMP);
  618. //分批,每批处理100个订单,最多处理5W个订单
  619. for ($i = 0; $i < 500; $i++) {
  620. if ($_break) {
  621. break;
  622. }
  623. $order_list = $vrorder_model->getVrorderList($condition, '', 'order_id,order_sn', 'vr_indate asc', 100);
  624. if (empty($order_list))
  625. break;
  626. foreach ($order_list as $order_info) {
  627. $result = $logic_vrorder->changeOrderStateSuccess($order_info['order_id']);
  628. if (!$result['code']) {
  629. $this->log('虚拟订单过使用期自动完成失败SN:' . $order_info['order_sn']);
  630. $_break = true;
  631. break;
  632. }
  633. }
  634. }
  635. //实物订单发货后,超期自动收货完成
  636. $_break = false;
  637. $order_model = model('order');
  638. $logic_order = model('order', 'logic');
  639. $condition = array();
  640. $condition[] = array('order_state', '=', ORDER_STATE_SEND);
  641. $condition[] = array('lock_state', '=', 0);
  642. $condition[] = array('delay_time', '<', TIMESTAMP - config('ds_config.order_auto_receive_day') * 86400);
  643. //分批,每批处理100个订单,最多处理5W个订单
  644. for ($i = 0; $i < 500; $i++) {
  645. if ($_break) {
  646. break;
  647. }
  648. $order_list = $order_model->getOrderList($condition, '', '*', 'delay_time asc', 100);
  649. if (empty($order_list))
  650. break;
  651. foreach ($order_list as $order_info) {
  652. $result = $logic_order->changeOrderStateReceive($order_info, 'system', '系统', '超期未收货系统自动完成订单');
  653. if (!$result['code']) {
  654. $this->log('实物订单超期未收货自动完成订单失败SN:' . $order_info['order_sn']);
  655. $_break = true;
  656. break;
  657. }
  658. }
  659. }
  660. }
  661. /**
  662. * 更新订单扩展表中收货人所在省份ID
  663. */
  664. private function _order_reciver_provinceid_update()
  665. {
  666. $order_model = model('order');
  667. $area_model = model('area');
  668. //每次最多处理5W个订单
  669. $condition = array();
  670. $condition[] = array('reciver_province_id', '=', 0);
  671. $condition[] = array('reciver_city_id', '<>', 0);
  672. for ($i = 0; $i < 500; $i++) {
  673. $order_list = $order_model->getOrdercommonList($condition, 'reciver_city_id', 'order_id desc', 100);
  674. if (!empty($order_list)) {
  675. $city_ids = array();
  676. foreach ($order_list as $v) {
  677. if (!in_array($v['reciver_city_id'], $city_ids)) {
  678. $city_ids[] = $v['reciver_city_id'];
  679. }
  680. }
  681. $area_list = $area_model->getAreaList(array(array('area_id', 'in', $city_ids)), 'area_parent_id,area_id');
  682. if (!empty($area_list)) {
  683. foreach ($area_list as $v) {
  684. $update = $order_model->editOrdercommon(array('reciver_province_id' => $v['area_parent_id']), array('reciver_city_id' => $v['area_id']));
  685. if (!$update) {
  686. $this->log('更新订单扩展表中收货人所在省份ID失败');
  687. break;
  688. }
  689. }
  690. }
  691. } else {
  692. break;
  693. }
  694. }
  695. }
  696. /**
  697. * 增加会员积分和经验值
  698. */
  699. private function _add_points()
  700. {
  701. return;
  702. $points_model = model('points');
  703. $exppoints_model = model('exppoints');
  704. //24小时之内登录的会员送积分和经验值,每次最多处理5W个会员
  705. $member_model = model('member');
  706. $condition = array();
  707. $condition[] = array('member_logintime', '>', TIMESTAMP - self::EXE_TIMES);
  708. for ($i = 0; $i < 50000; $i = $i + 100) {
  709. $member_list = $member_model->getMemberList($condition, 'member_name,member_id', 0, '', "{$i},100");
  710. if (!empty($member_list)) {
  711. foreach ($member_list as $member_info) {
  712. if (config('ds_config.points_isuse')) {
  713. $points_model->savePointslog('login', array('pl_memberid' => $member_info['member_id'], 'pl_membername' => $member_info['member_name']), true);
  714. }
  715. $exppoints_model->saveExppointslog('login', array('explog_memberid' => $member_info['member_id'], 'explog_membername' => $member_info['member_name']), true);
  716. }
  717. } else {
  718. break;
  719. }
  720. }
  721. //24小时之内注册的会员送积分,每次最多处理5W个会员
  722. if (config('ds_config.points_isuse')) {
  723. $condition = array();
  724. $condition[] = array('member_addtime', '>', TIMESTAMP - self::EXE_TIMES);
  725. for ($i = 0; $i < 50000; $i = $i + 100) {
  726. $member_list = $member_model->getMemberList($condition, 'member_name,member_id', 0, 'member_id desc', "{$i},100");
  727. if (!empty($member_list)) {
  728. foreach ($member_list as $member_info) {
  729. $points_model->savePointslog('regist', array('pl_memberid' => $member_info['member_id'], 'pl_membername' => $member_info['member_name']), true);
  730. }
  731. } else {
  732. break;
  733. }
  734. }
  735. }
  736. //24小时之内完成了实物订单送积分和经验值,每次最多处理5W个订单
  737. $order_model = model('order');
  738. $condition = array();
  739. $condition[] = array('finnshed_time', '>', TIMESTAMP - self::EXE_TIMES);
  740. for ($i = 0; $i < 50000; $i = $i + 100) {
  741. $order_list = $order_model->getOrderList($condition, '', 'buyer_name,buyer_id,order_amount,order_sn,order_id', '', "{$i},100");
  742. if (!empty($order_list)) {
  743. foreach ($order_list as $order_info) {
  744. if (config('ds_config.points_isuse')) {
  745. $points_model->savePointslog('order', array('pl_memberid' => $order_info['buyer_id'], 'pl_membername' => $order_info['buyer_name'], 'orderprice' => $order_info['order_amount'], 'order_sn' => $order_info['order_sn'], 'order_id' => $order_info['order_id']), true);
  746. }
  747. $exppoints_model->saveExppointslog('order', array('explog_memberid' => $order_info['buyer_id'], 'explog_membername' => $order_info['buyer_name'], 'orderprice' => $order_info['order_amount'], 'order_sn' => $order_info['order_sn'], 'order_id' => $order_info['order_id']), true);
  748. }
  749. } else {
  750. break;
  751. }
  752. }
  753. //24小时之内完成了实物订单送积分和经验值,每次最多处理5W个订单
  754. $vrorder_model = model('vrorder');
  755. $condition = array();
  756. $condition[] = array('finnshed_time', '>', TIMESTAMP - self::EXE_TIMES);
  757. for ($i = 0; $i < 50000; $i = $i + 100) {
  758. $order_list = $vrorder_model->getVrorderList($condition, '', 'buyer_name,buyer_id,order_amount,order_sn,order_id', '', "{$i},100");
  759. if (!empty($order_list)) {
  760. foreach ($order_list as $order_info) {
  761. if (config('ds_config.points_isuse')) {
  762. $points_model->savePointslog('order', array('pl_memberid' => $order_info['buyer_id'], 'pl_membername' => $order_info['buyer_name'], 'orderprice' => $order_info['order_amount'], 'order_sn' => $order_info['order_sn'], 'order_id' => $order_info['order_id']), true);
  763. }
  764. $exppoints_model->saveExppointslog('order', array('explog_memberid' => $order_info['buyer_id'], 'explog_membername' => $order_info['buyer_name'], 'orderprice' => $order_info['order_amount'], 'order_sn' => $order_info['order_sn'], 'order_id' => $order_info['order_id']), true);
  765. }
  766. } else {
  767. break;
  768. }
  769. }
  770. }
  771. /**
  772. * 代金券即将过期提醒
  773. */
  774. private function _voucher_will_expire()
  775. {
  776. $time_start = mktime(0, 0, 0, date("m"), date("d") + self::VOUCHER_INTERVAL, date("Y"));
  777. $time_stop = $time_start + self::EXE_TIMES - 1;
  778. $where = array();
  779. $where[] = array('voucher_enddate', '>=', $time_start);
  780. $where[] = array('voucher_enddate', '<=', $time_stop);
  781. $list = model('voucher')->getVoucherUnusedList($where);
  782. if (!empty($list)) {
  783. foreach ($list as $val) {
  784. $param = array();
  785. $param['code'] = 'voucher_will_expire';
  786. $param['member_id'] = $val['voucher_owner_id'];
  787. $param['ali_param'] = array(
  788. 'indate' => date('Y-m-d H:i:s', $val['voucher_enddate']),
  789. );
  790. $param['ten_param'] = array(
  791. date('Y-m-d H:i:s', $val['voucher_enddate']),
  792. );
  793. $param['param'] = array_merge($param['ali_param'], array(
  794. 'voucher_url' => HOME_SITE_URL . '/Membervoucher/index'
  795. ));
  796. $param['weixin_param'] = array(
  797. 'url' => config('ds_config.h5_site_url') . '/pages/member/voucher/VoucherList',
  798. 'data' => array(
  799. "keyword1" => array(
  800. "value" => $val['voucher_code'],
  801. "color" => "#333"
  802. ),
  803. "keyword2" => array(
  804. "value" => date('Y-m-d', $val['voucher_startdate']) . '~' . date('Y-m-d', $val['voucher_enddate']),
  805. "color" => "#333"
  806. )
  807. ),
  808. );
  809. model('cron')->addCron(array('cron_exetime' => TIMESTAMP, 'cron_type' => 'sendMemberMsg', 'cron_value' => serialize($param)));
  810. }
  811. }
  812. }
  813. /**
  814. * 虚拟兑换码即将过期提醒
  815. */
  816. private function _vr_code_will_expire()
  817. {
  818. $time_start = mktime(0, 0, 0, date("m"), date("d") + self::VR_CODE_INTERVAL, date("Y"));
  819. $time_stop = $time_start + self::EXE_TIMES - 1;
  820. $where = array();
  821. $where[] = array('vr_indate', '>=', $time_start);
  822. $where[] = array('vr_indate', '<=', $time_stop);
  823. $list = model('vrorder')->getCodeUnusedList($where);
  824. if (!empty($list)) {
  825. foreach ($list as $val) {
  826. $param = array();
  827. $param['code'] = 'vr_code_will_expire';
  828. $param['member_id'] = $val['buyer_id'];
  829. $param['ali_param'] = array(
  830. 'indate' => date('Y-m-d H:i:s', $val['vr_indate']),
  831. );
  832. $param['ten_param'] = array(
  833. date('Y-m-d H:i:s', $val['vr_indate']),
  834. );
  835. $param['param'] = array_merge($param['ali_param'], array(
  836. 'vr_order_url' => HOME_SITE_URL . '/Membervrorder/index'
  837. ));
  838. $vrorder = model('vrorder')->getVrorderInfo(array('order_id' => $val['order_id']));
  839. $param['weixin_param'] = array(
  840. 'url' => config('ds_config.h5_site_url') . '/pages/member/vrorder/OrderDetail?order_id=' . $val['order_id'],
  841. 'data' => array(
  842. "keyword1" => array(
  843. "value" => (!empty($vrorder)) ? $vrorder['goods_name'] : '',
  844. "color" => "#333"
  845. ),
  846. "keyword2" => array(
  847. "value" => date('Y-m-d', $val['vr_indate']),
  848. "color" => "#333"
  849. )
  850. ),
  851. );
  852. model('cron')->addCron(array('cron_exetime' => TIMESTAMP, 'cron_type' => 'sendMemberMsg', 'cron_value' => serialize($param)));
  853. }
  854. }
  855. }
  856. /**
  857. * 订单超期后不允许评价
  858. */
  859. private function _order_eval_expire_update()
  860. {
  861. //实物订单超期未评价自动更新状态,每次最多更新1000个订单
  862. $order_model = model('order');
  863. $condition = array();
  864. $condition[] = array('order_state', '=', ORDER_STATE_SUCCESS);
  865. $condition[] = array('evaluation_state', '=', 0);
  866. $condition[] = array('finnshed_time', '<', TIMESTAMP - self::ORDER_EVALUATE_TIME);
  867. $update = array();
  868. $update['evaluation_state'] = 2;
  869. $update = $order_model->editOrder($update, $condition, 1000);
  870. if (!$update) {
  871. $this->log('更新实物订单超期不能评价失败');
  872. }
  873. //虚拟订单超期未评价自动更新状态,每次最多更新1000个订单
  874. $vrorder_model = model('vrorder');
  875. $condition = array();
  876. $condition[] = array('order_state', '=', ORDER_STATE_SUCCESS);
  877. $condition[] = array('evaluation_state', '=', 0);
  878. $condition[] = array('use_state', '=', 1);
  879. $condition[] = array('finnshed_time', '<', TIMESTAMP - self::ORDER_EVALUATE_TIME);
  880. $update = array();
  881. $update['evaluation_state'] = 2;
  882. $update = $vrorder_model->editVrorder($update, $condition, 1000);
  883. if (!$update) {
  884. $this->log('更新虚拟订单超期不能评价失败');
  885. }
  886. }
  887. /**
  888. * 更新商品访问量(redis)
  889. */
  890. private function _goods_click_update()
  891. {
  892. $data = rcache('updateRedisDate', 'goodsClick');
  893. if (is_array($data)) {
  894. foreach ($data as $key => $val) {
  895. model('goods')->editGoodsById(array('goods_click' => Db::raw('goods_click+' . $val)), $key);
  896. }
  897. }
  898. dcache('updateRedisDate', 'goodsClick');
  899. }
  900. /**
  901. * 更新商品促销到期状态(目前只有满即送)
  902. */
  903. private function _goods_promotion_state_update()
  904. {
  905. //满即送过期
  906. model('pmansong')->editExpireMansong();
  907. }
  908. /**
  909. * 商品到货通知提醒
  910. */
  911. private function _arrival_notice()
  912. {
  913. $arrivalnotice_model = model('arrivalnotice');
  914. $count = $arrivalnotice_model->getArrivalNoticeCount(array());
  915. $times = ceil($count / self::ARRIVAL_NOTICE_NUM);
  916. if ($times == 0)
  917. return false;
  918. for ($i = 0; $i <= $times; $i++) {
  919. $notice_list = $arrivalnotice_model->getArrivalNoticeList(array(), '*', $i . ',' . self::ARRIVAL_NOTICE_NUM);
  920. if (empty($notice_list))
  921. continue;
  922. // 查询商品是否已经上架
  923. $goodsid_array = array();
  924. foreach ($notice_list as $val) {
  925. $goodsid_array[] = $val['goods_id'];
  926. }
  927. $goodsid_array = array_unique($goodsid_array);
  928. $condition = array();
  929. $condition[] = array('goods_id', 'in', $goodsid_array);
  930. $condition[] = array('goods_storage', '>', 0);
  931. $goods_list = model('goods')->getGoodsOnlineList($condition, 'goods_id');
  932. if (empty($goods_list))
  933. continue;
  934. // 需要通知到货的商品
  935. $goodsid_array = array();
  936. $storage_array = array();
  937. foreach ($goods_list as $val) {
  938. $goodsid_array[] = $val['goods_id'];
  939. $storage_array[$val['goods_id']] = $val['goods_storage'];
  940. }
  941. // 根据商品id重新查询需要通知的列表
  942. $notice_list = $arrivalnotice_model->getArrivalNoticeList(array(array('goods_id', 'in', $goodsid_array)), '*');
  943. if (empty($notice_list))
  944. continue;
  945. foreach ($notice_list as $val) {
  946. $param = array();
  947. $param['code'] = 'arrival_notice';
  948. $param['member_id'] = $val['member_id'];
  949. $param['ali_param'] = array(
  950. 'goods_name' => $val['goods_name'],
  951. );
  952. $param['ten_param'] = array(
  953. $val['goods_name'],
  954. );
  955. $param['param'] = array_merge(array(
  956. 'goods_name' => $val['goods_name'],
  957. 'goods_url' => HOME_SITE_URL . '/Goods/index?goods_id=' . $val['goods_id']
  958. ));
  959. $param['number'] = array('mobile' => $val['arrivalnotice_mobile'], 'email' => $val['arrivalnotice_email']);
  960. $param['weixin_param'] = array(
  961. 'url' => config('ds_config.h5_site_url') . '/pages/home/goodsdetail/Goodsdetail?goods_id=' . $val['goods_id'],
  962. 'data' => array(
  963. "keyword1" => array(
  964. "value" => $val['goods_name'],
  965. "color" => "#333"
  966. ),
  967. "keyword2" => array(
  968. "value" => isset($storage_array[$val['goods_id']]) ? $storage_array[$val['goods_id']] : '99',
  969. "color" => "#333"
  970. ),
  971. "keyword3" => array(
  972. "value" => date('Y-m-d'),
  973. "color" => "#333"
  974. )
  975. ),
  976. );
  977. model('cron')->addCron(array('cron_exetime' => TIMESTAMP, 'cron_type' => 'sendMemberMsg', 'cron_value' => serialize($param)));
  978. }
  979. // 清楚发送成功的数据
  980. $arrivalnotice_model->editArrivalNotice(['arrivalnotice_state' => 2, 'arrivalnotice_time' => TIMESTAMP], array(array('goods_id', 'in', $goodsid_array)));
  981. }
  982. }
  983. /**
  984. * 将缓存中的浏览记录存入数据库中,并删除30天前的浏览历史
  985. */
  986. private function _goods_browse_update()
  987. {
  988. $goodsbrowse_model = model('goodsbrowse');
  989. //将cache中的记录存入数据库
  990. //如果浏览记录已经存入了缓存中,则将其整理到数据库中
  991. //上次更新缓存的时间
  992. $latest_record = $goodsbrowse_model->getOneGoodsbrowse(array(), '', 'goodsbrowse_time desc');
  993. $starttime = ($t = intval($latest_record['goodsbrowse_time'])) ? $t : 0;
  994. $monthago = strtotime(date('Y-m-d', TIMESTAMP)) - 86400 * 30;
  995. $member_model = model('member');
  996. //查询会员信息总条数
  997. $countnum = $member_model->getMemberCount(array());
  998. $eachnum = 100;
  999. for ($i = 0; $i < $countnum; $i += $eachnum) { //每次查询100条
  1000. $member_list = $member_model->getMemberList(array(), '*', 0, 'member_id asc', "$i,$eachnum");
  1001. foreach ((array) $member_list as $k => $v) {
  1002. $insert_arr = array();
  1003. $goodsid_arr = array();
  1004. //生成缓存的键值
  1005. $hash_key = $v['member_id'];
  1006. $browse_goodsid = rcache($hash_key, 'goodsbrowse');
  1007. if ($browse_goodsid) {
  1008. //删除缓存中多余的浏览历史记录,仅保留最近的30条浏览历史,先取出最近30条浏览历史的商品ID
  1009. $cachegoodsid_arr = $browse_goodsid['goodsid'] ? unserialize($browse_goodsid['goodsid']) : array();
  1010. unset($browse_goodsid['goodsid']);
  1011. if ($cachegoodsid_arr) {
  1012. $cachegoodsid_arr = array_slice($cachegoodsid_arr, -30, 30, true);
  1013. }
  1014. //处理存入数据库的浏览历史缓存信息
  1015. $_cache = rcache($hash_key, 'goodsbrowse');
  1016. foreach ((array) $_cache as $c_k => $c_v) {
  1017. $c_v = unserialize($c_v);
  1018. if (isset($c_v['goodsbrowse_time']) && $c_v['goodsbrowse_time'] >= $starttime) { //如果 缓存中的数据未更新到数据库中(即添加时间大于上次更新到数据库中的数据时间)则将数据更新到数据库中
  1019. $tmp_arr = array();
  1020. $tmp_arr['goods_id'] = $c_v['goods_id'];
  1021. $tmp_arr['member_id'] = $v['member_id'];
  1022. $tmp_arr['goodsbrowse_time'] = $c_v['goodsbrowse_time'];
  1023. $tmp_arr['gc_id'] = $c_v['gc_id'];
  1024. $tmp_arr['gc_id_1'] = $c_v['gc_id_1'];
  1025. $tmp_arr['gc_id_2'] = $c_v['gc_id_2'];
  1026. $tmp_arr['gc_id_3'] = $c_v['gc_id_3'];
  1027. $insert_arr[] = $tmp_arr;
  1028. $goodsid_arr[] = $c_v['goods_id'];
  1029. }
  1030. //除了最近的30条浏览历史之外多余的浏览历史记录或者30天之前的浏览历史从缓存中删除
  1031. if (!in_array($c_v['goods_id'], $cachegoodsid_arr) || $c_v['goodsbrowse_time'] < $monthago) {
  1032. unset($_cache[$c_k]);
  1033. }
  1034. }
  1035. //删除已经存在的该商品浏览记录
  1036. if ($goodsid_arr) {
  1037. $condition = array();
  1038. $condition[] = array('member_id', '=', $v['member_id']);
  1039. $condition[] = array('goods_id', 'in', $goodsid_arr);
  1040. $goodsbrowse_model->delGoodsbrowse($condition);
  1041. }
  1042. //将缓存中的浏览历史存入数据库
  1043. if ($insert_arr) {
  1044. $goodsbrowse_model->addGoodsbrowseAll($insert_arr);
  1045. }
  1046. //重新赋值浏览历史缓存
  1047. dcache($hash_key, 'goodsbrowse');
  1048. $_cache['goodsid'] = serialize($cachegoodsid_arr);
  1049. wcache($hash_key, $_cache, 'goodsbrowse');
  1050. }
  1051. }
  1052. }
  1053. //删除30天前的浏览历史
  1054. $goodsbrowse_model->delGoodsbrowse(array(array('goodsbrowse_time', '<', $monthago)));
  1055. }
  1056. /**
  1057. * 缓存订单及订单商品相关数据
  1058. */
  1059. private function _order_goods_cache()
  1060. {
  1061. //查询最后统计的记录
  1062. $latest_record = Db::name('statordergoods')->order('stat_updatetime desc,rec_id desc')->find();
  1063. $stime = 0;
  1064. if ($latest_record) {
  1065. $start_time = strtotime(date('Y-m-d', $latest_record['stat_updatetime']));
  1066. } else {
  1067. $start_time = strtotime(date('Y-m-d', strtotime(config('ds_config.setup_date')))); //从系统的安装时间开始统计
  1068. }
  1069. for ($stime = $start_time; $stime < TIMESTAMP; $stime = $stime + 86400) {
  1070. $etime = $stime + 86400 - 1;
  1071. //避免重复统计,开始时间必须大于最后一条记录的记录时间
  1072. $search_stime = $latest_record['stat_updatetime'] > $stime ? $latest_record['stat_updatetime'] : $stime;
  1073. //统计一天的数据,如果结束时间大于当前时间,则结束时间为当前时间,避免因为查询时间的延迟造成数据遗落
  1074. $search_etime = ($t = ($stime + 86400 - 1)) > TIMESTAMP ? TIMESTAMP : ($stime + 86400 - 1);
  1075. //查询时间段内新订单或者更新过的订单,在缓存表中需要将新订单和更新过的订单进行重新缓存
  1076. $where = array();
  1077. $where[] = array('log_time', 'between', array($search_stime, $search_etime));
  1078. //查询记录总条数
  1079. $countnum_arr = Db::name('orderlog')->field('COUNT(DISTINCT order_id) as countnum')->where($where)->find();
  1080. $countnum = intval($countnum_arr['countnum']);
  1081. for ($i = 0; $i < $countnum; $i += 100) { //每次查询100条
  1082. $orderlog_list = array();
  1083. $orderlog_list = Db::name('orderlog')->field('DISTINCT order_id')->where($where)->limit($i . ',100')->select()->toArray();
  1084. if ($orderlog_list) {
  1085. //店铺ID数组
  1086. $storeid_arr = array();
  1087. //商品ID数组
  1088. $goodsid_arr = array();
  1089. //商品公共表ID数组
  1090. $goods_commonid_arr = array();
  1091. //订单ID数组
  1092. $orderid_arr = array();
  1093. //整理需要缓存的订单ID
  1094. foreach ((array) $orderlog_list as $k => $v) {
  1095. $orderid_arr[] = $v['order_id'];
  1096. }
  1097. unset($orderlog_list);
  1098. //查询订单数据
  1099. $field = 'order_id,order_sn,store_id,buyer_id,buyer_name,add_time,payment_code,order_amount,shipping_fee,evaluation_state,order_state,refund_state,refund_amount,order_from';
  1100. $order_list_tmp = Db::name('order')->field($field)->where('order_id', 'in', $orderid_arr)->select()->toArray();
  1101. $order_list = array();
  1102. foreach ((array) $order_list_tmp as $k => $v) {
  1103. //判读订单是否计入统计(在线支付订单已支付或者经过退款的取消订单或者货到付款订单订单已成功)
  1104. $v['order_isvalid'] = 0;
  1105. if ($v['payment_code'] != 'offline' && $v['order_state'] != ORDER_STATE_NEW && $v['order_state'] != ORDER_STATE_CANCEL) { //在线支付并且已支付并且未取消
  1106. $v['order_isvalid'] = 1;
  1107. } elseif ($v['order_state'] == ORDER_STATE_CANCEL && $v['refund_state'] != 0) { //经过退款的取消订单
  1108. $v['order_isvalid'] = 1;
  1109. } elseif ($v['payment_code'] == 'offline' && $v['order_state'] == ORDER_STATE_SUCCESS) { //货到付款订单,订单成功之后才计入统计
  1110. $v['order_isvalid'] = 1;
  1111. }
  1112. $order_list[$v['order_id']] = $v;
  1113. $storeid_arr[] = $v['store_id'];
  1114. }
  1115. unset($order_list_tmp);
  1116. //查询订单扩展数据
  1117. $field = 'order_id,reciver_province_id';
  1118. $order_common_list_tmp = Db::name('ordercommon')->field($field)->where('order_id', 'in', $orderid_arr)->select()->toArray();
  1119. $order_common_list = array();
  1120. foreach ((array) $order_common_list_tmp as $k => $v) {
  1121. $order_common_list[$v['order_id']] = $v;
  1122. }
  1123. unset($order_common_list_tmp);
  1124. //查询店铺信息
  1125. $field = 'store_id,store_name,grade_id,storeclass_id';
  1126. $store_list_tmp = Db::name('store')->field($field)->where('store_id', 'in', $storeid_arr)->select()->toArray();
  1127. $store_list = array();
  1128. foreach ((array) $store_list_tmp as $k => $v) {
  1129. $store_list[$v['store_id']] = $v;
  1130. }
  1131. unset($store_list_tmp);
  1132. //查询订单商品
  1133. $field = 'rec_id,order_id,goods_id,goods_name,goods_price,goods_num,goods_image,goods_pay_price,store_id,buyer_id,goods_type,promotions_id,commis_rate,gc_id';
  1134. $ordergoods_list = Db::name('ordergoods')->field($field)->where('order_id', 'in', $orderid_arr)->select()->toArray();
  1135. foreach ((array) $ordergoods_list as $k => $v) {
  1136. $goodsid_arr[] = $v['goods_id'];
  1137. }
  1138. //查询商品信息
  1139. $field = 'goods_id,goods_commonid,goods_price,goods_serial,gc_id,gc_id_1,gc_id_2,gc_id_3,goods_image';
  1140. $goods_list_tmp = Db::name('goods')->field($field)->where('goods_id', 'in', $goodsid_arr)->select()->toArray();
  1141. foreach ((array) $goods_list_tmp as $k => $v) {
  1142. $goods_commonid_arr[] = $v['goods_commonid'];
  1143. }
  1144. //查询商品公共信息
  1145. $field = 'goods_commonid,goods_name,brand_id,brand_name';
  1146. $goods_common_list_tmp = Db::name('goodscommon')->field($field)->where('goods_commonid', 'in', $goods_commonid_arr)->select()->toArray();
  1147. $goods_common_list = array();
  1148. foreach ((array) $goods_common_list_tmp as $k => $v) {
  1149. $goods_common_list[$v['goods_commonid']] = $v;
  1150. }
  1151. unset($goods_common_list_tmp);
  1152. //处理商品数组
  1153. $goods_list = array();
  1154. foreach ((array) $goods_list_tmp as $k => $v) {
  1155. $v['goods_commonname'] = $goods_common_list[$v['goods_commonid']]['goods_name'];
  1156. $v['brand_id'] = $goods_common_list[$v['goods_commonid']]['brand_id'];
  1157. $v['brand_name'] = $goods_common_list[$v['goods_commonid']]['brand_name'];
  1158. $goods_list[$v['goods_id']] = $v;
  1159. }
  1160. unset($goods_list_tmp);
  1161. //查询订单缓存是否存在,存在则删除
  1162. Db::name('statordergoods')->where('order_id', 'in', $orderid_arr)->delete();
  1163. //查询订单缓存是否存在,存在则删除
  1164. Db::name('statorder')->where('order_id', 'in', $orderid_arr)->delete();
  1165. //整理新增数据
  1166. $ordergoods_insert_arr = array();
  1167. foreach ((array) $ordergoods_list as $k => $v) {
  1168. $tmp = array();
  1169. $tmp['rec_id'] = $v['rec_id'];
  1170. $tmp['stat_updatetime'] = $search_etime;
  1171. $tmp['order_id'] = $v['order_id'];
  1172. $tmp['order_sn'] = $order_list[$v['order_id']]['order_sn'];
  1173. $tmp['order_add_time'] = $order_list[$v['order_id']]['add_time'];
  1174. $tmp['payment_code'] = $order_list[$v['order_id']]['payment_code'];
  1175. $tmp['order_amount'] = $order_list[$v['order_id']]['order_amount'];
  1176. $tmp['shipping_fee'] = $order_list[$v['order_id']]['shipping_fee'];
  1177. $tmp['evaluation_state'] = (string) $order_list[$v['order_id']]['evaluation_state'];
  1178. $tmp['order_state'] = (string) $order_list[$v['order_id']]['order_state'];
  1179. $tmp['refund_state'] = $order_list[$v['order_id']]['refund_state'];
  1180. $tmp['refund_amount'] = $order_list[$v['order_id']]['refund_amount'];
  1181. $tmp['order_from'] = $order_list[$v['order_id']]['order_from'];
  1182. $tmp['order_isvalid'] = $order_list[$v['order_id']]['order_isvalid'];
  1183. $tmp['reciver_province_id'] = $order_common_list[$v['order_id']]['reciver_province_id'];
  1184. $tmp['store_id'] = $v['store_id'];
  1185. $tmp['store_name'] = $store_list[$v['store_id']]['store_name'];
  1186. $tmp['grade_id'] = $store_list[$v['store_id']]['grade_id'];
  1187. $tmp['storeclass_id'] = $store_list[$v['store_id']]['storeclass_id'];
  1188. $tmp['buyer_id'] = $order_list[$v['order_id']]['buyer_id'];
  1189. $tmp['buyer_name'] = $order_list[$v['order_id']]['buyer_name'];
  1190. $tmp['goods_id'] = $v['goods_id'];
  1191. $tmp['goods_name'] = $v['goods_name'];
  1192. $tmp['goods_commonid'] = intval($goods_list[$v['goods_id']]['goods_commonid']);
  1193. $tmp['goods_commonname'] = ($t = $goods_list[$v['goods_id']]['goods_commonname']) ? $t : '';
  1194. $tmp['gc_id'] = intval($goods_list[$v['goods_id']]['gc_id']);
  1195. $tmp['gc_parentid_1'] = intval($goods_list[$v['goods_id']]['gc_id_1']);
  1196. $tmp['gc_parentid_2'] = intval($goods_list[$v['goods_id']]['gc_id_2']);
  1197. $tmp['gc_parentid_3'] = intval($goods_list[$v['goods_id']]['gc_id_3']);
  1198. $tmp['brand_id'] = intval($goods_list[$v['goods_id']]['brand_id']);
  1199. $tmp['brand_name'] = ($t = $goods_list[$v['goods_id']]['brand_name']) ? $t : '';
  1200. $tmp['goods_serial'] = ($t = $goods_list[$v['goods_id']]['goods_serial']) ? $t : '';
  1201. $tmp['goods_price'] = $v['goods_price'];
  1202. $tmp['goods_num'] = $v['goods_num'];
  1203. $tmp['goods_image'] = $goods_list[$v['goods_id']]['goods_image'];
  1204. $tmp['goods_pay_price'] = $v['goods_pay_price'];
  1205. $tmp['goods_type'] = $v['goods_type'];
  1206. $tmp['promotions_id'] = $v['promotions_id'];
  1207. $tmp['commis_rate'] = $v['commis_rate'];
  1208. $ordergoods_insert_arr[] = $tmp;
  1209. }
  1210. Db::name('statordergoods')->insertAll($ordergoods_insert_arr);
  1211. $order_insert_arr = array();
  1212. foreach ((array) $order_list as $k => $v) {
  1213. $tmp = array();
  1214. $tmp['order_id'] = $v['order_id'];
  1215. $tmp['order_sn'] = $v['order_sn'];
  1216. $tmp['order_add_time'] = $v['add_time'];
  1217. $tmp['payment_code'] = $v['payment_code'];
  1218. $tmp['order_amount'] = $v['order_amount'];
  1219. $tmp['shipping_fee'] = $v['shipping_fee'];
  1220. $tmp['evaluation_state'] = (string) $v['evaluation_state'];
  1221. $tmp['order_state'] = (string) $v['order_state'];
  1222. $tmp['refund_state'] = $v['refund_state'];
  1223. $tmp['refund_amount'] = $v['refund_amount'];
  1224. $tmp['order_from'] = $v['order_from'];
  1225. $tmp['order_isvalid'] = $v['order_isvalid'];
  1226. $tmp['reciver_province_id'] = $order_common_list[$v['order_id']]['reciver_province_id'];
  1227. $tmp['store_id'] = $v['store_id'];
  1228. $tmp['store_name'] = $store_list[$v['store_id']]['store_name'];
  1229. $tmp['grade_id'] = $store_list[$v['store_id']]['grade_id'];
  1230. $tmp['storeclass_id'] = $store_list[$v['store_id']]['storeclass_id'];
  1231. $tmp['buyer_id'] = $v['buyer_id'];
  1232. $tmp['buyer_name'] = $v['buyer_name'];
  1233. $order_insert_arr[] = $tmp;
  1234. }
  1235. Db::name('statorder')->insertAll($order_insert_arr);
  1236. }
  1237. }
  1238. }
  1239. }
  1240. /**
  1241. * 会员相关数据统计
  1242. */
  1243. private function _member_stat()
  1244. {
  1245. $stat_model = model('stat');
  1246. //查询最后统计的记录
  1247. $latest_record = $stat_model->getOneStatmember(array(), '', 'statm_id desc');
  1248. $stime = 0;
  1249. if ($latest_record) {
  1250. $start_time = strtotime(date('Y-m-d', $latest_record['statm_updatetime']));
  1251. } else {
  1252. $start_time = strtotime(date('Y-m-d', strtotime(config('ds_config.setup_date')))); //从系统的安装时间开始统计
  1253. }
  1254. $j = 1;
  1255. for ($stime = $start_time; $stime < TIMESTAMP; $stime = $stime + 86400) {
  1256. //数据库更新数据数组
  1257. $insert_arr = array();
  1258. $update_arr = array();
  1259. $etime = $stime + 86400 - 1;
  1260. //避免重复统计,开始时间必须大于最后一条记录的记录时间
  1261. $search_stime = $latest_record['statm_updatetime'] > $stime ? $latest_record['statm_updatetime'] : $stime;
  1262. //统计一天的数据,如果结束时间大于当前时间,则结束时间为当前时间,避免因为查询时间的延迟造成数据遗落
  1263. $search_etime = ($t = ($stime + 86400 - 1)) > TIMESTAMP ? TIMESTAMP : ($stime + 86400 - 1);
  1264. //统计订单下单量和下单金额
  1265. $field = ' order.order_id,add_time,buyer_id,buyer_name,order_amount';
  1266. $where = array();
  1267. $where[] = array('order.order_state', '<>', ORDER_STATE_NEW); //去除未支付订单
  1268. $where[] = array('order.refund_state', '<>', "0"); //没有参与退款的取消订单,不记录到统计中
  1269. $where[] = array('orderlog.log_time', 'between', array($search_stime, $search_etime)); //按照订单付款的操作时间统计
  1270. //货到付款当交易成功进入统计,非货到付款当付款后进入统计
  1271. $where = "(order.payment_code='offline' and orderlog.log_orderstate = '" . ORDER_STATE_SUCCESS . "') or (order.payment_code<>'offline' and orderlog.log_orderstate = '" . ORDER_STATE_PAY . "' )";
  1272. $orderlist_tmp = $stat_model->statByOrderLog($where, $field, 0, 0, 'order_id'); //此处由于底层的限制,仅能查询1000条,如果日下单量大于1000,则需要limit的支持
  1273. $order_list = array();
  1274. $orderid_list = array();
  1275. foreach ((array) $orderlist_tmp as $k => $v) {
  1276. $addtime = strtotime(date('Y-m-d', $v['add_time']));
  1277. if ($addtime != $stime) { //订单如果隔天支付的话,需要进行统计数据更新
  1278. $update_arr[$addtime][$v['buyer_id']]['statm_membername'] = $v['buyer_name'];
  1279. $update_arr[$addtime][$v['buyer_id']]['statm_ordernum'] = intval($update_arr[$addtime][$v['buyer_id']]['statm_ordernum']) + 1;
  1280. $update_arr[$addtime][$v['buyer_id']]['statm_orderamount'] = floatval($update_arr[$addtime][$v['buyer_id']]['statm_orderamount']) + (($t = floatval($v['order_amount'])) > 0 ? $t : 0);
  1281. } else {
  1282. $order_list[$v['buyer_id']]['buyer_name'] = $v['buyer_name'];
  1283. $order_list[$v['buyer_id']]['ordernum'] = intval($order_list[$v['buyer_id']]['ordernum']) + 1;
  1284. $order_list[$v['buyer_id']]['orderamount'] = floatval($order_list[$v['buyer_id']]['orderamount']) + (($t = floatval($v['order_amount'])) > 0 ? $t : 0);
  1285. }
  1286. //记录订单ID数组
  1287. $orderid_list[] = $v['order_id'];
  1288. }
  1289. //统计下单商品件数
  1290. if ($orderid_list) {
  1291. $field = ' add_time,order.buyer_id,order.buyer_name,goods_num ';
  1292. $where = array();
  1293. $where[] = array('order.order_id', 'in', $orderid_list);
  1294. $ordergoods_tmp = $stat_model->statByOrderGoods($where, $field, 0, 0, 'order.order_id');
  1295. $ordergoods_list = array();
  1296. foreach ((array) $ordergoods_tmp as $k => $v) {
  1297. $addtime = strtotime(date('Y-m-d', $v['add_time']));
  1298. if ($addtime != $stime) { //订单如果隔天支付的话,需要进行统计数据更新
  1299. $update_arr[$addtime][$v['buyer_id']]['statm_goodsnum'] = intval($update_arr[$addtime][$v['buyer_id']]['statm_goodsnum']) + (($t = floatval($v['goods_num'])) > 0 ? $t : 0);
  1300. } else {
  1301. $ordergoods_list[$v['buyer_id']]['goodsnum'] = $ordergoods_list[$v['buyer_id']]['goodsnum'] + (($t = floatval($v['goods_num'])) > 0 ? $t : 0);
  1302. }
  1303. }
  1304. }
  1305. //统计的预存款记录
  1306. $field = ' lg_member_id,lg_member_name,lg_av_amount as predincrease, lg_av_amount as predreduce ';
  1307. $where = array();
  1308. $where[] = array('lg_addtime', 'between', array($stime, $etime));
  1309. $predeposit_tmp = $stat_model->getPredepositInfo($where, $field, 0, 'lg_member_id', 0, 'lg_member_id');
  1310. $predeposit_list = array();
  1311. foreach ((array) $predeposit_tmp as $k => $v) {
  1312. $predeposit_list[$v['lg_member_id']] = $v;
  1313. }
  1314. //统计的积分记录
  1315. $field = ' pl_memberid,pl_membername,pl_points as pointsincrease, pl_points as pointsreduce ';
  1316. $where = array();
  1317. $where[] = array('pl_addtime', 'between', array($stime, $etime));
  1318. $points_tmp = $stat_model->statByPointslog($where, $field, 0, 0, '', 'pl_memberid');
  1319. $points_list = array();
  1320. foreach ((array) $points_tmp as $k => $v) {
  1321. $points_list[$v['pl_memberid']] = $v;
  1322. }
  1323. //处理需要更新的数据
  1324. foreach ((array) $update_arr as $k => $v) {
  1325. foreach ($v as $m_k => $m_v) {
  1326. //查询记录是否存在
  1327. $statmember_info = $stat_model->getOneStatmember(array('statm_time' => $k, 'statm_memberid' => $m_k));
  1328. if ($statmember_info) {
  1329. $m_v['statm_ordernum'] = intval($statmember_info['statm_ordernum']) + $m_v['statm_ordernum'];
  1330. $m_v['statm_orderamount'] = floatval($statmember_info['statm_ordernum']) + $m_v['statm_orderamount'];
  1331. $m_v['statm_updatetime'] = $search_etime;
  1332. $stat_model->editStatmember(array('statm_time' => $k, 'statm_memberid' => $m_k), $m_v);
  1333. } else {
  1334. $tmp = array();
  1335. $tmp['statm_memberid'] = $m_k;
  1336. $tmp['statm_membername'] = $m_v['statm_membername'];
  1337. $tmp['statm_time'] = $k;
  1338. $tmp['statm_updatetime'] = $search_etime;
  1339. $tmp['statm_ordernum'] = ($t = intval($m_v['statm_ordernum'])) > 0 ? $t : 0;
  1340. $tmp['statm_orderamount'] = ($t = floatval($m_v['statm_orderamount'])) > 0 ? $t : 0;
  1341. $tmp['statm_goodsnum'] = ($t = intval($m_v['statm_goodsnum'])) ? $t : 0;
  1342. $tmp['statm_predincrease'] = 0;
  1343. $tmp['statm_predreduce'] = 0;
  1344. $tmp['statm_pointsincrease'] = 0;
  1345. $tmp['statm_pointsreduce'] = 0;
  1346. $insert_arr[] = $tmp;
  1347. }
  1348. unset($statmember_info);
  1349. }
  1350. }
  1351. //处理获得所有会员ID数组
  1352. $memberidarr_order = isset($order_list) ? array_keys($order_list) : array();
  1353. $memberidarr_ordergoods = isset($ordergoods_list) ? array_keys($ordergoods_list) : array();
  1354. $memberidarr_predeposit = isset($predeposit_list) ? array_keys($predeposit_list) : array();
  1355. $memberidarr_points = isset($points_list) ? array_keys($points_list) : array();
  1356. $memberid_arr = array_merge($memberidarr_order, $memberidarr_ordergoods, $memberidarr_predeposit, $memberidarr_points);
  1357. //查询会员信息
  1358. $memberid_list = model('member')->getMemberList(array(array('member_id', 'in', $memberid_arr)), '', 0);
  1359. //查询记录是否存在
  1360. $statmemberlist_tmp = $stat_model->statByStatmember(array('statm_time' => $stime));
  1361. $statmemberlist = array();
  1362. foreach ((array) $statmemberlist_tmp as $k => $v) {
  1363. $statmemberlist[$v['statm_memberid']] = $v;
  1364. }
  1365. foreach ((array) $memberid_list as $k => $v) {
  1366. $tmp = array();
  1367. $tmp['statm_memberid'] = $v['member_id'];
  1368. $tmp['statm_membername'] = $v['member_name'];
  1369. $tmp['statm_time'] = $stime;
  1370. $tmp['statm_updatetime'] = $search_etime;
  1371. //因为记录可能已经存在,所以加上之前的统计记录
  1372. $statmemberlist[$tmp['statm_memberid']] = isset($statmemberlist[$tmp['statm_memberid']]) ? $statmemberlist[$tmp['statm_memberid']] : 0;
  1373. $order_list[$tmp['statm_memberid']] = isset($order_list[$tmp['statm_memberid']]) ? $order_list[$tmp['statm_memberid']] : 0;
  1374. $ordergoods_list[$tmp['statm_memberid']] = isset($ordergoods_list[$tmp['statm_memberid']]) ? $ordergoods_list[$tmp['statm_memberid']] : 0;
  1375. $predeposit_list[$tmp['statm_memberid']] = isset($predeposit_list[$tmp['statm_memberid']]) ? $predeposit_list[$tmp['statm_memberid']] : 0;
  1376. $tmp['statm_ordernum'] = intval($statmemberlist[$tmp['statm_memberid']]['statm_ordernum']) + (($t = intval($order_list[$tmp['statm_memberid']]['ordernum'])) > 0 ? $t : 0);
  1377. $tmp['statm_orderamount'] = floatval($statmemberlist[$tmp['statm_memberid']]['statm_orderamount']) + (($t = floatval($order_list[$tmp['statm_memberid']]['orderamount'])) > 0 ? $t : 0);
  1378. $tmp['statm_goodsnum'] = intval($statmemberlist[$tmp['statm_memberid']]['statm_goodsnum']) + (($t = intval($ordergoods_list[$tmp['statm_memberid']]['goodsnum'])) ? $t : 0);
  1379. $tmp['statm_predincrease'] = (($t = floatval($predeposit_list[$tmp['statm_memberid']]['predincrease'])) ? $t : 0);
  1380. $tmp['statm_predreduce'] = (($t = floatval($predeposit_list[$tmp['statm_memberid']]['predreduce'])) ? $t : 0);
  1381. $tmp['statm_pointsincrease'] = (($t = intval($points_list[$tmp['statm_memberid']]['pointsincrease'])) ? $t : 0);
  1382. $tmp['statm_pointsreduce'] = (($t = intval($points_list[$tmp['statm_memberid']]['pointsreduce'])) ? $t : 0);
  1383. $insert_arr[] = $tmp;
  1384. }
  1385. //删除旧的统计数据
  1386. $stat_model->delByStatmember(array('statm_time' => $stime));
  1387. Db::name('statmember')->insertAll($insert_arr);
  1388. }
  1389. }
  1390. }