shikeyin
2024-01-11 65da8373531677b1c37a98f53eaa30c892f35e5a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
package com.ishop.merchant.service;
 
import com.ishop.merchant.Constants;
import com.ishop.merchant.ProductConstants;
import com.ishop.merchant.pojo.ProductParam;
import com.ishop.model.po.EbMerchantInfo;
import com.ishop.model.po.EbProduct;
import com.ishop.model.po.EbProductAttr;
import com.ishop.model.po.EbProductAttrValue;
import com.ishop.model.po.EbProductCoupon;
import com.ishop.model.po.EbProductDescription;
import com.ishop.model.vo.ProductTabsHeaderVo;
import com.walker.db.page.GenericPager;
import com.walker.infrastructure.utils.StringUtils;
import com.walker.infrastructure.utils.UrlUtils;
import com.walker.jdbc.service.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
@Service
public class ProductServiceImpl extends BaseServiceImpl {
 
    private ProductDescriptionServiceImpl productDescriptionService;
    private ProductRelationServiceImpl productRelationService;
    private ProductAttrServiceImpl productAttrService;
    private ProductAttrValueServiceImpl productAttrValueService;
 
    @Autowired
    public ProductServiceImpl(ProductDescriptionServiceImpl productDescriptionService
            , ProductRelationServiceImpl productRelationService
            , ProductAttrServiceImpl productAttrService, ProductAttrValueServiceImpl productAttrValueService){
        this.productDescriptionService = productDescriptionService;
        this.productRelationService = productRelationService;
        this.productAttrService = productAttrService;
        this.productAttrValueService = productAttrValueService;
    }
 
    /**
     * 判断给定'平台分类'下面是否存在关联商品
     * @param platformCategoryId
     * @return 存在返回true,不存在返回false
     * @date 2023-07-31
     */
    public boolean queryExistCategoryProductRef(int platformCategoryId){
        int total = this.sqlMathQuery("select count(id) total from eb_product where category_id=?", new Object[]{platformCategoryId}, Integer.class);
        return total > 0;
    }
 
    /**
     * 分页查询商户商品列表,移动端使用
     * @param merId 商户ID
     * @param keyword 关键词
     * @param cid 分类
     * @param maxPrice 最大价格
     * @param minPrice 最小价格
     * @param salesOrder 销量排序
     * @param priceOrder 价格排序
     * @return
     * @date 2023-07-05
     */
    public GenericPager<EbProduct> queryPageMerchantProductH5List(int merId
            , String keyword, Integer cid, Double maxPrice, Double minPrice, String salesOrder, String priceOrder){
        Map<String, Object> param = new HashMap<>(4);
        StringBuilder sql = new StringBuilder(SQL_PRODUCT_H5_LIST);
        sql.append(" where mer_id=:merId and is_del=0 and is_recycle=0 and is_show=1 and (audit_status=2 or audit_status=0)");
        param.put("merId", merId);
        if(StringUtils.isNotEmpty(keyword)){
            sql.append(" and (name like :keyword or keyword like :keyword)");
            param.put("keyword", StringUtils.CHAR_PERCENT + keyword + StringUtils.CHAR_PERCENT);
        }
        if(cid != null && cid.intValue() > 0){
 
        }
        if(maxPrice != null){
            sql.append(" and price<=:maxPrice");
            param.put("maxPrice", maxPrice);
        }
        if(minPrice != null){
            sql.append(" and price>=:minPrice");
            param.put("minPrice", minPrice);
        }
        if(StringUtils.isNotEmpty(salesOrder)){
            if(salesOrder.equals(Constants.SORT_ASC)){
                sql.append(" order by sales asc, sort desc");
            } else {
                sql.append(" order by sales desc, sort desc");
            }
        } else if(StringUtils.isNotEmpty(priceOrder)){
            if(priceOrder.equals(Constants.SORT_ASC)){
                sql.append(" order by price asc, sort desc");
            } else {
                sql.append(" order by price desc, sort desc");
            }
        }
        return this.selectSplit(sql.toString(), param, new EbProduct());
    }
    private static final String SQL_PRODUCT_H5_LIST = "select id, mer_id,image,name,price,ot_price,stock,sales,intro,ficti,browse,unit_name,brand_id,category_id from eb_product";
 
    /**
     * 商品下架
     * @param productId
     * @date 2023-08-02
     */
    public void execProductDown(long productId){
        // 1:购物车中商品状态更新:不可用
        this.execute("update eb_cart set status=0 where product_id=? and status=1", new Object[]{productId});
        // 2:用户收藏表,删除商品
        this.productRelationService.execDeleteProduct(productId);
        // 3:更新商品状态
        this.execute("update eb_product set is_show=0 where id=?", new Object[]{productId});
    }
 
    /**
     * 商品上架
     * @param productId 商品id
     * @param skuIdList 购物车中更新(sku)状态为可用
     * @date 2023-08-02
     */
    public void execProductUp(long productId, List<Integer> skuIdList){
        if(skuIdList != null){
            Map<String, Object> parameter = new HashMap<>(2);
            parameter.put("status", 1);
            parameter.put("skuIds", skuIdList);
            this.execute(SQL_CART_STATUS, parameter);
        }
        this.execute("update eb_product set is_show=1 where id=?", new Object[]{productId});
    }
    private static final String SQL_CART_STATUS = "update eb_cart set status=:status where product_attr_unique in (:skuIds)";
 
    /**
     * 操作库存
     * @param id 商品ID
     * @param num 数量
     * @param type 类型:add—添加,sub—扣减
     * @return
     */
    public int execOperateStock(long id, Integer num, String type){
        Map<String, Object> param = new HashMap<>(4);
        StringBuilder sql = new StringBuilder("update eb_product");
        if(type.equals(Constants.OPERATION_TYPE_QUICK_ADD)){
            sql.append(" set stock=stock+:num");
            param.put("num", num);
        } else if(type.equals(Constants.OPERATION_TYPE_ADD)){
            sql.append(" set stock=stock+:num");
            sql.append(",sales=sales-:num");
            param.put("num", num);
        } else if(type.equals(Constants.OPERATION_TYPE_SUBTRACT)){
            sql.append(" set stock=stock-:num");
            sql.append(",sales=sales+:num");
            param.put("num", num);
        } else {
            throw new UnsupportedOperationException("不支持的库存操作类型:" + type);
        }
        sql.append(" where id=:id");
        param.put("id", id);
        return this.execute(sql.toString(), param);
    }
 
    /**
     * 更新商品信息。
     * @param product 商品
     * @param addAttrList 添加的规格
     * @param updateAttrList 更新的规格
     * @param addAttrValueList 添加的自定义属性值
     * @param updateAttrValueList 更新的自定义属性值
     * @param spd 描述信息
     * @param couponList 优惠券集合
     * @date 2023-08-02
     */
    public void execUpdateProduct(EbProduct product
            , List<EbProductAttr> addAttrList, List<EbProductAttr> updateAttrList
            , List<EbProductAttrValue> addAttrValueList, List<EbProductAttrValue> updateAttrValueList
            , EbProductDescription spd, List<EbProductCoupon> couponList){
 
        // attr
        this.productAttrService.execDeleteByProductIdAndType(product.getId(), ProductConstants.PRODUCT_TYPE_NORMAL);
        if(!StringUtils.isEmptyList(addAttrList)){
            int attrId = this.queryAttrNextId();
            for(EbProductAttr attr: addAttrList){
                attr.setId(attrId++);
            }
            this.insertBatch(addAttrList);
        }
        if(!StringUtils.isEmptyList(updateAttrList)){
            this.updateBatch(updateAttrList);
        }
 
        // attr value
        this.productAttrValueService.execDeleteByProductIdAndType(product.getId(), ProductConstants.PRODUCT_TYPE_NORMAL);
        if(!StringUtils.isEmptyList(addAttrValueList)){
            int attrValueId = this.queryAttrValueNextId();
            for(EbProductAttrValue attrValue: addAttrValueList){
                attrValue.setId(attrValueId++);
            }
            this.insertBatch(addAttrValueList);
        }
        if(!StringUtils.isEmptyList(updateAttrValueList)){
            this.updateBatch(updateAttrValueList);
        }
 
        if(spd != null){
            this.deleteProductDescription(product.getId(), ProductConstants.PRODUCT_TYPE_NORMAL);
            this.insert(spd);
        }
 
        // 先删除商品关联优惠券,如果存在添加的在加入。
        this.execDeleteProductCouponList(product.getId());
        if(!StringUtils.isEmptyList(couponList)){
            this.insertBatch(couponList);
        }
        this.save(product);
    }
 
    /**
     * 根据商品ID,删除关联的商品优惠券集合
     * @param productId
     * @date 2023-08-02
     */
    public void execDeleteProductCouponList(long productId){
        this.execute("delete from eb_product_coupon where product_id=?", new Object[]{productId});
    }
 
    /**
     * 商户新增一个商品信息。
     * @param product
     * @param productAttrList
     * @param productAttrValueList
     * @param spd
     * @param couponList
     */
    public void execInsertProduct(EbProduct product, List<EbProductAttr> productAttrList
            , List<EbProductAttrValue> productAttrValueList, EbProductDescription spd, List<EbProductCoupon> couponList){
        if(!StringUtils.isEmptyList(productAttrList)){
            int attrId = this.queryAttrNextId();
            for(EbProductAttr attr: productAttrList){
                attr.setId(attrId++);
            }
            this.insertBatch(productAttrList);
        }
        if(!StringUtils.isEmptyList(productAttrValueList)){
            int attrValueId = this.queryAttrValueNextId();
            for(EbProductAttrValue attrValue: productAttrValueList){
                attrValue.setId(attrValueId++);
            }
            this.insertBatch(productAttrValueList);
        }
        if(spd != null){
            this.deleteProductDescription(product.getId(), ProductConstants.PRODUCT_TYPE_NORMAL);
            this.insert(spd);
        }
        if(!StringUtils.isEmptyList(couponList)){
            this.insertBatch(couponList);
        }
        this.insert(product);
    }
 
    private void deleteProductDescription(long productId, int type){
        this.execute("delete from eb_product_description where product_id=? and type=?", new Object[]{productId, type});
    }
 
    /**
     * 查询商家推荐的商品。
     * @param merId
     * @param limit 限制条数
     * @return
     * @date 2023-07-04
     */
    public List queryRecommendedProductsByMerId(int merId, int limit){
        return this.select(SQL_PRODUCT_RECOMMEND, new Object[]{merId,limit}, new EbProduct());
    }
    private static final String SQL_PRODUCT_RECOMMEND = "select id,mer_id,image,name,price,sales,ficti from eb_product where mer_id=? and is_del=0 and is_recycle=0 and is_show=1 and (audit_status=2 or audit_status=0) limit ?";
 
    /**
     * 返回H5移动端商品详情。
     * @param id 商品ID
     * @return
     * @date 2023-07-04
     */
    public EbProduct queryH5Detail(long id){
        EbProduct product = this.get(SQL_PRODUCT_DETAIL_H5, new Object[]{id}, new EbProduct());
        EbProductDescription description = this.productDescriptionService.queryProductDescription(ProductConstants.PRODUCT_TYPE_NORMAL, id);
        if(description != null){
            product.setParameterString("content", StringUtils.isNotEmpty(description.getDescription())? description.getDescription():StringUtils.EMPTY_STRING);
        }
        return product;
    }
 
    private static final String SQL_PRODUCT_DETAIL_H5 = "select id, mer_id,image,name,slider_image,ot_price,stock,sales,price,intro,ficti,browse,unit_name,guarantee_ids,brand_id,category_id from eb_product where id=?";
 
    /**
     * 商户端,商品管理列表。
     * @param productParam
     * @return
     * @date 2023-06-15
     */
    public GenericPager<EbProduct> queryPageMerchantProductList(ProductParam productParam){
        Map<String, Object> parameters = new HashMap<>(4);
        StringBuilder sql = new StringBuilder("select * from eb_product where mer_id=:merId");
        parameters.put("merId", productParam.getMerId());
        this.searchConditionByType(sql, productParam.getType(), productParam.getMerId());
        // 2023-07-31 平台商品分类
        if(productParam.getCategoryId() != null && productParam.getCategoryId() > 0){
            sql.append(" and category_id=:categoryId");
            parameters.put("categoryId", productParam.getCategoryId());
        }
        if(StringUtils.isNotEmpty(productParam.getKeywords())){
            sql.append(" and (keyword like :keywords or name like :keywords)");
            parameters.put("keywords", StringUtils.CHAR_PERCENT + UrlUtils.decode(productParam.getKeywords()) + StringUtils.CHAR_PERCENT);
        }
        if(StringUtils.isNotEmpty(productParam.getCateId())){
            sql.append(" and cate_id like :cateId");
            parameters.put("cateId", StringUtils.CHAR_PERCENT + productParam.getCateId() + StringUtils.CHAR_PERCENT);
        }
 
        sql.append(" order by create_time desc");
        return this.selectSplit(sql.toString(), parameters, new EbProduct());
    }
 
    private void searchConditionByType(StringBuilder sql, Integer type, Integer merId){
        if(type.intValue() == ProductConstants.PRODUCT_STATUS_UP){
            sql.append(" and is_show=1 and is_recycle=0 and is_del=0");
            sql.append(" and audit_status in (2,0)");
        } else if(type.intValue() == ProductConstants.PRODUCT_STATUS_DOWN){
            //仓库中(未上架)
            sql.append(" and is_show=0 and is_recycle=0 and is_del=0 and is_audit=0");
            sql.append(" and audit_status in (1,2,0)");
        } else if(type.intValue() == ProductConstants.PRODUCT_STATUS_OVER){
            //已售罄
            sql.append(" and stock<=0 and is_recycle=0 and is_del=0");
            sql.append(" and audit_status in (2,0)");
        } else if(type.intValue() == ProductConstants.PRODUCT_STATUS_WARN){
            //警戒库存
            EbMerchantInfo merchantInfo = new EbMerchantInfo();
            merchantInfo.setMerId(merId);
            merchantInfo = this.get(merchantInfo);
            Integer alertStock = 0;
            if(merchantInfo != null){
                alertStock = merchantInfo.getAlertStock();
            }
            sql.append(" and stock=").append(alertStock==null? 0 : alertStock);
            sql.append(" and is_recycle=0 and is_del=0");
            sql.append(" and audit_status in (2,0)");
        } else if(type.intValue() == ProductConstants.PRODUCT_STATUS_CYCLE){
            //回收站
            sql.append(" and is_recycle=1 and is_del=0");
        } else if(type.intValue() == ProductConstants.PRODUCT_STATUS_WAIT_AUDIT){
            //待审核
            sql.append(" and audit_status=1 and is_audit=1 and is_recycle=0 and is_del=0");
        } else if(type.intValue() == ProductConstants.PRODUCT_STATUS_AUDIT_FAILED){
            //审核失败
            sql.append(" and audit_status=3 and is_audit=0 and is_recycle=0 and is_del=0");
        }
    }
 
    /**
     * 平台商品分类统计,暂时先不实现。
     * @return
     * @date 2023-06-11
     */
    public List<ProductTabsHeaderVo> queryTabsHeader() {
        List<ProductTabsHeaderVo> headers = new ArrayList<>();
        ProductTabsHeaderVo header1 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_UP);
        ProductTabsHeaderVo header2 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_DOWN);
        ProductTabsHeaderVo header3 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_OVER);
        ProductTabsHeaderVo header4 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_WARN);
        ProductTabsHeaderVo header5 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_CYCLE);
        ProductTabsHeaderVo header6 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_WAIT_AUDIT);
        ProductTabsHeaderVo header7 = new ProductTabsHeaderVo(1, ProductConstants.PRODUCT_STATUS_AUDIT_FAILED);
        headers.add(header1);
        headers.add(header2);
        headers.add(header3);
        headers.add(header4);
        headers.add(header5);
        headers.add(header6);
        headers.add(header7);
        return headers;
    }
 
    /**
     * 平台分页查询商品信息列表
     * @param productParam
     * @return
     * @date 2023-06-11
     */
    public GenericPager<EbProduct> queryPageProductList(ProductParam productParam){
        StringBuilder sql = new StringBuilder(SQL_PAGE_LIST);
        if(productParam == null){
            sql.append(SQL_PAGE_ORDER);
            return this.selectSplit(sql.toString(), new Object[]{}, new EbProduct());
        }
 
        Map<String, Object> parameters = new HashMap<>(4);
 
        int type = productParam.getType();
        if(type == ProductConstants.PRODUCT_STATUS_UP){
            sql.append(" and p.is_show = 1");
            sql.append(" and (p.audit_status=0 or p.audit_status=2)");
        } else if(type == ProductConstants.PRODUCT_STATUS_DOWN){
            sql.append(" and p.is_show = 0");
            sql.append(" and p.is_audit = 0");
            sql.append(" and p.audit_status in (0,1,2)");
        } else if(type == ProductConstants.PRODUCT_STATUS_WAIT_AUDIT){
            sql.append(" and p.audit_status = 1");
            sql.append(" and p.is_audit = 1");
        } else if (type == ProductConstants.PRODUCT_STATUS_AUDIT_FAILED) {
            sql.append(" and p.audit_status = 3");
            sql.append(" and p.is_audit = 0");
        }
 
        if(productParam.getMerId() != null && productParam.getMerId().intValue() > 0){
            sql.append(" and p.mer_id=:merId");
            parameters.put("merId", productParam.getMerId());
        }
        if(productParam.getIsSelf() != null){
            sql.append(" and m.is_self=:isSelf");
            parameters.put("isSelf", productParam.getIsSelf());
        }
        if(productParam.getCategoryId() != null){
            sql.append(" and p.category_id=:categoryId");
            parameters.put("categoryId", productParam.getCategoryId());
        }
        if(StringUtils.isNotEmpty(productParam.getKeywords())){
            sql.append(" and (p.name like :keywords or p.keyword like :keywords)");
            parameters.put("keywords", StringUtils.CHAR_PERCENT + productParam.getKeywords() + StringUtils.CHAR_PERCENT);
        }
        sql.append(SQL_PAGE_ORDER);
        return this.selectSplit(sql.toString(), parameters, new EbProduct());
    }
 
    public int queryAttrNextId(){
        int maxId = this.queryForInt(ATTR_NEXT_ID, new Object[]{});
        return maxId+1;
    }
    public int queryAttrValueNextId(){
        int maxId = this.queryForInt(ATTR_VALUE_NEXT_ID, new Object[]{});
        return maxId+1;
    }
 
    private static final String ATTR_NEXT_ID = "select max(id) from eb_product_attr";
    private static final String ATTR_VALUE_NEXT_ID = "select max(id) from eb_product_attr_value";
    private static final String SQL_PAGE_ORDER = " ORDER BY p.rank desc, p.id desc";
    private static final String SQL_PAGE_LIST = "SELECT p.id,p.mer_id,p.image,p.name,p.keyword,p.category_id,p.price,p.sales" +
            ",p.stock,p.ficti,p.audit_status,p.reason,p.rank FROM eb_product p right join eb_merchant m on p.mer_id = m.id " +
            "where p.is_del = 0 and p.is_recycle = 0";
}