first commit

This commit is contained in:
@jyuhsin
2026-01-14 14:49:41 +08:00
commit 105c955abd
4752 changed files with 911871 additions and 0 deletions
@@ -0,0 +1,25 @@
package com.budwk.app.zhgh.mall.controller.buy;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @nameMallBuyHomeController
* @Date 2025/8/6 11:14
* @注释
*/
@IocBean
@Ok("json:full")
@At("/platform/mall/buy/home")
public class MallBuyHomeController {
@At("")
@Ok("beetl:/platform/zhgh/mall/buy/home/index.html")
// @SaCheckPermission("mall.category.manage")
public void index() {
}
}
@@ -0,0 +1,25 @@
package com.budwk.app.zhgh.mall.controller.buy;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @nameMallCartHomeController
* @Date 2025/8/6 16:20
* @注释
*/
@IocBean
@Ok("json:full")
@At("/platform/mall/buy/cart")
public class MallCartHomeController {
@At("")
@Ok("beetl:/platform/zhgh/mall/buy/cart/index.html")
// @SaCheckPermission("mall.category.manage")
public void index() {
}
}
@@ -0,0 +1,150 @@
package com.budwk.app.zhgh.mall.controller.manage.goods;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.mall.models.entity.goods.MallCategory;
import com.budwk.app.zhgh.mall.param.goods.MallCategorySearchParams;
import com.budwk.app.zhgh.mall.service.goods.MallCategoryService;
import com.budwk.app.zhgh.mall.models.vo.goods.MallCategoryVO;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallCategoryManagerController
* @Date 2025/7/16 9:23
* @注释 商品分类
*/
@IocBean
@Ok("json:full")
@At("/platform/mall/category/manage")
public class MallCategoryManagerController {
@Inject
private Dao dao;
@Inject
private MallCategoryService categoryService;
@At("")
@Ok("beetl:/platform/zhgh/mall/manage/goods/category/index.html")
// @SaCheckPermission("mall.category.manage")
public void index() {
}
/**
* 查询某分类下的全部子分类列表
* @param parentId
* @return
*/
@At("/all-children")
// @SaCheckPermission("mall.category.manage")
public Result list(@Valid String parentId){
List<MallCategory> query = dao.query(MallCategory.class, Cnd.where("parentId", "=", parentId).asc("sortOrder"));
return Result.success(query);
}
/**
* 查询全部分类列表
* @param categorySearchParams
* @return
*/
@At("/allChildren")
// @SaCheckPermission("mall.category.manage")
public Result list(MallCategorySearchParams categorySearchParams){
List<MallCategoryVO> mallCategoryVOList = categoryService.listCategory(categorySearchParams);
return Result.success(mallCategoryVOList);
}
@At
@SLog(tag = "商品分类", msg = "添加商品分类")
// @SaCheckPermission("mall.category.manage")
public Result saveCategory(MallCategory category){
if (category.getParentId() != null && !"0".equals(category.getParentId())) {
int count = dao.count(MallCategory.class, Cnd.where("id", "=", category.getParentId()));
if (count == 0) {
return Result.error("该分类名称已存在");
}
if (category.getLevel() >= 4) {
return Result.error("最多为三级分类,添加失败");
}
}
categoryService.saveCategory(category);
return Result.success();
}
@At
@SLog(tag = "商品分类", msg = "修改商品分类")
// @SaCheckPermission("mall.category.manage")
public Result updateCategory(@Valid MallCategoryVO category) {
int count = dao.count(MallCategory.class, Cnd.where(MallCategory::getId, "=", category.getId()));
if (count == 0) {
return Result.error("该分类不存在");
}
//判断父分类与子分类的状态是否一致
if (category.getParentId() != null && !"0".equals(category.getParentId())) {
MallCategory parentCategory = dao.fetch(MallCategory.class, Cnd.where(MallCategory::getId, "=", category.getParentId()));
if (!parentCategory.getDelFlag().equals(category.getDelFlag())) {
return Result.error("父分类与子分类状态不一致");
}
}
dao.update(category);
return Result.success();
}
@At
@SLog(tag = "商品分类", msg = "删除商品分类")
// @SaCheckPermission("mall.category.manage")
public Result delAllByIds(@Valid String id) {
MallCategory category = new MallCategory();
category.setParentId(id);
Cnd cnd = Cnd.NEW();
cnd.andEX("level", "=", category.getLevel());
cnd.andEX("name", "=", category.getName());
cnd.andEX("parentId", "=", category.getParentId());
cnd.andEX("id", "<>", category.getId());
cnd.andEX("delFlag", "=", false);
cnd.asc("sortOrder");
List<MallCategory> list = dao.query(MallCategory.class, cnd);
if (Lang.isNotEmpty(list)) {
return Result.error("此类别下存在子类别不能删除");
}
// int count = dao.count(MallGoods.class, Cnd.where(MallGoods::getCategoryPath, "=", category.getId()).and(MallGoods::getDelFlag, "=", false));
// if (count > 0) {
// return Result.error("此类别下存在商品不能删除");
// }
dao.clear(MallCategory.class, Cnd.where(MallCategory::getId, "=", id));
return Result.success();
}
@At
@SLog(tag = "商品分类", msg = "后台 禁用/启用 分类")
// @SaCheckPermission("mall.category.manage")
public Result disable(@Valid String id, Boolean enableOperations){
int count = dao.count(MallCategory.class, Cnd.where(MallCategory::getId, "=", id));
if (count == 0) {
return Result.error("商品分类不存在");
}
categoryService.updateCategoryStatus(id, enableOperations);
return Result.success();
}
}
@@ -0,0 +1,31 @@
package com.budwk.app.zhgh.mall.controller.manage.goods;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsStoreController
* @Date 2025/7/16 17:02
* @注释 商品仓库管理
*/
@IocBean
@Ok("json:full")
@At("/platform/mall/goods/manage")
public class MallGoodsManageController {
@Inject
private Dao dao;
@At("")
@Ok("beetl:/platform/zhgh/mall/goods/goodsManage.html")
// @SaCheckPermission("mall.goods.manage")
public void index() {
}
}
@@ -0,0 +1,67 @@
package com.budwk.app.zhgh.mall.controller.manage.goods;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.mall.models.dto.goods.MallGoodsOperationDTO;
import com.budwk.app.zhgh.mall.models.vo.goods.MallGoodsVO;
import com.budwk.app.zhgh.mall.service.goods.MallGoodsService;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.validation.Valid;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsStoreController
* @Date 2025/7/16 17:09
* @注释 商品添加管理
*/
@IocBean
@Ok("json:full")
@At("/platform/mall/goods/store")
public class MallGoodsStoreController {
@Inject
private Dao dao;
@Inject
private MallGoodsService goodsService;
@At("")
// @SaCheckPermission("mall.goods.store")
@Ok("beetl:/platform/zhgh/mall/manage/goods/add/index.html")
public void index() {
}
@At
@Aop(TransAop.READ_COMMITTED)
// @SaCheckPermission("mall.goods.store")
@SLog(tag = "添加商品", msg = "商品名称:${args[0].goodsName}")
public Result save(@Valid MallGoodsOperationDTO goodsOperationDTO) {
goodsService.addGoods(goodsOperationDTO);
return Result.success();
}
@At
@Aop(TransAop.READ_COMMITTED)
// @SaCheckPermission("mall.goods.store")
@SLog(tag = "修改商品", msg = "商品名称:${args[0].goodsName}")
public Result update(@Valid @Param("goodsOperationDTO") MallGoodsOperationDTO goodsOperationDTO, @Param("goodsId") String goodsId){
goodsService.editGoods(goodsOperationDTO, goodsId);
return Result.success();
}
@At
// @SaCheckPermission("mall.goods.store")
public Result getGoodsStoreById(@Valid String id){
MallGoodsVO goodsVO = goodsService.getGoodsVO(id);
return Result.success().addData(goodsVO);
}
}
@@ -0,0 +1,71 @@
package com.budwk.app.zhgh.mall.models.dto.goods;
import cn.hutool.json.JSONObject;
import com.budwk.app.zhgh.mall.models.entity.goods.MallCategory;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsImportDTO
* @Date 2025/7/16 17:16
* @注释
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MallGoodsImportDTO {
@ApiModelProperty(value = "商品名称")
private String goodsName;
@ApiModelProperty(value = "商品卖点")
private String sellingPoint;
@ApiModelProperty(value = "商品分类")
private MallCategory category;
@ApiModelProperty(value = "运费模板")
private String template;
@ApiModelProperty(value = "计量单位")
private String goodsUnit;
@ApiModelProperty(value = "发布状态")
private Boolean release;
@ApiModelProperty(value = "商品图片")
private List<String> images;
private List<JSONObject> goodsGalleryFiles;
@ApiModelProperty(value = "成本价")
private Double cost;
@ApiModelProperty(value = "销售价")
private Double price;
@ApiModelProperty(value = "库存")
private Integer quantity;
@ApiModelProperty(value = "重量")
private Double weight;
@ApiModelProperty(value = "货号")
private String sn;
@ApiModelProperty(value = "详情")
private String intro;
@ApiModelProperty(value = "规格项")
private String skuKey;
@ApiModelProperty(value = "规格值")
private String skuValue;
}
@@ -0,0 +1,104 @@
package com.budwk.app.zhgh.mall.models.dto.goods;
import cn.hutool.json.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import org.nutz.lang.util.NutMap;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsOperationDTO
* @Date 2025/7/16 17:13
* @注释
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MallGoodsOperationDTO implements Serializable {
@Serial
private static final long serialVersionUID = -509667581371776913L;
@ApiModelProperty(hidden = true)
private String goodsId;
@ApiModelProperty(value = "商品价格", required = true)
@NotNull(message = "商品价格不能为空")
@Min(value = 0, message = "商品价格不能为负数")
@Max(value = 99999999, message = "商品价格不能超过99999999")
private Double price;
@ApiModelProperty(value = "分类path")
private String categoryPath;
@ApiModelProperty(value = "商品名称", required = true)
@NotEmpty(message = "商品名称不能为空")
private String goodsName;
@ApiModelProperty(value = "详情")
private String intro;
@ApiModelProperty(value = "商品移动端详情")
private String mobileIntro;
@ApiModelProperty(value = "库存")
@Min(value = 0, message = "库存不能为负数")
@Max(value = 99999999, message = "库存不能超过99999999")
private Integer quantity;
@ApiModelProperty(value = "是否立即发布")
private Boolean release;
@ApiModelProperty(value = "是否是推荐商品")
private Boolean recommend;
@ApiModelProperty(value = "商品图片")
private List<JSONObject> goodsGalleryFiles;
@ApiModelProperty(value = "卖点")
private String sellingPoint;
@ApiModelProperty(value = "是否有规格", hidden = true)
private String haveSpec;
@ApiModelProperty(value = "商品描述")
private String info;
@ApiModelProperty(value = "是否重新生成sku数据")
private Boolean regeneratorSkuFlag = true;
@ApiModelProperty(value = "商品类型")
private String goodsType;
/**
* 商品视频
*/
@ApiModelProperty(value = "商品视频")
private String goodsVideo;
@ApiModelProperty(value = "sku列表")
@Valid
private List<NutMap> skuList;
@ApiModelProperty(value = "是否为商品模版")
private Boolean goodsTemplateFlag = false;
@ApiModelProperty(value = "注意事项")
private String needingAttention;
@ApiModelProperty(value = "浏览权限")
private String browsePermissions;
public String getGoodsName() {
return goodsName.replace(",", "");
}
}
@@ -0,0 +1,54 @@
package com.budwk.app.zhgh.mall.models.entity.goods;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.math.BigDecimal;
/**
* @version 1.0
* @Author zzr
* @nameMallCategory
* @Date 2025/7/15 15:59
* @注释
*/
@Data
@Table
@EqualsAndHashCode(callSuper = true)
public class MallCategory extends BaseModel {
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("分类名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String name;
@Column
@Comment("父id, 根节点为0")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String parentId;
@Column
@Comment("层级, 从0开始")
@ColDefine(type = ColType.INT)
private Integer level;
@Column
@Comment("排序值")
@ColDefine(type = ColType.INT)
private Integer sortOrder;
@Column
@Comment("分类图标")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String image;
}
@@ -0,0 +1,196 @@
package com.budwk.app.zhgh.mall.models.entity.goods;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.http.HtmlUtil;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.model.BaseModel;
import com.budwk.app.zhgh.mall.models.dto.goods.MallGoodsOperationDTO;
import com.budwk.app.zhgh.mall.models.enums.GoodsStatusEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.eclipse.jetty.util.StringUtil;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.Map;
/**
* @version 1.0
* @Author zzr
* @nameMallGoods
* @Date 2025/7/15 15:17
* @注释 商城商品
*/
@Data
@Table
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class MallGoods extends BaseModel {
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("商品名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String goodsName;
@Column
@Comment("商品价格")
@ColDefine(type = ColType.DOUBLE)
private Double price;
@Column
@Comment("分类path")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String categoryPath;
@Column
@Comment("计量单位")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String goodsUnit;
@Column
@Comment("卖点")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String sellingPoint;
@Column
@Comment("上架状态")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String marketEnable;
@Column
@Comment("pc端详情")
@ColDefine(type = ColType.TEXT)
private String intro;
@Column
@Comment("购买数量")
@ColDefine(type = ColType.INT)
private Integer buyCount;
@Column
@Comment("库存")
@ColDefine(type = ColType.INT)
private Integer quantity;
@Column
@Comment("商品好评率")
@ColDefine(type = ColType.DOUBLE)
private Double grade;
@Column
@Comment("缩略图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String thumbnail;
@Column
@Comment("小图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String small;
@Column
@Comment("原图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String original;
@Column
@Comment("评论数量")
@ColDefine(type = ColType.INT)
private Integer commentNum;
@Column
@Comment("运费模板id")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String templateId;
@Column
@Comment("是否自营")
@ColDefine(type = ColType.BOOLEAN)
private Boolean selfOperated;
@Column
@Comment("商品移动端详情")
@ColDefine(type = ColType.TEXT)
private String mobileIntro;
@Column
@Comment("商品视频")
@ColDefine(type = ColType.VARCHAR)
private String goodsVideo;
@Column
@Comment("是否为推荐商品")
@ColDefine(type = ColType.BOOLEAN)
private Boolean recommend;
@Column
@Comment("商品类型")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String goodsType;
@Column
@Comment("商品参数json")
@ColDefine(type = ColType.MYSQL_JSON)
private String params;
public MallGoods(MallGoodsOperationDTO goodsOperationDTO) {
this.goodsName = goodsOperationDTO.getGoodsName();
this.categoryPath = goodsOperationDTO.getCategoryPath();
this.recommend = goodsOperationDTO.getRecommend();
this.sellingPoint = goodsOperationDTO.getSellingPoint();
this.intro = goodsOperationDTO.getIntro();
this.mobileIntro = goodsOperationDTO.getMobileIntro();
this.goodsVideo = goodsOperationDTO.getGoodsVideo();
this.price = goodsOperationDTO.getPrice();
//如果立即上架则
this.marketEnable = Boolean.TRUE.equals(goodsOperationDTO.getRelease()) ? GoodsStatusEnum.UPPER.name() : GoodsStatusEnum.DOWN.name();
this.goodsType = goodsOperationDTO.getGoodsType();
this.grade = 100D;
//循环sku,判定sku是否有效
for (Map<String, Object> sku : goodsOperationDTO.getSkuList()) {
//判定参数不能为空
if ((!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0)) {
throw new BaseException("商品SKU价格不能小于等于0");
}
// if ((!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0)) {
// throw new BaseException("商品SKU成本价不能小于等于0");
// }
if (!sku.containsKey("quantity") || StringUtil.isEmpty(sku.get("quantity").toString()) || Convert.toInt(sku.get("quantity").toString()) < 0) {
throw new BaseException("商品库存数量不能为负数");
}
sku.values().forEach(i -> {
if (CharSequenceUtil.isBlank(i.toString())) {
throw new BaseException("规格值不能为空!");
}
});
}
}
public String getIntro() {
if (CharSequenceUtil.isNotEmpty(intro)) {
return HtmlUtil.unescape(intro);
}
return intro;
}
public String getMobileIntro() {
if (CharSequenceUtil.isNotEmpty(mobileIntro)) {
return HtmlUtil.unescape(mobileIntro);
}
return mobileIntro;
}
}
@@ -0,0 +1,210 @@
package com.budwk.app.zhgh.mall.models.entity.goods;
import com.budwk.app.base.model.BaseModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsSku
* @Date 2025/7/15 17:33
* @注释 商品sku(库存)
*/
@Data
@Table
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class MallGoodsSku extends BaseModel {
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("商品id")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String goodsId;
@Column
@Comment("规格信息json")
@ColDefine(type = ColType.MYSQL_JSON)
private String specs;
@Column
@Comment("规格信息")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String simpleSpecs;
@Column
@Comment("配送模版id")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String freightTemplateId;
@Column
@Comment("商品名称")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String goodsName;
@Column
@Comment("商品编号")
@ColDefine(type = ColType.VARCHAR, width = 30)
private String sn;
@Column
@Comment("分类path")
@ColDefine(type = ColType.TEXT)
private String categoryPath;
@Column
@Comment("计量单位")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String goodsUnit;
@Column
@Comment("卖点")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String sellingPoint;
@Column
@Comment("重量")
@ColDefine(type = ColType.DOUBLE)
private Double weight;
@Column
@Comment("上架状态")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String marketEnable;
@Column
@Comment("商品详情")
@ColDefine(type = ColType.TEXT)
private String intro;
@Column
@Comment("商品价格")
@ColDefine(type = ColType.DOUBLE)
private Double price;
@Column
@Comment("商品价格")
@ColDefine(type = ColType.INT)
private Integer viewCount;
@Column
@Comment("购买数量")
@ColDefine(type = ColType.INT)
private Integer buyCount;
@Column
@Comment("库存")
@ColDefine(type = ColType.INT)
private Integer quantity;
@Column
@Comment("商品好评率")
@ColDefine(type = ColType.DOUBLE)
private Double grade;
@Column
@Comment("缩略图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String thumbnail;
@Column
@Comment("大图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String big;
@Column
@Comment("小图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String small;
@Column
@Comment("原图路径")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String original;
@Column
@Comment("评论数量")
@ColDefine(type = ColType.INT)
private Integer commentNum;
@Column
@Comment("运费模板id")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String templateId;
@Column
@Comment("商品移动端详情")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String mobileIntro;
@Column
@Comment("商品视频")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String goodsVideo;
@Column
@Comment("是否为推荐商品")
@ColDefine(type = ColType.BOOLEAN)
private Boolean recommend;
@Column
@Comment("商品类型")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String goodsType;
@ApiModelProperty(value = "预警数量")
@Column
@Comment("预警数量")
@ColDefine(type = ColType.INT)
private Integer alertQuantity;
public Double getWeight() {
if (weight == null) {
return 0d;
}
return weight;
}
public Integer getAlertQuantity() {
if(alertQuantity == null){
return 0;
}
return alertQuantity;
}
/**
* 设置规格商品的基本商品信息
*
* @param goods 基本商品信息
*/
public MallGoodsSku(MallGoods goods) {
//商品基本信息
this.goodsId = goods.getId();
this.goodsName = goods.getGoodsName();
this.goodsType = goods.getGoodsType();
this.goodsVideo = goods.getGoodsVideo();
this.sellingPoint = goods.getSellingPoint();
this.categoryPath = goods.getCategoryPath();
this.marketEnable = goods.getMarketEnable();
this.intro = goods.getIntro();
this.mobileIntro = goods.getMobileIntro();
this.goodsUnit = goods.getGoodsUnit();
this.grade = 100D;
this.alertQuantity = 0;
this.freightTemplateId = goods.getTemplateId();
this.recommend = goods.getRecommend();
}
}
@@ -0,0 +1,28 @@
package com.budwk.app.zhgh.mall.models.enums;
/**
* 商品类型枚举
*
* @author pikachu
* @since 2020-02-26 23:24:13
*/
public enum GoodsStatusEnum {
/**
* 上架
*/
UPPER("上架"),
/**
* 下架
*/
DOWN("下架");
private final String description;
GoodsStatusEnum(String description) {
this.description = description;
}
public String description() {
return description;
}
}
@@ -0,0 +1,32 @@
package com.budwk.app.zhgh.mall.models.enums;
/**
* 库存操作类型
*/
public enum GoodsStockTypeEnum {
SUB(""),
ADD("");
private final String description;
GoodsStockTypeEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
// 根据描述获取枚举实例
public static GoodsStockTypeEnum fromDescription(String description) {
for (GoodsStockTypeEnum type : GoodsStockTypeEnum.values()) {
if (type.getDescription().equals(description)) {
return type;
}
}
throw new IllegalArgumentException("No matching enum constant for description: " + description);
}
}
@@ -0,0 +1,69 @@
package com.budwk.app.zhgh.mall.models.vo.goods;
import cn.hutool.core.bean.BeanUtil;
import com.budwk.app.zhgh.mall.models.entity.goods.MallCategory;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Comparator;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallCategoryVO
* @Date 2025/7/16 10:56
* @注释 分类VO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MallCategoryVO {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "分类名称")
private String name;
@ApiModelProperty(value = "父id, 根节点为0")
private String parentId;
@ApiModelProperty(value = "层级, 从0开始")
private Integer level;
@ApiModelProperty(value = "排序值")
private Integer sortOrder;
@ApiModelProperty(value = "图片名称")
private String image;
@ApiModelProperty(value = "父节点名称")
private String parentTitle;
@ApiModelProperty("子分类列表")
private List<MallCategoryVO> children;
@ApiModelProperty("删除标识")
private Boolean delFlag;
public MallCategoryVO(MallCategory category) {
BeanUtil.copyProperties(category, this);
}
public List<MallCategoryVO> getChildren() {
if (children != null) {
children.sort(new Comparator<MallCategoryVO>() {
@Override
public int compare(MallCategoryVO o1, MallCategoryVO o2) {
return o1.getSortOrder().compareTo(o2.getSortOrder());
}
});
return children;
}
return null;
}
}
@@ -0,0 +1,91 @@
package com.budwk.app.zhgh.mall.models.vo.goods;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoodsSku;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsVO
* @Date 2025/7/17 16:31
* @注释
*/
@Data
public class MallGoodsVO {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "商品名称")
private String goodsName;
@ApiModelProperty(value = "商品价格")
private Double price;
@ApiModelProperty(value = "分类path")
private String categoryPath;
@ApiModelProperty(value = "计量单位")
private String goodsUnit;
@ApiModelProperty(value = "卖点")
private String sellingPoint;
@ApiModelProperty(value = "上架状态")
private String marketEnable;
@ApiModelProperty(value = "pc端详情")
private String intro;
@ApiModelProperty(value = "购买数量")
private Integer buyCount;
@ApiModelProperty(value = "库存")
private Integer quantity;
@ApiModelProperty(value = "商品好评率")
private Double grade;
@ApiModelProperty(value = "缩略图路径")
private String thumbnail;
@ApiModelProperty(value = "小图路径")
private String small;
@ApiModelProperty(value = "原图路径")
private String original;
@ApiModelProperty(value = "评论数量")
private Integer commentNum;
@ApiModelProperty(value = "运费模板id")
private String templateId;
@ApiModelProperty(value = "是否自营")
private Boolean selfOperated;
@ApiModelProperty(value = "商品移动端详情")
private String mobileIntro;
@ApiModelProperty(value = "商品视频")
private String goodsVideo;
@ApiModelProperty(value = "是否为推荐商品")
private Boolean recommend;
@ApiModelProperty(value = "商品类型")
private String goodsType;
@ApiModelProperty(value = "商品参数json")
private String params;
@ApiModelProperty(value = "分类名称")
private List<String> categoryName;
@ApiModelProperty(value = "sku列表")
private List<MallGoodsSku> skuList;
}
@@ -0,0 +1,38 @@
package com.budwk.app.zhgh.mall.param.goods;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* @version 1.0
* @Author zzr
* @nameMallCategorySearchParams
* @Date 2025/7/16 10:45
* @注释
*/
@Data
public class MallCategorySearchParams {
@ApiModelProperty(value = "分类名称")
private String name;
@ApiModelProperty(value = "父id")
private String parentId;
@ApiModelProperty(value = "层级")
private Integer level;
@ApiModelProperty(value = "排序值")
private BigDecimal sortOrder;
@ApiModelProperty(value = "佣金比例")
private BigDecimal commissionRate;
@ApiModelProperty(value = "父节点名称")
private String parentTitle;
@ApiModelProperty(value = "是否禁用")
private Boolean deleteFlag;
}
@@ -0,0 +1,25 @@
package com.budwk.app.zhgh.mall.service.goods;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.mall.models.entity.goods.MallCategory;
import com.budwk.app.zhgh.mall.param.goods.MallCategorySearchParams;
import com.budwk.app.zhgh.mall.models.vo.goods.MallCategoryVO;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallCategoryService
* @Date 2025/7/16 9:42
* @注释
*/
public interface MallCategoryService extends BaseService<MallCategory> {
void saveCategory(MallCategory category);
List<MallCategoryVO> listCategory(MallCategorySearchParams categorySearchParams);
void updateCategoryStatus(String id, Boolean enableOperations);
}
@@ -0,0 +1,46 @@
package com.budwk.app.zhgh.mall.service.goods;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.mall.models.dto.goods.MallGoodsOperationDTO;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoods;
import com.budwk.app.zhgh.mall.models.vo.goods.MallGoodsVO;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsService
* @Date 2025/7/16 17:03
* @注释
*/
public interface MallGoodsService extends BaseService<MallGoods> {
/**
* 添加商品
*
* @param goodsOperationDTO 商品查询条件
*/
void addGoods(MallGoodsOperationDTO goodsOperationDTO);
/**
* 修改商品
*
* @param goodsOperationDTO 商品查询条件
* @param goodsId 商品ID
*/
void editGoods(MallGoodsOperationDTO goodsOperationDTO, String goodsId);
/**
* 修改商品库存数量
*
* @param goodsId 商品ID
*/
void updateStock(String goodsId);
/**
* 查询商品VO
*
* @param goodsId 商品id
* @return 商品VO
*/
MallGoodsVO getGoodsVO(String goodsId);
}
@@ -0,0 +1,79 @@
package com.budwk.app.zhgh.mall.service.goods;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.mall.models.dto.goods.MallGoodsOperationDTO;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoods;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoodsSku;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameGoodsSkuService
* @Date 2025/7/16 18:05
* @注释
*/
public interface MallGoodsSkuService extends BaseService<MallGoodsSku> {
/**
* 添加商品sku
*
* @param goods 商品信息
* @param goodsOperationDTO 商品操作信息
*/
void add(MallGoods goods, MallGoodsOperationDTO goodsOperationDTO);
/**
* 更新商品sku
*
* @param goods 商品信息
* @param goodsOperationDTO 商品操作信息
*/
void update(MallGoods goods, MallGoodsOperationDTO goodsOperationDTO);
/**
* 获取最新商品库存
*
* @param goodsId 商品ID
* @return 库存数量
*/
Integer getGoodsStock(String goodsId);
/**
* 修改商品库存字段
*
* @param goodsSkus
*/
void updateGoodsStock(List<MallGoodsSku> goodsSkus);
/**
* 更新SKU库存
*
* @param skuId SKUId
* @param quantity 设置的库存数量
*/
void updateStock(String skuId, Integer quantity);
void updateStock(String skuId, Integer quantity,String type);
/**
* 批量渲染商品sku
*
* @param goodsSkuList SKU基础数据列表
* @param goodsOperationDTO 商品操作信息
*/
void renderGoodsSkuList(List<MallGoodsSku> goodsSkuList, MallGoodsOperationDTO goodsOperationDTO);
/**
* 获取goodsId下所有的goodsSku
*
* @param goodsId 商品id
* @return goodsSku列表
*/
List<MallGoodsSku> getGoodsListByGoodsId(String goodsId);
}
@@ -0,0 +1,129 @@
package com.budwk.app.zhgh.mall.service.impl.goods;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.mall.models.entity.goods.MallCategory;
import com.budwk.app.zhgh.mall.param.goods.MallCategorySearchParams;
import com.budwk.app.zhgh.mall.service.goods.MallCategoryService;
import com.budwk.app.zhgh.mall.models.vo.goods.MallCategoryVO;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallCategoryServiceImpl
* @Date 2025/7/16 10:27
* @注释
*/
@IocBean(args = {"refer:dao"})
public class MallCategoryServiceImpl extends BaseServiceImpl<MallCategory> implements MallCategoryService {
public MallCategoryServiceImpl(Dao dao) {
super(dao);
}
@Override
public void saveCategory(MallCategory category) {
if (category.getParentId() != null && !("0").equals(category.getParentId())) {
MallCategory parentCategory = dao().fetch(MallCategory.class, Cnd.where("id", "=", category.getParentId()));
category.setDelFlag(parentCategory.getDelFlag());
}
dao().insert(category);
}
@Override
public List<MallCategoryVO> listCategory(MallCategorySearchParams categorySearchParams) {
// 获取全部分类
List<MallCategory> list = dao().query(MallCategory.class, Cnd.where(MallCategory::getDelFlag, "=", false));
// 构造分类树
List<MallCategoryVO> categoryVOList = new ArrayList<>();
for (MallCategory category : list) {
if (("0").equals(category.getParentId())) {
MallCategoryVO categoryVO = new MallCategoryVO(category);
categoryVO.setChildren(findChildren(list, categoryVO));
categoryVOList.add(categoryVO);
}
}
categoryVOList.sort(Comparator.comparing(MallCategoryVO::getSortOrder));
return categoryVOList;
}
@Override
public void updateCategoryStatus(String id, Boolean enableOperations) {
//禁用子分类
MallCategoryVO categoryVO = new MallCategoryVO(dao().fetch(MallCategory.class, Cnd.where(MallCategory::getId, "=", id)));
List<String> ids = new ArrayList<>();
ids.add(categoryVO.getId());
this.findAllChild(categoryVO);
this.findAllChildIds(categoryVO, ids);
dao().update(MallCategory.class, Chain.make("delFlag", enableOperations), Cnd.where(MallCategory::getId, "in", ids));
}
/**
* 递归树形VO
*
* @param categories 分类列表
* @param categoryVO 分类VO
* @return 分类VO列表
*/
private List<MallCategoryVO> findChildren(List<MallCategory> categories, MallCategoryVO categoryVO) {
List<MallCategoryVO> children = new ArrayList<>();
categories.forEach(item -> {
if (item.getParentId().equals(categoryVO.getId())) {
MallCategoryVO temp = new MallCategoryVO(item);
temp.setChildren(findChildren(categories, temp));
children.add(temp);
}
});
return children;
}
/**
* 条件查询分类
*
* @param category 分类VO
*/
private void findAllChild(MallCategoryVO category) {
List<MallCategory> categories = dao().query(MallCategory.class, Cnd.where("parentId", "=", category.getId()));
List<MallCategoryVO> categoryVOList = new ArrayList<>();
for (MallCategory category1 : categories) {
categoryVOList.add(new MallCategoryVO(category1));
}
category.setChildren(categoryVOList);
if (!categoryVOList.isEmpty()) {
categoryVOList.forEach(this::findAllChild);
}
}
/**
* 获取所有的子分类ID
*
* @param category 分类
* @param ids ID列表
*/
private void findAllChildIds(MallCategoryVO category, List<String> ids) {
if (category.getChildren() != null && !category.getChildren().isEmpty()) {
for (MallCategoryVO child : category.getChildren()) {
ids.add(child.getId());
this.findAllChildIds(child, ids);
}
}
}
}
@@ -0,0 +1,144 @@
package com.budwk.app.zhgh.mall.service.impl.goods;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.mall.models.dto.goods.MallGoodsOperationDTO;
import com.budwk.app.zhgh.mall.models.entity.goods.MallCategory;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoods;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoodsSku;
import com.budwk.app.zhgh.mall.models.vo.goods.MallGoodsVO;
import com.budwk.app.zhgh.mall.service.goods.MallCategoryService;
import com.budwk.app.zhgh.mall.service.goods.MallGoodsService;
import com.budwk.app.zhgh.mall.service.goods.MallGoodsSkuService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsServiceImpl
* @Date 2025/7/16 17:04
* @注释
*/
@Slf4j
@IocBean(args = {"refer:dao"})
public class MallGoodsServiceImpl extends BaseServiceImpl<MallGoods> implements MallGoodsService {
public MallGoodsServiceImpl(Dao dao) {
super(dao);
}
@Inject
private MallCategoryService categoryService;
@Inject
private MallGoodsSkuService goodsSkuService;
@Override
public void addGoods(MallGoodsOperationDTO goodsOperationDTO) {
MallGoods goods = new MallGoods(goodsOperationDTO);
// 判断商品信息
this.checkGoods(goods);
dao().insert(goods);
//添加商品sku信息
goodsSkuService.add(goods, goodsOperationDTO);
}
@Override
public void editGoods(MallGoodsOperationDTO goodsOperationDTO, String goodsId) {
MallGoods goods = new MallGoods(goodsOperationDTO);
goods.setId(goodsId);
//检查商品信息
this.checkGoods(goods);
//修改商品
dao().update(goods);
//修改商品sku信息
this.goodsSkuService.update(goods, goodsOperationDTO);
}
@Override
public void updateStock(String goodsId) {
Integer stock = goodsSkuService.getGoodsStock(goodsId);
dao().update(MallGoods.class, Chain.make("quantity", stock), Cnd.where("id", "=", goodsId));
}
@Override
public MallGoodsVO getGoodsVO(String goodsId) {
//查询商品信息
MallGoods goods = dao().fetch(MallGoods.class ,goodsId);
if (goods == null) {
log.error("商品ID为{}的商品不存在", goodsId);
throw new BaseException("商品不存在");
}
MallGoodsVO goodsVO = new MallGoodsVO();
//赋值
BeanUtils.copyProperties(goods, goodsVO);
//商品id
goodsVO.setId(goods.getId());
//商品sku赋值
List<MallGoodsSku> goodsListByGoodsId = goodsSkuService.getGoodsListByGoodsId(goodsId);
if (goodsListByGoodsId != null && !goodsListByGoodsId.isEmpty()) {
goodsVO.setSkuList(goodsListByGoodsId);
}
//商品分类名称赋值
List<String> categoryName = new ArrayList<>();
String categoryPath = goods.getCategoryPath();
String[] strArray = categoryPath.split(",");
List<MallCategory> categories = categoryService.dao().query(MallCategory.class, Cnd.where("id", "in", Arrays.asList(strArray)));
for (MallCategory category : categories) {
categoryName.add(category.getName());
}
goodsVO.setCategoryName(categoryName);
return goodsVO;
}
/**
* 检查商品
* @param goods 商品
*/
public void checkGoods(MallGoods goods){
// 判断是通过草稿加的还是手动新增
if (goods.getId() != null) {
// 如果有Id就去判断库里面有没有
MallGoods sourceGoods = dao().fetch(MallGoods.class, Cnd.where("id", "=", goods.getId()));
if (sourceGoods == null) {
log.error("商品ID为{}的商品不存在", goods.getId());
throw new BaseException("商品不存在");
}
} else {
//评论次数
goods.setCommentNum(0);
//购买次数
goods.setBuyCount(0);
//购买次数
goods.setQuantity(0);
//商品评分
goods.setGrade(100.0);
}
}
/**
* 添加商品默认图片
*
* @param origin 图片
* @param goods 商品
*/
private void setGoodsGalleryParam(String origin, MallGoods goods) {
goods.setOriginal(origin);
goods.setSmall(origin);
goods.setThumbnail(origin);
}
}
@@ -0,0 +1,284 @@
package com.budwk.app.zhgh.mall.service.impl.goods;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.mall.models.dto.goods.MallGoodsOperationDTO;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoods;
import com.budwk.app.zhgh.mall.models.entity.goods.MallGoodsSku;
import com.budwk.app.zhgh.mall.models.enums.GoodsStockTypeEnum;
import com.budwk.app.zhgh.mall.service.goods.MallGoodsService;
import com.budwk.app.zhgh.mall.service.goods.MallGoodsSkuService;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import java.util.*;
import java.util.stream.Collectors;
/**
* @version 1.0
* @Author zzr
* @nameMallGoodsSkuServiceImpl
* @Date 2025/7/16 18:05
* @注释
*/
@IocBean(args = {"refer:dao"})
public class MallGoodsSkuServiceImpl extends BaseServiceImpl<MallGoodsSku> implements MallGoodsSkuService {
public MallGoodsSkuServiceImpl(Dao dao) {
super(dao);
}
@Inject
private MallGoodsService goodsService;
@Override
public void add(MallGoods goods, MallGoodsOperationDTO goodsOperationDTO) {
// 是否存在规格
if (Lang.isEmpty(goodsOperationDTO.getSkuList())) {
throw new BaseException("规格必须填写!");
}
// 检查是否需要生成索引
List<MallGoodsSku> goodsSkus = buildBatch(goods, goodsOperationDTO.getSkuList());
renderGoodsSkuList(goodsSkus, goodsOperationDTO);
if (!goodsSkus.isEmpty()) {
dao().insertOrUpdate(goodsSkus);
this.updateGoodsStock(goodsSkus);
}
}
@Override
public void update(MallGoods goods, MallGoodsOperationDTO goodsOperationDTO) {
// 是否存在规格
if (Lang.isEmpty(goodsOperationDTO.getSkuList())) {
throw new BaseException("规格必须填写!");
}
List<MallGoodsSku> skuList = new ArrayList<>();
// 去遍历新的sku
for (Map<String, Object> skuInfo : goodsOperationDTO.getSkuList()) {
MallGoodsSku sku = new MallGoodsSku(goods);
builderSingle(sku, skuInfo);
renderGoodsSku(sku, goodsOperationDTO);
skuList.add(sku);
}
if (Lang.isNotEmpty(skuList)) {
Cnd cnd = Cnd.NEW();
cnd.and(MallGoodsSku::getGoodsId, "=", goods.getId());
List<String> ids = skuList.stream().map(MallGoodsSku::getId).filter(StrUtil::isNotBlank).toList();
if (Lang.isNotEmpty(ids)) {
cnd.and(MallGoodsSku::getId, "not in", ids);
}
// 删除旧sku
dao().clear(MallGoodsSku.class, cnd);
// 修改或新增sku
dao().insertOrUpdate(skuList);
// 请计算库存
updateGoodsStock(skuList);
}
}
@Override
public Integer getGoodsStock(String goodsId) {
Sql sql = Sqls.create("select id,quantity from mall_goods_sku where goodsId = @id").setParam("id", goodsId);
sql.setCallback(Sqls.callback.maps());
dao().execute(sql);
List<NutMap> skuInfos = (List<NutMap>) sql.getResult();
int stock = 0;
for (NutMap map : skuInfos) {
stock += map.getInt("quantity");
}
return stock;
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void updateGoodsStock(List<MallGoodsSku> goodsSkus) {
Map<String, List<MallGoodsSku>> groupByGoodsIds = goodsSkus.stream().collect(Collectors.groupingBy(MallGoodsSku::getGoodsId));
//统计每个商品的库存
for (String goodsId : groupByGoodsIds.keySet()) {
//库存
Integer quantity = 0;
for (MallGoodsSku goodsSku : goodsSkus) {
if (goodsId.equals(goodsSku.getGoodsId())) {
quantity += goodsSku.getQuantity();
}
this.updateStock(goodsSku.getId(), goodsSku.getQuantity());
}
//保存商品库存结果
goodsService.updateStock(goodsId);
}
}
@Override
public void updateStock(String skuId, Integer quantity) {
MallGoodsSku goodsSku = dao().fetch(MallGoodsSku.class, skuId);
if (Lang.isNotEmpty(goodsSku)) {
goodsSku.setQuantity(quantity);
dao().update(MallGoodsSku.class, Chain.make("quantity", quantity), Cnd.where(MallGoodsSku::getId, "=", skuId));
}
}
@Override
public void updateStock(String skuId, Integer quantity, String type) {
MallGoodsSku goodsSku = dao().fetch(MallGoodsSku.class, skuId);
if (Lang.isNotEmpty(goodsSku)) {
//计算修改库存
if (type.equals(GoodsStockTypeEnum.ADD.name())) {
quantity = Convert.toInt(NumberUtil.add(goodsSku.getQuantity(), quantity));
} else {
quantity = Convert.toInt(NumberUtil.sub(goodsSku.getQuantity(), quantity));
}
goodsSku.setQuantity(quantity);
dao().update(MallGoodsSku.class, Chain.make("quantity", quantity), Cnd.where(MallGoodsSku::getId, "=", skuId));
}
}
/**
* 批量渲染商品sku
*
* @param goodsSkuList sku集合
* @param goodsOperationDTO 商品操作DTO
*/
@Override
public void renderGoodsSkuList(List<MallGoodsSku> goodsSkuList, MallGoodsOperationDTO goodsOperationDTO) {
// 商品销售模式渲染器
for (MallGoodsSku goodsSku : goodsSkuList) {
renderGoodsSku(goodsSku, goodsOperationDTO);
}
}
@Override
public List<MallGoodsSku> getGoodsListByGoodsId(String goodsId) {
return dao().query(MallGoodsSku.class, Cnd.where("goodsId", "=", goodsId));
}
/**
* 渲染商品sku
*
* @param goodsSku sku
* @param goodsOperationDTO 商品操作DTO
*/
void renderGoodsSku(MallGoodsSku goodsSku, MallGoodsOperationDTO goodsOperationDTO) {
extendOldSkuValue(goodsSku);
List<JSONObject> goodsImages = goodsOperationDTO.getGoodsGalleryFiles();
if (goodsImages == null || goodsImages.isEmpty()) {
return;
}
JSONObject jsonObject = JSONUtil.parseObj(goodsSku.getSpecs());
List<String> images = jsonObject.getBeanList("images", String.class);
String imageUrl = "";
if (Lang.isNotEmpty(images)) {
imageUrl = images.get(0);
} else {
imageUrl = goodsImages.get(0).getStr("url");
}
goodsSku.setBig(imageUrl);
goodsSku.setOriginal(imageUrl);
goodsSku.setThumbnail(imageUrl);
goodsSku.setSmall(imageUrl);
}
/**
* 将原sku的一些不会直接传递的值放到新的sku中
*
* @param goodsSku 商品sku
*/
private void extendOldSkuValue(MallGoodsSku goodsSku) {
if (StrUtil.isNotBlank(goodsSku.getGoodsId())) {
MallGoodsSku oldSku = dao().fetch(MallGoodsSku.class, Cnd.where(MallGoodsSku::getId, "=", goodsSku.getId()));
if (Lang.isNotEmpty(oldSku)) {
goodsSku.setCommentNum(oldSku.getCommentNum());
goodsSku.setViewCount(oldSku.getViewCount());
goodsSku.setBuyCount(oldSku.getBuyCount());
goodsSku.setGrade(oldSku.getGrade());
}
}
}
/**
* 批量构建商品sku
*
* @param goods 商品
* @return 商品sku
*/
public List<MallGoodsSku> buildBatch(MallGoods goods, List<NutMap> skuList) {
Assert.notEmpty(skuList, "skuList不能为空");
Assert.notNull(goods, "goods不能为空");
List<MallGoodsSku> goodsSkus = new ArrayList<>();
for (Map<String, Object> skuInfo : skuList) {
MallGoodsSku goodsSku = new MallGoodsSku(goods);
builderSingle(goodsSku, skuInfo);
goodsSkus.add(goodsSku);
}
return goodsSkus;
}
private static void builderSingle(MallGoodsSku goodsSku, Map<String, Object> skuInfo) {
Assert.notNull(goodsSku, "goodsSku不能为空");
Assert.notEmpty(skuInfo, "skuInfo不能为空");
//规格简短信息
StringBuilder simpleSpecs = new StringBuilder();
//商品名称
StringBuilder goodsName = new StringBuilder(goodsSku.getGoodsName());
//规格值
Map<String, Object> specMap = new LinkedHashMap<>();
// 原始规格项
String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight", "alertQuantity"};
//获取规格信息
for (Map.Entry<String, Object> spec : skuInfo.entrySet()) {
//保存新增规格信息
if (!CollUtil.contains(Arrays.asList(ignoreOriginKeys), spec.getKey()) && spec.getValue() != null) {
specMap.put(spec.getKey(), spec.getValue());
if (!"images".equals(spec.getKey())) {
//设置商品名称
goodsName.append(" ").append(spec.getValue());
//规格简短信息
simpleSpecs.append(" ").append(spec.getValue());
}
}
}
//设置规格信息
goodsSku.setGoodsName(goodsName.toString());
//规格信息
goodsSku.setId(Convert.toStr(skuInfo.get("id"), ""));
goodsSku.setSn(Convert.toStr(skuInfo.get("sn")));
goodsSku.setWeight(Convert.toDouble(skuInfo.get("weight"), 0D));
goodsSku.setPrice(Convert.toDouble(skuInfo.get("price"), 0D));
goodsSku.setQuantity(Convert.toInt(skuInfo.get("quantity"), 0));
goodsSku.setSpecs(JSONUtil.toJsonStr(specMap));
goodsSku.setSimpleSpecs(simpleSpecs.toString());
goodsSku.setAlertQuantity(Convert.toInt(skuInfo.get("alertQuantity"), 0));
}
}