Goods.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\common\model;
  13. use app\common\enum\goods\GoodsType;
  14. use think\model\relation\BelongsTo;
  15. use think\Paginator;
  16. use think\model\Collection;
  17. use app\common\library\helper;
  18. use app\store\model\GoodsCategoryRel as GoodsCategoryRelModel;
  19. use app\common\enum\goods\Status as GoodsStatusEnum;
  20. use app\common\model\chef\ChefAreas as RegionModel;
  21. use think\facade\Db;
  22. /**
  23. * 商品模型
  24. * Class Goods
  25. * @package app\common\model
  26. */
  27. class Goods extends BaseModel
  28. {
  29. // 定义表名
  30. protected $name = 'goods';
  31. // 定义主键
  32. protected $pk = 'goods_id';
  33. // 追加字段
  34. protected $append = ['goods_sales','province_text','city_text','region_text', 'category_name','cascader'];
  35. const PACKAGETYPE = 30;
  36. // const UNIT = [
  37. // 1 => '件',
  38. // 2 => '盒',
  39. // 3 => '包',
  40. // 4 => '份',
  41. // 5 => '箱',
  42. // 6 => '袋',
  43. // 7 => '斤',
  44. // 8 => '桶',
  45. // 9 => '瓶',
  46. // 10 => '罐',
  47. // 11 => '个',
  48. // ];
  49. /**
  50. * 省市区id集
  51. * @param $value
  52. * @param $data
  53. * @return array
  54. */
  55. public function getCascaderAttr($value, $data)
  56. {
  57. return [$data['province_id']??0, $data['city_id']??0, $data['region_id']??0];
  58. }
  59. /**
  60. * 计算显示销量 (初始销量 + 实际销量 + 门店销量)
  61. * @param $value
  62. * @param $data
  63. * @return mixed
  64. */
  65. public function getGoodsSalesAttr($value, $data)
  66. {
  67. return ($data['sales_initial']??0) + ($data['sales_actual']??0) + ($data['sales_shops']??0);
  68. }
  69. /**
  70. * Notes:产地:省份
  71. * Author: zhangs
  72. * DateTime: 2021/9/24 14:20
  73. * @param $value
  74. * @param $data
  75. * @return mixed
  76. */
  77. public function getProvinceTextAttr($value, $data)
  78. {
  79. if (empty($data['province_id'])) return '';
  80. return RegionModel::getNameById($data['province_id'] ?? 0);
  81. }
  82. /**
  83. * Notes:产地:城市
  84. * Author: zhangs
  85. * DateTime: 2021/9/24 14:21
  86. * @param $value
  87. * @param $data
  88. * @return mixed
  89. */
  90. public function getCityTextAttr($value, $data)
  91. {
  92. if (empty($data['city_id'])) return '';
  93. return RegionModel::getNameById($data['city_id'] ?? 0);
  94. }
  95. /**
  96. * Notes:产地:地区
  97. * Author: zhangs
  98. * DateTime: 2021/9/24 14:21
  99. * @param $value
  100. * @param $data
  101. * @return mixed
  102. */
  103. public function getRegionTextAttr($value, $data)
  104. {
  105. if (empty($data['region_id'])) return '';
  106. return RegionModel::getNameById($data['region_id'] ?? 0);
  107. }
  108. /**
  109. * Notes:商品分类名称
  110. * Author: zhangs
  111. * DateTime: 2021/9/24 16:41
  112. * @param $value
  113. * @param $data
  114. * @return string
  115. */
  116. public function getCategoryNameAttr($value, $data)
  117. {
  118. if(isset($data['goods_id'])){
  119. $category_ids = GoodsCategoryRel::where('goods_id', '=', $data['goods_id'])->column('category_id');
  120. if (empty($category_ids)) {
  121. return '';
  122. }
  123. $names = Category::whereIn('category_id', $category_ids)->column('name');
  124. return $names ? implode(',', $names) : '';
  125. }
  126. }
  127. /**
  128. * 商品详情:HTML实体转换回普通字符
  129. * @param $value
  130. * @return string
  131. */
  132. public function getContentAttr($value)
  133. {
  134. return htmlspecialchars_decode($value);
  135. }
  136. /**
  137. * 获取器:单独设置折扣的配置
  138. * @param $json
  139. * @return mixed
  140. */
  141. public function getAloneGradeEquityAttr($json)
  142. {
  143. return helper::jsonDecode($json);
  144. }
  145. /**
  146. * 修改器:单独设置折扣的配置
  147. * @param $data
  148. * @return mixed
  149. */
  150. public function setAloneGradeEquityAttr($data)
  151. {
  152. return helper::jsonEncode($data);
  153. }
  154. /**
  155. * 关联商品规格表
  156. * @return \think\model\relation\HasMany
  157. */
  158. public function skuList()
  159. {
  160. return $this->hasMany('GoodsSku')->order(['id' => 'asc']);
  161. }
  162. /**
  163. *
  164. * @return \think\model\relation\HasMany
  165. * @author: zjwhust
  166. * @Time: 2021/12/28 15:43
  167. */
  168. public function category()
  169. {
  170. return $this->hasOne('GoodsCategoryRel','goods_id','goods_id');
  171. }
  172. /**
  173. * 关联商品规格关系表
  174. * @return \think\model\relation\HasMany
  175. */
  176. public function specRel()
  177. {
  178. return $this->hasMany('GoodsSpecRel');
  179. }
  180. /**
  181. * 关联商品图片表
  182. * @return \think\model\relation\HasMany
  183. */
  184. public function images()
  185. {
  186. return $this->hasMany('GoodsImage')->order(['id']);
  187. }
  188. /**
  189. * 关联运费模板表
  190. * @return BelongsTo
  191. */
  192. public function delivery()
  193. {
  194. return $this->belongsTo('Delivery');
  195. }
  196. /**
  197. * 关联订单评价表
  198. * @return \think\model\relation\HasMany
  199. */
  200. public function commentData()
  201. {
  202. return $this->hasMany('Comment');
  203. }
  204. /**
  205. * 关联供应商表/商铺
  206. * @return BelongsTo
  207. */
  208. public function provider()
  209. {
  210. return $this->belongsTo(Provider::class, 'provider_id', 'provider_id');
  211. }
  212. /**
  213. * 获取商品列表
  214. * @param array $param 查询条件
  215. * @param int $listRows 分页数量
  216. * @param bool $showVip 会员商品列表
  217. * @return mixed
  218. * @throws \think\db\exception\DbException
  219. */
  220. public function getList(array $param = [], int $listRows = 15,bool $showVip = false)
  221. {
  222. // 筛选条件
  223. $query = $this->getQueryFilter($param);
  224. // 设置显示的销量 goods_sales
  225. // 购买数*1.5+加入购物车数+收藏数*0.8)之和排倒序
  226. $query->field(['(sales_initial + sales_actual) as online_sales','(sales_initial + sales_actual + sales_shops) as goods_sales','(shops_stock_total+stock_total) as goods_stocks','(collect_num*0.8+cart_num+(sales_initial+sales_actual)*1.5) as common_sort']);
  227. // 排序条件
  228. //$sort = $this->setQuerySort($param);
  229. $sort = $this->setQuerySortZq($param);
  230. //dd($sort);
  231. // 执行查询
  232. $list = $query->with(['images.file','provider'])
  233. ->alias($this->name);
  234. if ($showVip){
  235. $list = $list->whereExists('select id from yoshop_member_goods where goods_id=goods.goods_id and status=0');
  236. }
  237. $list = $list->field($this->getAliasFields($this->name, ['content']))
  238. ->where('is_delete', '=', 0)
  239. ->order($sort)
  240. ->paginate($listRows);
  241. // 整理列表数据并返回
  242. return $this->setGoodsListData($list);
  243. }
  244. /**
  245. * 获取商品列表
  246. * @param array $param 查询条件
  247. * @param int $listRows 分页数量
  248. * @param bool $showVip 会员商品列表
  249. * @return mixed
  250. * @throws \think\db\exception\DbException
  251. */
  252. public function getListFront(array $param = [], int $listRows = 15,bool $showVip = false)
  253. {
  254. // 筛选条件
  255. $query = $this->getQueryFilter($param);
  256. // 设置显示的销量 goods_sales
  257. // 购买数*1.5+加入购物车数+收藏数*0.8)之和排倒序
  258. $query->field(['(sales_initial + sales_actual) as online_sales','(sales_initial + sales_actual + sales_shops) as goods_sales','(shops_stock_total+stock_total) as goods_stocks','(collect_num*0.8+cart_num+(sales_initial+sales_actual)*1.5) as common_sort']);
  259. // 排序条件
  260. //$sort = $this->setQuerySort($param);
  261. $sort = $this->setQuerySortZq($param);
  262. //dd($sort);
  263. // 执行查询
  264. $list = $query->with(['images.file','provider'])
  265. ->alias($this->name);
  266. if ($showVip){
  267. $list = $list->whereExists('select id from yoshop_member_goods where goods_id=goods.goods_id and status=0');
  268. }
  269. $list = $list->field($this->getAliasFields($this->name, ['content']))
  270. ->where('is_delete', '=', 0)
  271. ->where('is_show', '=', 1)
  272. ->order($sort)
  273. ->paginate($listRows);
  274. // 整理列表数据并返回
  275. return $this->setGoodsListData($list);
  276. }
  277. /**
  278. * 检索排序条件
  279. * @param array $param
  280. * @return array|string[]
  281. */
  282. private function setQuerySort(array $param = [])
  283. {
  284. $params = $this->setQueryDefaultValue($param, [
  285. 'sortType' => 'all', // 排序类型
  286. 'sortPrice' => false, // 价格排序 (true高到低 false低到高)
  287. ]);
  288. // 排序规则
  289. $sort = [];
  290. if ($params['sortType'] === 'all') {
  291. $sort = ['common_sort' => 'desc'];
  292. } elseif ($params['sortType'] === 'sales') {
  293. $sort = ['goods_sales' => 'desc'];
  294. } elseif ($params['sortType'] === 'price') {
  295. $sort = $params['sortPrice'] ? ['goods_price_max' => 'desc'] : ['goods_price_min' => 'asc'];
  296. } elseif ($params['sortType'] == 'create_time') { // 按上架时间倒序
  297. $sort = ['create_time' => 'desc'];
  298. }
  299. return array_merge($sort, [$this->getPk() => 'desc']);
  300. }
  301. /**
  302. * 检索排序条件
  303. * @param array $param
  304. * @return array|string[]
  305. */
  306. private function setQuerySortZq(array $param = [])
  307. {
  308. $params = $this->setQueryDefaultValue($param, [
  309. 'sortStyle' => 'all', // 排序类型
  310. 'sortSort' => false, // 价格排序 (true高到低 false低到高)
  311. ]);
  312. // 排序规则
  313. $sort = [];
  314. $sortSort = ($params['sortSort'] == 'false' || !$params['sortSort'])?false:true;
  315. if ($params['sortStyle'] == 'all') {//综合
  316. $sort = $sortSort ?['goods_sales' => 'desc']:['goods_sales' => 'asc'];
  317. } elseif ($params['sortStyle'] == 'sales') {
  318. $sort = $sortSort ?['goods_sales' => 'desc']:['goods_sales' => 'asc'];
  319. } elseif ($params['sortStyle'] == 'price') {
  320. $sort = $sortSort ? ['goods_price_max' => 'desc'] : ['goods_price_min' => 'asc'];
  321. } elseif ($params['sortStyle'] == 'create_time') { // 按上架时间倒序
  322. $sort = $sortSort ? ['create_time' => 'desc'] : ['create_time' => 'asc'];
  323. }
  324. return array_merge($sort, [$this->getPk() => 'desc']);
  325. }
  326. /**
  327. * 检索查询条件
  328. * @param array $param
  329. * @return \think\db\BaseQuery
  330. */
  331. private function getQueryFilter(array $param)
  332. {
  333. // 商品列表获取条件
  334. $params = $this->setQueryDefaultValue($param, [
  335. 'listType' => 'all', // 列表模式 (全部:all 出售中:on_sale 已下架:off_sale 已售罄:sold_out)
  336. 'categoryId' => null, // 分类ID集
  337. 'goodsName' => null, // 商品名称
  338. 'goodsNo' => null, // 商品编码
  339. 'status' => 0, // 商品状态(0全部 10上架 20下架)
  340. 'have_stock' => 0, // 是否查找有库存商品
  341. 'stock_status' => -1, // 库存状态 0-预警 1-正常
  342. 'spec_type'=>0
  343. ]);
  344. // 实例化新查询对象
  345. $query = $this->getNewQuery();
  346. // 筛选条件
  347. $filter = [];
  348. // 列表模式
  349. if ($params['listType'] === 'on_sale') {
  350. $filter[] = ['status', '=', GoodsStatusEnum::ON_SALE]; // 出售中
  351. } elseif ($params['listType'] === 'off_sale') {
  352. $filter[] = ['status', '=', GoodsStatusEnum::OFF_SALE]; // 已下架
  353. } elseif ($params['listType'] === 'sold_out') {
  354. $filter[] = ['stock_total', '=', 0]; // 已售罄
  355. }
  356. if(!empty($params['not_goods_id_arr'])){
  357. $filter[] = ['goods.goods_id','not in',$params['not_goods_id_arr']];
  358. }
  359. if(!empty($params['spec_type'])){
  360. $filter[] = ['spec_type','=',$params['spec_type']];
  361. }
  362. if(isset($params['goods_id_arr'])){
  363. $filter[] = ['goods_id','in',$params['goods_id_arr']];
  364. }
  365. // 起止时间
  366. if (!empty($params['betweenTime'])) {
  367. $times = between_time($params['betweenTime']);
  368. $filter[] = ['goods.create_time', '>=', $times['start_time']];
  369. $filter[] = ['goods.create_time', '<', $times['end_time'] + 86400];
  370. }
  371. if (isset($params['stock_status']) && $params['stock_status'] != -1) { // 库存预警
  372. $filter[] = ['status', '=', GoodsStatusEnum::ON_SALE]; // 出售中
  373. $filterSku[] = ['stock_num', 'exp', Db::raw('< `alarm_stock_num`')];
  374. $goodsIds = GoodsSku::where($filterSku)->column('goods_id');
  375. if ($params['stock_status'] == 1) {
  376. if (!empty($goodsIds)) {
  377. $filter[] = ['goods_id', 'not in', $goodsIds];
  378. }
  379. } else {
  380. $filter[] = ['goods_id', 'in', $goodsIds];
  381. }
  382. }
  383. // 商品状态
  384. $params['status'] > 0 && $filter[] = ['status', '=', (int)$params['status']];
  385. $params['have_stock'] > 0 && $filter[] = ['stock_total', '>', 0]; // 有库存
  386. // 商品分类
  387. if ($params['categoryId'] > 0) {
  388. // 关联商品与分类关系记录表
  389. $GoodsCategoryRelName = (new GoodsCategoryRelModel)->getName();
  390. $query->join($GoodsCategoryRelName, "{$GoodsCategoryRelName}.goods_id = {$this->name}.goods_id");
  391. // 设置分类ID条件
  392. $query->where('goods_category_rel.category_id', '=', (int)$params['categoryId']);
  393. }
  394. // 商品名称
  395. !empty($params['goodsName']) && $filter[] = ['goods_name', 'like', "%{$params['goodsName']}%"];
  396. // 商品编码
  397. !empty($params['goodsNo']) && $filter[] = ['goods_no', 'like', "%{$params['goodsNo']}%"];
  398. //普通商品还是赠品
  399. //in_array($params['goods_type'],[10,20]) && $filter[] = ['goods_type','=',$params['goods_type']];
  400. if(isset($params['goods_type']) && ($params['goods_type'] == GoodsType::GIFT || $params['goods_type'] == GoodsType::NORMAL)){
  401. $filter[] = ['goods_type','=',$params['goods_type']];
  402. $filter[] = ['stock_total','>',0];
  403. }elseif(isset($params['goods_type']) && $params['goods_type'] == 90){
  404. //需要单规格的商品或赠品
  405. $filter[] = ['goods_type','<',GoodsType::MULTI];
  406. $filter[] = ['stock_total','>',0];
  407. }elseif(isset($params['goods_type']) && $params['goods_type'] == GoodsType::EXCHANGE){
  408. //积分兑换商品
  409. $filter[] = ['goods_type','=',GoodsType::EXCHANGE];
  410. $filter[] = ['stock_total','>',0];
  411. }else{
  412. if (isset($params['is_backend']) && $params['is_backend'] == 1){
  413. }else{
  414. $filter[] = ['goods_type','<>',GoodsType::GIFT];
  415. }
  416. }
  417. // // 是否显示在商品列表
  418. // $filter[] = ['display', '=', 1]; // 可以显示的
  419. // 实例化新查询对象
  420. return $query->where($filter);
  421. }
  422. /**
  423. * 设置商品展示的数据
  424. * @param Collection|Paginator $list 商品列表
  425. * @param callable|null $callback 回调函数
  426. * @return mixed
  427. */
  428. protected function setGoodsListData($list, callable $callback = null)
  429. {
  430. if ($list->isEmpty()) return $list;
  431. // 遍历商品列表整理数据
  432. foreach ($list as &$goods) {
  433. $goods = $this->setGoodsData($goods, $callback);
  434. }
  435. return $list;
  436. }
  437. /**
  438. * 设置商品展示的结算价格列表
  439. * @param Collection|Paginator $list 商品列表
  440. * @param callable|null $callback 回调函数
  441. * @return mixed
  442. */
  443. protected function setGoodsListDataFinance($list, callable $callback = null)
  444. {
  445. if ($list->isEmpty()) return $list;
  446. // 遍历商品列表整理数据
  447. foreach ($list as &$goods) {
  448. $goods = $this->setGoodsData($goods, $callback);
  449. $goodsArr = $goods->toArray();
  450. $clearing_price_arr = array_column($goodsArr['skues'],'clearing_price');
  451. //dd($clearing_price_arr);
  452. if (count($clearing_price_arr) == 0){
  453. $goods['clearing_price_range'] = '';
  454. } elseif (count($clearing_price_arr) == 1){
  455. $goods['clearing_price_range'] = (string)$clearing_price_arr[0];
  456. }else{
  457. $clearing_price_arr = array_unique($clearing_price_arr);
  458. asort($clearing_price_arr);
  459. $clearing_price_arr = array_values($clearing_price_arr);
  460. $goods['clearing_price_range'] = $clearing_price_arr[0].'~'.$clearing_price_arr[count($clearing_price_arr)-1];
  461. }
  462. $rate_arr = array_column($goodsArr['skues'],'platform_rate');
  463. if (count($rate_arr) == 0){
  464. $goods['platform_rate_range'] = '';
  465. } elseif (count($rate_arr) == 1){
  466. $goods['platform_rate_range'] = (string)$rate_arr[0];
  467. }else{
  468. $rate_arr = array_unique($rate_arr);
  469. asort($rate_arr);
  470. $rate_arr = array_values($rate_arr);
  471. $goods['platform_rate_range'] = $rate_arr[0].'~'.$rate_arr[count($rate_arr)-1];
  472. }
  473. }
  474. return $list;
  475. }
  476. /**
  477. * 整理商品数据
  478. * @param Collection|static $goodsInfo
  479. * @param callable|null $callback
  480. * @return mixed
  481. */
  482. protected function setGoodsData($goodsInfo, callable $callback = null)
  483. {
  484. // 商品图片列表
  485. $goodsInfo['goods_images'] = helper::getArrayColumn($goodsInfo['images'], 'file');
  486. $goodsImages = [];
  487. if (!empty($goodsInfo['goods_images'])) {
  488. foreach ($goodsInfo['goods_images'] as $item) {
  489. $item = $item->toArray();
  490. $item['preview_url'] = config('chef.sso_domain_text').$item['file_path'];
  491. $item['external_url'] = config('chef.sso_domain_text').$item['file_path'];
  492. $goodsImages[] = $item;
  493. }
  494. }
  495. $goodsInfo['goods_images'] = $goodsImages;
  496. // 商品主图
  497. $goodsInfo['goods_image'] = current($goodsInfo['goods_images'])['preview_url'];
  498. // 商品主图 生成海报用
  499. $goodsInfo['goods_image_text'] = current($goodsInfo['goods_images'])['preview_url'];
  500. // 商品销量(实际显示=初始虚拟销量+实际销量)
  501. $goodsInfo['goods_sales'] = $goodsInfo['sales_initial'] + $goodsInfo['sales_actual'];
  502. // 商品库存(总库存=线上库存+门店库存)
  503. $goodsInfo['goods_stocks'] = $goodsInfo['stock_total'] + $goodsInfo['shops_stock_total'];
  504. // 回调函数
  505. is_callable($callback) && call_user_func($callback, $goodsInfo);
  506. return $goodsInfo->hidden(array_merge($this->hidden, ['specRel', 'images']));
  507. }
  508. /**
  509. * 根据商品id集获取商品列表
  510. * @param array $goodsIds
  511. * @param null $status
  512. * @return array|mixed
  513. */
  514. public function getListByIds(array $goodsIds, $status = null)
  515. {
  516. if (empty($goodsIds)) {
  517. return [];
  518. }
  519. // 筛选条件
  520. $filter = [['goods_id', 'in', $goodsIds]];
  521. // 商品状态
  522. $status > 0 && $filter[] = ['status', '=', $status];
  523. // 获取商品列表数据
  524. $data = $this
  525. // ->withoutField(['content'])
  526. ->with(['images.file','category'])
  527. ->where($filter)
  528. ->where('is_delete', '=', 0)
  529. ->orderRaw('field(goods_id, ' . implode(',', $goodsIds) . ')')
  530. ->select();
  531. // 整理列表数据并返回
  532. return $this->setGoodsListData($data);
  533. }
  534. /**
  535. * 商品多规格信息
  536. * @param \think\Collection $specRel
  537. * @param \think\Collection $skuData
  538. * @return array
  539. */
  540. public function getManySpecData($specRel, $skuData)
  541. {
  542. // spec_attr
  543. $specAttrData = [];
  544. foreach ($specRel as $item) {
  545. if (!isset($specAttrData[$item['spec_id']])) {
  546. $specAttrData[$item['spec_id']] = [
  547. 'group_id' => $item['spec']['spec_id'],
  548. 'name' => $item['spec']['spec_name'],
  549. 'spec_items' => [],
  550. ];
  551. }
  552. $specAttrData[$item['spec_id']]['spec_items'][] = [
  553. 'item_id' => $item['spec_value_id'],
  554. 'spec_value' => $item['spec_value'],
  555. ];
  556. }
  557. // spec_list
  558. $specListData = [];
  559. foreach ($skuData as $item) {
  560. $image = (isset($item['images']) && !empty($item['images'])) ? $item['images'] : ['file_id' => 0, 'external_url' => ''];
  561. $specListData[] = [
  562. 'id' => $item['id'],
  563. 'goods_sku_id' => $item['goods_sku_id'],
  564. 'rows' => [],
  565. 'form' => [
  566. 'image_id' => $image['file_id'],
  567. 'image_path' => $image['external_url'],
  568. 'goods_sku_no' => $item['goods_sku_no'],
  569. 'goods_price' => $item['goods_price'],
  570. 'goods_weight' => $item['goods_weight'],
  571. 'line_price' => $item['line_price'],
  572. 'stock_num' => $item['stock_num'],
  573. ],
  574. ];
  575. }
  576. return ['spec_attr' => array_values($specAttrData), 'spec_list' => $specListData];
  577. }
  578. /**
  579. * 获取商品记录
  580. * @param int $goodsId
  581. * @param array $with
  582. * @return static
  583. */
  584. public static function detail(int $goodsId, array $with = [])
  585. {
  586. return static::get($goodsId, $with);
  587. }
  588. /**
  589. * 累积收藏数
  590. * @param int $goodsId 商品ID
  591. * @param int $num 递增的数量
  592. * @return mixed
  593. */
  594. public static function setIncByField(int $goodsId, $field = '', int $num = 1)
  595. {
  596. return (new static)->setInc([['goods_id', '=', $goodsId]], $field, $num);
  597. }
  598. /**
  599. * 累积收藏数
  600. * @param int $goodsId 商品ID
  601. * @param int $num 递减的数量
  602. * @return mixed
  603. */
  604. public static function setDecByField(int $goodsId, $field = '', int $num = 1)
  605. {
  606. return (new static)->setDec([['goods_id', '=', $goodsId]], $field, $num);
  607. }
  608. // /**
  609. // * 指定的商品规格信息
  610. // * @param static $goods 商品详情
  611. // * @param string $goodsSkuId
  612. // * @return array|bool
  613. // */
  614. // public static function getGoodsSku(self $goods, string $goodsSkuId)
  615. // {
  616. // // 获取指定的sku
  617. // $goodsSku = [];
  618. // foreach ($goods['skuList'] as $item) {
  619. // if ($item['goods_sku_id'] == $goodsSkuId) {
  620. // $goodsSku = $item;
  621. // break;
  622. // }
  623. // }
  624. // if (empty($goodsSku)) {
  625. // return false;
  626. // }
  627. // // 多规格文字内容
  628. // $goodsSku['goods_attr'] = '';
  629. // if ($goods['spec_type'] == 20) {
  630. // $specRelData = helper::arrayColumn2Key($goods['spec_rel'], 'spec_value_id');
  631. // $attrs = explode('_', $goodsSku['goods_sku_id']);
  632. // foreach ($attrs as $specValueId) {
  633. // $goodsSku['goods_attr'] .= $specRelData[$specValueId]['spec']['spec_name'] . ':'
  634. // . $specRelData[$specValueId]['spec_value'] . '; ';
  635. // }
  636. // }
  637. // return $goodsSku;
  638. // }
  639. public function getCostsList(array $param = [], int $listRows = 15)
  640. {
  641. // 筛选条件
  642. $query = $this->getQueryFilter($param);
  643. // 排序条件
  644. //$sort = $this->setQuerySort($param);
  645. // 执行查询
  646. $list = $query->with(['provider','skues'])
  647. ->alias($this->name)
  648. ->field($this->getAliasFields($this->name, ['content']))
  649. ->where('is_delete', '=', 0)
  650. ->paginate($listRows);
  651. // 整理列表数据并返回
  652. return $this->setGoodsListDataFinance($list);
  653. }
  654. /**
  655. * 关联供应商表/商铺
  656. * @return \think\model\relation\HasMany
  657. */
  658. public function skues()
  659. {
  660. return $this->hasMany(\app\store\model\GoodsSku::class, 'goods_id', 'goods_id')->field('id,goods_id,clearing_price,platform_rate,goods_props');
  661. }
  662. /**
  663. * 导出提现列表
  664. * @param array $param
  665. * @author: zq
  666. * @Time: 2021/10/15 13:51
  667. */
  668. public function listExport(array $param)
  669. {
  670. //$ids = $param['goods_id'];
  671. $data['header'] = ['商品序号', '商品编码', '商品名称', '供应商名称', '商品分类','售价', '结算价'];
  672. $data['filename'] = '财务成本管理列表导出';
  673. $data['data'] = [];
  674. $query = $this->getQueryFilter($param);
  675. $listI = $query->with(['provider','skues'])
  676. ->alias($this->name)
  677. ->field($this->getAliasFields($this->name, ['content']))
  678. ->where('is_delete', '=', 0)->select();
  679. //->whereIn('goods_id',$ids)
  680. //->paginate(500);
  681. // 整理列表数据并返回
  682. $list = $this->setGoodsListDataFinance($listI);
  683. /* $list = $listPage->toArray();
  684. dd($listPage);*/
  685. foreach ($list as $arr){
  686. $new_list['goods_id'] = $arr['goods_id'];
  687. $new_list['goods_no'] = $arr['goods_no'];
  688. $new_list['goods_name'] = $arr['goods_name'];
  689. $new_list['provider'] = $arr['provider']['provider_name'];
  690. $new_list['category_name'] = $arr['category_name'];
  691. $new_list['goods_prices'] = $arr['goods_price_min'].'~'.$arr['goods_price_max'];
  692. $new_list['clearing_price_range'] = $arr['clearing_price_range'];
  693. $data['data'][] = $new_list;
  694. }
  695. return $data;
  696. }
  697. /**
  698. * 获取商品列表
  699. * @param array $param 查询条件
  700. * @return mixed
  701. * @throws \think\db\exception\DbException
  702. */
  703. public function getListNoPage()
  704. {
  705. $param['sortType'] = 'create_time';
  706. $param['listType'] = 'all';
  707. $param['status'] = 10;
  708. // 筛选条件
  709. $query = $this->getQueryFilter($param);
  710. // 设置显示的销量 goods_sales
  711. // 购买数*1.5+加入购物车数+收藏数*0.8)之和排倒序
  712. $query->field(['(sales_initial + sales_actual + sales_shops) as goods_sales']);
  713. // 排序条件
  714. $sort = $this->setQuerySortZq($param);
  715. // 执行查询
  716. return $query->with(['images.file'])
  717. ->alias($this->name)
  718. ->field($this->getAliasFields($this->name, ['content']))
  719. ->where('status', '=', 10)
  720. ->where('is_delete', '=', 0)
  721. ->order($sort)
  722. ->select();
  723. /* return $list;
  724. dd($list->toArray());
  725. // 整理列表数据并返回
  726. return $this->setGoodsListData($list);*/
  727. }
  728. }