GoodsAttr.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <?php
  2. namespace common\models\goods;
  3. use common\enums\StatusEnum;
  4. use addons\ScoreMall\common\models\ScoreMallGoodsAttr;
  5. use common\models\common\Addons;
  6. use Exception;
  7. use Yii;
  8. /**
  9. * This is the model class for table "{{%goods_attr}}".
  10. *
  11. * @property int $id
  12. * @property int $goods_id 商品ID
  13. * @property string $name 规格名称
  14. * @property string $sign_id 规格ID标识
  15. * @property int $stock 库存
  16. * @property float $price 价格
  17. * @property float $original_price 原价
  18. * @property float $cost_price 成本价
  19. * @property string $goods_no 货号
  20. * @property int $weight 重量(克)
  21. * @property string $pic_url 规格图片
  22. * @property int $version 版本
  23. * @property int $sort 排序
  24. * @property int $created_at 创建时间
  25. * @property int $updated_at 修改时间
  26. * @property int $is_show 是否显示[0隐藏; 1显示]
  27. */
  28. class GoodsAttr extends \common\models\base\BaseActiveRecord
  29. {
  30. /**
  31. * {@inheritdoc}
  32. */
  33. public static function tableName()
  34. {
  35. return '{{%goods_attr}}';
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public function rules()
  41. {
  42. return [
  43. [['goods_id', 'stock', 'status', 'version', 'sort', 'created_at', 'updated_at', 'is_show', 'is_show_code'], 'integer'],
  44. [['price', 'original_price', 'cost_price', 'weight'], 'number'],
  45. [['sign_id', 'pic_url', 'spec_no'], 'string', 'max' => 255],
  46. [['name'], 'string', 'max' => 500],
  47. [['goods_no'], 'safe'],
  48. ];
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. public function attributeLabels()
  54. {
  55. return [
  56. 'id' => 'ID',
  57. 'goods_id' => '商品ID',
  58. 'name' => '规格名称',
  59. 'sign_id' => '规格ID标识',
  60. 'stock' => '库存',
  61. 'price' => '价格',
  62. 'original_price' => '原价',
  63. 'cost_price' => '成本价',
  64. 'goods_no' => '货号',
  65. 'weight' => '重量(克)',
  66. 'pic_url' => '规格图片',
  67. 'status' => '状态[1正常 -1删除]',
  68. 'version' => '版本',
  69. 'sort' => '排序',
  70. 'created_at' => '创建时间',
  71. 'updated_at' => '修改时间',
  72. 'is_show' => '是否显示[0隐藏; 1显示]'
  73. ];
  74. }
  75. // 关联模型
  76. public function getGoods()
  77. {
  78. return $this->hasOne(Goods::class, ['id' => 'goods_id']);
  79. }
  80. public function getBaseGoods()
  81. {
  82. return $this->hasOne(Goods::class, ['id' => 'goods_id'])->select(['id', 'name', 'pic_url']);
  83. }
  84. public function getScoreGoodsAttr() {
  85. return $this->hasOne(ScoreMallGoodsAttr::class, ['goods_attr_id' => 'id'])->andWhere(['status' => [StatusEnum::ENABLED]]);
  86. }
  87. /**
  88. * 保存规格数据
  89. * @Author bing
  90. * @DateTime 2021-09-02 19:37:52
  91. * @copyright: Copyright (c) 2020 广东七件事集团
  92. * @param [type] $goods_id
  93. * @param [type] $attrs
  94. * @param [type] $attr_groups
  95. * @param string $addons 来自插件
  96. * @param callback $call_back 回调函数
  97. * @return void
  98. */
  99. public static function setData($goods_id, $attrs, $attr_groups, &$wait_del_attr_id_arr=[])
  100. {
  101. try{
  102. if($goods_id && $attrs && $attr_groups){
  103. $goods_attr_list = self::lists(['where'=>[['goods_id'=>$goods_id],['status'=>StatusEnum::ENABLED]],'select'=>'id']);
  104. $wait_del_attr_id_arr = array_column($goods_attr_list,'id', 'id');//等待删除的规格id
  105. self::updateAll(['status'=>StatusEnum::DELETE],['goods_id'=>$goods_id]);
  106. $total_stock = 0; // 总库存
  107. $attr_pic_list = array_column($attr_groups[0]['attr_list'], 'pic_url', 'attr_id');
  108. foreach($attrs as $attr){
  109. $attr_ids = array_column($attr['attr_list'],'attr_id');
  110. // 和前端保持一致排序
  111. asort($attr_ids);
  112. $attr['pic_url'] = $attr_pic_list[$attr_ids[0]] ?? '';
  113. $attr['sign_id'] = implode(':',$attr_ids);
  114. $attr_group_name_list = array_column($attr['attr_list'], 'attr_group_name');
  115. $attr_name_list = array_column($attr['attr_list'], 'attr_name');
  116. $attr_name_arr = [];
  117. foreach ($attr_group_name_list as $index => $attr_group_name) {
  118. $attr_name_arr[] = $attr_group_name . ':' . $attr_name_list[$index];
  119. }
  120. $attr['name'] = implode(',',$attr_name_arr);
  121. $attr['weight'] = empty($attr['weight']) ? 0: $attr['weight'];
  122. $total_stock += $attr['stock'];
  123. if(!empty($attr['id'])){
  124. $model = self::findOne(['id' => $attr['id'],'goods_id' => $goods_id]);
  125. $model->status = StatusEnum::ENABLED;
  126. //移除状态正常的规格id
  127. unset($wait_del_attr_id_arr[$attr['id']]);
  128. }else{
  129. $model = new self();
  130. $model->loadDefaultValues();
  131. $model->goods_id = $goods_id;
  132. }
  133. if(!$model->load($attr,'') || !$model->save()){
  134. throw new Exception($model->getErrorMessage());
  135. }
  136. }
  137. // 更新商品库存
  138. $goods = Goods::findOne($goods_id);
  139. $goods->stock = $total_stock;
  140. if(!$goods->save()) throw new Exception($goods->getErrorMessage());
  141. }
  142. return true;
  143. }catch(Exception $e){
  144. self::$static_error = $e->getMessage();
  145. return false;
  146. }
  147. }
  148. /**
  149. * 无规格商品添加货品数据
  150. * @Author bing
  151. * @DateTime 2021-09-02 19:37:52
  152. * @copyright: Copyright (c) 2020 广东七件事集团
  153. * @param [type] $goods_id
  154. * @param [type] $attrs
  155. * @param [type] $attr_groups
  156. * @return void
  157. */
  158. public static function setAttr($goods_id,$attr){
  159. try{
  160. self::updateAll(['status'=>StatusEnum::DELETE],['goods_id'=>$goods_id]);
  161. $model = self::findOne(['goods_id' => $goods_id]);
  162. if(empty($model)){
  163. $model = new self();
  164. $model->loadDefaultValues();
  165. $model->goods_id = $goods_id;
  166. }else{
  167. $model->status = StatusEnum::ENABLED;
  168. $model->name = '';
  169. }
  170. if(!$model->load($attr,'') || !$model->save()){
  171. throw new Exception($model->getErrorMessage());
  172. }
  173. return true;
  174. }catch(Exception $e){
  175. self::$static_error = $e->getMessage();
  176. return false;
  177. }
  178. }
  179. /**
  180. * 获取规格列表
  181. * @Author bing
  182. * @DateTime 2021-08-26 13:00:11
  183. * @copyright: Copyright (c) 2020 广东七件事集团
  184. * @param array $cond
  185. * @param array $with
  186. * @param integer $is_array
  187. * @return array|null
  188. */
  189. public static function getGoodsAttrs(array $cond=[],array $with=[],bool $is_array=true,$select='*'){
  190. $default_cond = [['<>','status',StatusEnum::DELETE]];
  191. $cond = array_merge($default_cond,$cond);
  192. $query = self::find()->select($select);
  193. self::paramPack(['where'=>$cond,'with'=>$with],$query);
  194. $attrs = $query->asArray($is_array)->all();
  195. return $attrs;
  196. }
  197. /**
  198. * 格式化表单需要的规格
  199. * @Author bing
  200. * @DateTime 2021-09-03 15:52:03
  201. * @copyright: Copyright (c) 2020 广东七件事集团
  202. * @param array $attrs
  203. * @param array $format_attr_group
  204. * @return void
  205. */
  206. public static function formatFormAttr(array $attrs,array $format_attr_group){
  207. if(empty($attrs)) return $attrs;
  208. foreach ($attrs as $key => $attr) {
  209. $attrs[$key]['attr_list'] = $format_attr_group[$attr['sign_id']] ?? [];
  210. }
  211. return $attrs;
  212. }
  213. /**
  214. * 获取所选的规格
  215. * @param $sign_id
  216. * @param $attr_groups_format
  217. * @return string
  218. */
  219. public static function getAttrStr($sign_id,$attr_groups_format){
  220. $attr_name = '';
  221. if(empty($attr_groups_format[$sign_id])) return '默认规格';
  222. foreach ($attr_groups_format[$sign_id] as $val) {
  223. $attr_name .= $val['attr_name'].',';
  224. }
  225. return trim($attr_name,',');
  226. }
  227. /**
  228. * 获取sku数据
  229. * @param $goods_attr_list
  230. * @param $attr_groups_format
  231. * @return array
  232. */
  233. public static function getSkuArr($goods_attr_list,$attr_groups_format){
  234. $sku_arr = [];
  235. foreach ($goods_attr_list as $v) {
  236. $sku_arr[$v['goods_id']][] = [
  237. 'id' => empty($v['sign_id'])?$v['goods_id']:$v['id'],
  238. 'sign_id' => empty($v['sign_id'])?$v['goods_id']:$v['sign_id'],
  239. 'attr_name' => self::getAttrStr($v['sign_id'],$attr_groups_format),
  240. 'price' => $v['price'],
  241. 'pic_url' => $v['pic_url'],
  242. 'stock' => $v['stock'],
  243. ];
  244. }
  245. return $sku_arr;
  246. }
  247. /**
  248. * @desc:扣减规格库存
  249. * @Author: hua
  250. * @Date: 2021/11/9
  251. * @Time: 11:46
  252. * @Copyright: copyright (c) 2021 广东七件事集团
  253. * @param $goods_attr_id
  254. * @param $num +增加 -减少
  255. * @return bool
  256. * @throws Exception
  257. */
  258. public static function handleStock($goods_attr_id,$num){
  259. try{
  260. $model = self::findOne(['id'=>$goods_attr_id,'status'=>StatusEnum::ENABLED]);
  261. if(empty($model)) throw new Exception('规格不存在');
  262. if(!is_int($num)) throw new Exception('库存数量必须为整数');
  263. if($num < 0 && $model->stock < abs($num)) throw new Exception('库存不足');
  264. $model->stock += $num;
  265. $res = $model->save();
  266. if($res === false) throw new Exception($model->getErrorMessage());
  267. return true;
  268. }catch(Exception $e){
  269. self::setStaticError($e->getMessage());
  270. return false;
  271. }
  272. }
  273. }