StoreProduct.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\admin\model\store;
  12. use app\admin\model\system\RecommendRelation;
  13. use app\admin\model\wechat\WechatUser;
  14. use service\PHPExcelService;
  15. use think\Db;
  16. use traits\ModelTrait;
  17. use basic\ModelBasic;
  18. use app\admin\model\store\StoreCategory as CategoryModel;
  19. use app\admin\model\order\StoreOrder;
  20. use app\admin\model\system\SystemConfig;
  21. /**
  22. * 产品管理 model
  23. * Class StoreProduct
  24. * @package app\admin\model\store
  25. */
  26. class StoreProduct extends ModelBasic
  27. {
  28. use ModelTrait;
  29. /**
  30. * 获取连表查询条件
  31. * @param $type
  32. * @return array
  33. */
  34. public static function setData($type){
  35. $store_stock=SystemConfig::getValue('store_stock');
  36. switch ((int)$type){
  37. case 1:
  38. $data = ['p.is_show'=>1,'p.is_del'=>0];
  39. break;
  40. case 2:
  41. $data = ['p.is_show'=>0,'p.is_del'=>0];
  42. break;
  43. case 3:
  44. $data = ['p.is_del'=>0];
  45. break;
  46. case 4:
  47. $data = ['p.is_show'=>1,'p.is_del'=>0,'p.stock'=>0];
  48. break;
  49. case 5:
  50. $data = ['p.is_show'=>1,'p.is_del'=>0,'p.stock'=>['elt',$store_stock]];
  51. break;
  52. case 6:
  53. $data = ['p.is_del'=>1];
  54. break;
  55. };
  56. return isset($data) ? $data: [];
  57. }
  58. public static function PreWhere($alert = '')
  59. {
  60. $alert = $alert ? $alert . '.' : '';
  61. return self::where([$alert . 'is_show' => 1, $alert . 'is_del' => 0]);
  62. }
  63. /**
  64. * 获取连表MOdel
  65. * @param $model
  66. * @return object
  67. */
  68. public static function getModelObject($where=[]){
  69. $model=new self();
  70. $model=$model->alias('p');
  71. if(!empty($where)){
  72. $model=$model->group('p.id');
  73. if(isset($where['type']) && $where['type']!='' && ($data=self::setData($where['type']))){
  74. $model = $model->where($data);
  75. }
  76. if(isset($where['store_name']) && $where['store_name']!=''){
  77. $model = $model->where('p.store_name|p.keyword|p.id','LIKE',"%$where[store_name]%");
  78. }
  79. if(isset($where['cate_id']) && trim($where['cate_id'])!=0){
  80. $model = $model->where('p.cate_id',$where['cate_id']);
  81. }
  82. if(isset($where['order']) && $where['order']!=''){
  83. $model = $model->order(self::setOrder($where['order']));
  84. }else{
  85. $model = $model->order('p.sort DESC,p.add_time DESC');
  86. }
  87. }
  88. return $model;
  89. }
  90. /**
  91. * 获取商品
  92. */
  93. public static function storeProductList($where)
  94. {
  95. $where['store_name']=$where['title'];
  96. $model=self::getModelObject($where)->field(['p.*']);
  97. $model=$model->page((int)$where['page'],(int)$where['limit']);
  98. $data=($data=$model->select()) && count($data) ? $data->toArray():[];
  99. $count=self::getModelObject($where)->count();
  100. return compact('count','data');
  101. }
  102. /*
  103. * 获取产品列表
  104. * @param $where array
  105. * @return array
  106. *
  107. */
  108. public static function ProductList($where){
  109. $model=self::getModelObject($where)->field(['p.*']);
  110. if($where['excel']==0) $model=$model->page((int)$where['page'],(int)$where['limit']);
  111. $data=($data=$model->select()) && count($data) ? $data->toArray():[];
  112. foreach ($data as &$item){
  113. $item['recommend'] = RecommendRelation::where('a.link_id', $item['id'])->where('a.type', 4)->alias('a')
  114. ->join('__RECOMMEND__ r', 'a.recommend_id=r.id')->column('a.id,r.title');
  115. $cateName = CategoryModel::where('id',$item['cate_id'])->find();
  116. $item['cate_name'] = $cateName ? $cateName->cate_name : "";
  117. $item['stock'] = self::getStock($item['id'])>0?self::getStock($item['id']):$item['stock'];//库存
  118. $item['stock_attr'] = self::getStock($item['id'])>0 ? true : false;//库存
  119. $item['sales_attr'] = self::getSales($item['id']);//属性销量
  120. }
  121. if($where['excel']==1){
  122. $export = [];
  123. foreach ($data as $index=>$item){
  124. $export[] = [
  125. $item['store_name'],
  126. $item['store_info'],
  127. $item['cate_name'],
  128. '¥'.$item['price'],
  129. $item['stock'],
  130. $item['sales'],
  131. ];
  132. }
  133. PHPExcelService::setExcelHeader(['产品名称','产品简介','产品分类','价格','库存','销量'])
  134. ->setExcelTile('产品导出','产品信息'.time(),' 生成时间:'.date('Y-m-d H:i:s',time()))
  135. ->setExcelContent($export)
  136. ->ExcelSave();
  137. }
  138. $count=self::getModelObject($where)->count();
  139. return compact('count','data');
  140. }
  141. public static function getChatrdata($type,$data){
  142. $legdata=['销量','数量','点赞','收藏'];
  143. $model=self::setWhereType(self::order('id desc'),$type);
  144. $list=self::getModelTime(compact('data'),$model)
  145. ->field('FROM_UNIXTIME(add_time,"%Y-%c-%d") as un_time,count(id) as count,sum(sales) as sales')
  146. ->group('un_time')
  147. ->distinct(true)
  148. ->select()
  149. ->each(function($item) use($data){
  150. $item['collect']=self::getModelTime(compact('data'),new StoreProductRelation)->where(['type'=>'collect'])->count();
  151. $item['like']=self::getModelTime(compact('data'),new StoreProductRelation)->where(['type'=>'like'])->count();
  152. })->toArray();
  153. $chatrList=[];
  154. $datetime=[];
  155. $data_item=[];
  156. $itemList=[0=>[],1=>[],2=>[],3=>[]];
  157. foreach ($list as $item){
  158. $itemList[0][]=$item['sales'];
  159. $itemList[1][]=$item['count'];
  160. $itemList[2][]=$item['like'];
  161. $itemList[3][]=$item['collect'];
  162. array_push($datetime,$item['un_time']);
  163. }
  164. foreach ($legdata as $key=>$leg){
  165. $data_item['name']=$leg;
  166. $data_item['type']='line';
  167. $data_item['data']=$itemList[$key];
  168. $chatrList[]=$data_item;
  169. unset($data_item);
  170. }
  171. unset($leg);
  172. $badge=self::getbadge(compact('data'),$type);
  173. $count=self::setWhereType(self::getModelTime(compact('data'),new self()),$type)->count();
  174. return compact('datetime','chatrList','legdata','badge','count');
  175. }
  176. //获取 badge 内容
  177. public static function getbadge($where,$type){
  178. $StoreOrderModel=new StoreOrder;
  179. $replenishment_num = SystemConfig::getValue('replenishment_num');
  180. $replenishment_num = $replenishment_num > 0 ? $replenishment_num : 20;
  181. $stock1=self::getModelTime($where,new self())->where('stock','<',$replenishment_num)->column('stock');
  182. $sum_stock=self::where('stock','<',$replenishment_num)->column('stock');
  183. $stk=[];
  184. foreach ($stock1 as $item){
  185. $stk[]=$replenishment_num-$item;
  186. }
  187. $lack=array_sum($stk);
  188. $sum=[];
  189. foreach ($sum_stock as $val){
  190. $sum[]=$replenishment_num-$val;
  191. }
  192. return [
  193. [
  194. 'name'=>'商品数量',
  195. 'field'=>'件',
  196. 'count'=>self::setWhereType(new self(),$type)->where('add_time','<',mktime(0,0,0,date('m'),date('d'),date('Y')))->sum('stock'),
  197. 'content'=>'商品数量总数',
  198. 'background_color'=>'layui-bg-blue',
  199. 'sum'=>self::sum('stock'),
  200. 'class'=>'fa fa fa-ioxhost',
  201. ],
  202. [
  203. 'name'=>'新增商品',
  204. 'field'=>'件',
  205. 'count'=>self::setWhereType(self::getModelTime($where,new self),$type)->where('is_new',1)->sum('stock'),
  206. 'content'=>'新增商品总数',
  207. 'background_color'=>'layui-bg-cyan',
  208. 'sum'=>self::where('is_new',1)->sum('stock'),
  209. 'class'=>'fa fa-line-chart',
  210. ],
  211. [
  212. 'name'=>'活动商品',
  213. 'field'=>'件',
  214. 'count'=>self::getModelTime($where,$StoreOrderModel)->sum('total_num'),
  215. 'content'=>'活动商品总数',
  216. 'background_color'=>'layui-bg-green',
  217. 'sum'=>$StoreOrderModel->sum('total_num'),
  218. 'class'=>'fa fa-bar-chart',
  219. ],
  220. [
  221. 'name'=>'缺货商品',
  222. 'field'=>'件',
  223. 'count'=>$lack,
  224. 'content'=>'总商品数量',
  225. 'background_color'=>'layui-bg-orange',
  226. 'sum'=>array_sum($sum),
  227. 'class'=>'fa fa-cube',
  228. ],
  229. ];
  230. }
  231. public static function setWhereType($model,$type){
  232. switch ($type){
  233. case 1:
  234. $data = ['is_show'=>1,'is_del'=>0];
  235. break;
  236. case 2:
  237. $data = ['is_show'=>0,'is_del'=>0];
  238. break;
  239. case 3:
  240. $data = ['is_del'=>0];
  241. break;
  242. case 4:
  243. $data = ['is_show'=>1,'is_del'=>0,'stock'=>0];
  244. break;
  245. case 5:
  246. $data = ['is_show'=>1,'is_del'=>0,'stock'=>['elt',1]];
  247. break;
  248. case 6:
  249. $data = ['is_del'=>1];
  250. break;
  251. }
  252. if(isset($data)) $model = $model->where($data);
  253. return $model;
  254. }
  255. /*
  256. * layui-bg-red 红 layui-bg-orange 黄 layui-bg-green 绿 layui-bg-blue 蓝 layui-bg-cyan 黑
  257. * 销量排行 top 10
  258. */
  259. public static function getMaxList($where){
  260. $classs=['layui-bg-red','layui-bg-orange','layui-bg-green','layui-bg-blue','layui-bg-cyan'];
  261. $model=StoreOrder::alias('a')->join('StoreOrderCartInfo c','a.id=c.oid')->join('store_product b','b.id=c.product_id');
  262. $list=self::getModelTime($where,$model,'a.add_time')->group('c.product_id')->order('p_count desc')->limit(10)
  263. ->field(['count(c.product_id) as p_count','b.store_name','sum(b.price) as sum_price'])->select();
  264. if(count($list)) $list=$list->toArray();
  265. $maxList=[];
  266. $sum_count=0;
  267. $sum_price=0;
  268. foreach ($list as $item){
  269. $sum_count+=$item['p_count'];
  270. $sum_price=bcadd($sum_price,$item['sum_price'],2);
  271. }
  272. unset($item);
  273. foreach ($list as $key=>&$item){
  274. $item['w']=bcdiv($item['p_count'],$sum_count,2)*100;
  275. $item['class']=isset($classs[$key]) ?$classs[$key]:( isset($classs[$key-count($classs)]) ? $classs[$key-count($classs)]:'');
  276. $item['store_name']=self::getSubstrUTf8($item['store_name']);
  277. }
  278. $maxList['sum_count']=$sum_count;
  279. $maxList['sum_price']=$sum_price;
  280. $maxList['list']=$list;
  281. return $maxList;
  282. }
  283. //获取利润
  284. public static function ProfityTop10($where){
  285. $classs=['layui-bg-red','layui-bg-orange','layui-bg-green','layui-bg-blue','layui-bg-cyan'];
  286. $model=StoreOrder::alias('a')->join('StoreOrderCartInfo c','a.id=c.oid')->join('store_product b','b.id=c.product_id');
  287. $list=self::getModelTime($where,$model,'a.add_time')->group('c.product_id')->order('profity desc')->limit(10)
  288. ->field(['count(c.product_id) as p_count','b.store_name','sum(b.price) as sum_price','(b.price-b.cost) as profity'])
  289. ->select();
  290. if(count($list)) $list=$list->toArray();
  291. $maxList=[];
  292. $sum_count=0;
  293. $sum_price=0;
  294. foreach ($list as $item){
  295. $sum_count+=$item['p_count'];
  296. $sum_price=bcadd($sum_price,$item['sum_price'],2);
  297. }
  298. foreach ($list as $key=>&$item){
  299. $item['w']=bcdiv($item['sum_price'],$sum_price,2)*100;
  300. $item['class']=isset($classs[$key]) ?$classs[$key]:( isset($classs[$key-count($classs)]) ? $classs[$key-count($classs)]:'');
  301. $item['store_name']=self::getSubstrUTf8($item['store_name'],30);
  302. }
  303. $maxList['sum_count']=$sum_count;
  304. $maxList['sum_price']=$sum_price;
  305. $maxList['list']=$list;
  306. return $maxList;
  307. }
  308. //获取缺货
  309. public static function getLackList($where){
  310. $replenishment_num = SystemConfig::getValue('replenishment_num');
  311. $replenishment_num = $replenishment_num > 0 ? $replenishment_num : 20;
  312. $list=self::where('stock','<',$replenishment_num)->field(['id','store_name','stock','price'])->page((int)$where['page'],(int)$where['limit'])->order('stock asc')->select();
  313. if(count($list)) $list=$list->toArray();
  314. $count=self::where('stock','<',$replenishment_num)->count();
  315. return ['count'=>$count,'data'=>$list];
  316. }
  317. //获取差评
  318. public static function getnegativelist($where){
  319. $list=self::alias('s')->join('StoreProductReply r','s.id=r.product_id')
  320. ->field('s.id,s.store_name,s.price,count(r.product_id) as count')
  321. ->page((int)$where['page'],(int)$where['limit'])
  322. ->where('r.product_score',1)
  323. ->order('count desc')
  324. ->group('r.product_id')
  325. ->select();
  326. if(count($list)) $list=$list->toArray();
  327. $count=self::alias('s')->join('StoreProductReply r','s.id=r.product_id')->group('r.product_id')->where('r.product_score',1)->count();
  328. return ['count'=>$count,'data'=>$list];
  329. }
  330. public static function TuiProductList(){
  331. $perd=StoreOrder::alias('s')->join('StoreOrderCartInfo c','s.id=c.oid')
  332. ->field('count(c.product_id) as count,c.product_id as id')
  333. ->group('c.product_id')
  334. ->where('s.status',-1)
  335. ->order('count desc')
  336. ->limit(10)
  337. ->select();
  338. if(count($perd)) $perd=$perd->toArray();
  339. foreach ($perd as &$item){
  340. $item['store_name']=self::where(['id'=>$item['id']])->value('store_name');
  341. $item['price']=self::where(['id'=>$item['id']])->value('price');
  342. }
  343. return $perd;
  344. }
  345. //编辑库存
  346. public static function changeStock($stock,$productId)
  347. {
  348. return self::edit(compact('stock'),$productId);
  349. }
  350. //获取库存数量
  351. public static function getStock($productId)
  352. {
  353. return StoreProductAttrValue::where(['product_id'=>$productId])->sum('stock');
  354. }
  355. //获取总销量
  356. public static function getSales($productId)
  357. {
  358. return StoreProductAttrValue::where(['product_id'=>$productId])->sum('sales');
  359. }
  360. public static function getTierList($model = null)
  361. {
  362. if($model === null) $model = new self();
  363. return $model->field('id,store_name')->where('is_del',0)->select()->toArray();
  364. }
  365. /**
  366. * 设置查询条件
  367. * @param array $where
  368. * @return array
  369. */
  370. public static function setWhere($where){
  371. $time['data']='';
  372. if(isset($where['start_time']) && $where['start_time']!='' && isset($where['end_time']) && $where['end_time']!=''){
  373. $time['data']=$where['start_time'].' - '.$where['end_time'];
  374. }else{
  375. $time['data']=isset($where['data'])? $where['data']:'';
  376. }
  377. $model=self::getModelTime($time,db('store_cart')->alias('a')->join('store_product b','a.product_id=b.id'),'a.add_time');
  378. if(isset($where['title']) && $where['title']!=''){
  379. $model=$model->where('b.store_name|b.id','like',"%$where[title]%");
  380. }
  381. return $model;
  382. }
  383. /**
  384. * 获取真实销量排行
  385. * @param array $where
  386. * @return array
  387. */
  388. public static function getSaleslists($where){
  389. $data=self::setWhere($where)->where('a.is_pay',1)
  390. ->group('a.product_id')
  391. ->field(['sum(a.cart_num) as num_product','b.store_name','b.image','b.price','b.id'])
  392. ->order('num_product desc')
  393. ->page((int)$where['page'],(int)$where['limit'])
  394. ->select();
  395. $count=self::setWhere($where)->where('a.is_pay',1)->group('a.product_id')->count();
  396. foreach ($data as &$item){
  397. $item['sum_price']=bcdiv($item['num_product'],$item['price'],2);
  398. }
  399. return compact('data','count');
  400. }
  401. public static function SaveProductExport($where){
  402. $list=self::setWhere($where)
  403. ->where('a.is_pay',1)
  404. ->field(['sum(a.cart_num) as num_product','b.store_name','b.image','b.price','b.id'])
  405. ->order('num_product desc')
  406. ->group('a.product_id')
  407. ->select();
  408. $export=[];
  409. foreach ($list as $item){
  410. $export[]=[
  411. $item['id'],
  412. $item['store_name'],
  413. $item['price'],
  414. bcmul($item['num_product'],$item['price'],2),
  415. $item['num_product'],
  416. ];
  417. }
  418. PHPExcelService::setExcelHeader(['商品编号','商品名称','商品售价','销售额','销量'])
  419. ->setExcelTile('产品销量排行','产品销量排行',' 生成时间:'.date('Y-m-d H:i:s',time()))
  420. ->setExcelContent($export)
  421. ->ExcelSave();
  422. }
  423. /*
  424. * 单个商品详情的头部查询
  425. * $id 商品id
  426. * $where 条件
  427. */
  428. public static function getProductBadgeList($id,$where){
  429. $data['data']=$where;
  430. $list=self::setWhere($data)
  431. ->field(['sum(a.cart_num) as num_product','b.id','b.price'])
  432. ->where('a.is_pay',1)
  433. ->group('a.product_id')
  434. ->order('num_product desc')
  435. ->select();
  436. //排名
  437. $ranking=0;
  438. //销量
  439. $xiaoliang=0;
  440. //销售额 数组
  441. $list_price=[];
  442. foreach ($list as $key=>$item){
  443. if($item['id']==$id){
  444. $ranking=$key+1;
  445. $xiaoliang=$item['num_product'];
  446. }
  447. $value['sum_price']=$item['price']*$item['num_product'];
  448. $value['id']=$item['id'];
  449. $list_price[]=$value;
  450. }
  451. //排序
  452. $list_price=self::my_sort($list_price,'sum_price',SORT_DESC);
  453. //销售额排名
  454. $rank_price=0;
  455. //当前销售额
  456. $num_price=0;
  457. if($list_price!==false && is_array($list_price)){
  458. foreach ($list_price as $key=>$item){
  459. if($item['id']==$id){
  460. $num_price=$item['sum_price'];
  461. $rank_price=$key+1;
  462. continue;
  463. }
  464. }
  465. }
  466. return [
  467. [
  468. 'name'=>'销售额排名',
  469. 'field'=>'名',
  470. 'count'=>$rank_price,
  471. 'background_color'=>'layui-bg-blue',
  472. ],
  473. [
  474. 'name'=>'销量排名',
  475. 'field'=>'名',
  476. 'count'=>$ranking,
  477. 'background_color'=>'layui-bg-blue',
  478. ],
  479. [
  480. 'name'=>'商品销量',
  481. 'field'=>'名',
  482. 'count'=>$xiaoliang,
  483. 'background_color'=>'layui-bg-blue',
  484. ],
  485. [
  486. 'name'=>'点赞次数',
  487. 'field'=>'个',
  488. 'count'=>db('store_product_relation')->where('product_id',$id)->where('type','like')->count(),
  489. 'background_color'=>'layui-bg-blue',
  490. ],
  491. [
  492. 'name'=>'销售总额',
  493. 'field'=>'元',
  494. 'count'=>$num_price,
  495. 'background_color'=>'layui-bg-blue',
  496. 'col'=>12,
  497. ],
  498. ];
  499. }
  500. /*
  501. * 处理二维数组排序
  502. * $arrays 需要处理的数组
  503. * $sort_key 需要处理的key名
  504. * $sort_order 排序方式
  505. * $sort_type 类型 可不填写
  506. */
  507. public static function my_sort($arrays,$sort_key,$sort_order=SORT_ASC,$sort_type=SORT_NUMERIC ){
  508. if(is_array($arrays)){
  509. foreach ($arrays as $array){
  510. if(is_array($array)){
  511. $key_arrays[] = $array[$sort_key];
  512. }else{
  513. return false;
  514. }
  515. }
  516. }
  517. if(isset($key_arrays)){
  518. array_multisort($key_arrays,$sort_order,$sort_type,$arrays);
  519. return $arrays;
  520. }
  521. return false;
  522. }
  523. /*
  524. * 查询单个商品的销量曲线图
  525. *
  526. */
  527. public static function getProductCurve($where){
  528. $list=self::setWhere($where)
  529. ->where('a.product_id',$where['id'])
  530. ->where('a.is_pay',1)
  531. ->field(['FROM_UNIXTIME(a.add_time,"%Y-%m-%d") as _add_time','sum(a.cart_num) as num'])
  532. ->group('_add_time')
  533. ->order('_add_time asc')
  534. ->select();
  535. $seriesdata=[];
  536. $date=[];
  537. $zoom='';
  538. foreach ($list as $item){
  539. $date[]=$item['_add_time'];
  540. $seriesdata[]=$item['num'];
  541. }
  542. if(count($date)>$where['limit']) $zoom=$date[$where['limit']-5];
  543. return compact('seriesdata','date','zoom');
  544. }
  545. /*
  546. * 查询单个商品的销售列表
  547. *
  548. */
  549. public static function getSalelList($where){
  550. return self::setWhere($where)
  551. ->where(['a.product_id'=>$where['id'],'a.is_pay'=>1])
  552. ->join('user c','c.uid=a.uid')
  553. ->field(['FROM_UNIXTIME(a.add_time,"%Y-%m-%d") as _add_time','c.nickname','b.price','a.id','a.cart_num as num'])
  554. ->page((int)$where['page'],(int)$where['limit'])
  555. ->select();
  556. }
  557. }