Date.php 84 KB

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