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 queryPageMerchantProductH5List(int merId , String keyword, Integer cid, Double maxPrice, Double minPrice, String salesOrder, String priceOrder){ Map 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 skuIdList){ if(skuIdList != null){ Map 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 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 addAttrList, List updateAttrList , List addAttrValueList, List updateAttrValueList , EbProductDescription spd, List 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 productAttrList , List productAttrValueList, EbProductDescription spd, List 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 queryPageMerchantProductList(ProductParam productParam){ Map 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 queryTabsHeader() { List 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 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 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"; }