diff --git a/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopCategoryController.java b/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopCategoryController.java new file mode 100644 index 0000000..47a1ee9 --- /dev/null +++ b/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopCategoryController.java @@ -0,0 +1,55 @@ +package com.agileboot.admin.controller.shop; + + +import com.agileboot.common.core.dto.ResponseDTO; +import com.agileboot.common.core.page.PageDTO; +import com.agileboot.domain.shop.category.CategoryApplicationService; +import com.agileboot.domain.shop.category.db.ShopCategoryEntity; +import com.agileboot.domain.shop.category.dto.ShopCategoryDTO; +import com.agileboot.domain.shop.category.query.SearchShopCategoryQuery; +import io.swagger.v3.oas.annotations.Operation; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; +import com.agileboot.common.core.base.BaseController; + +/** + *

+ * 商品分类表 前端控制器 + *

+ * + * @author valarchie + * @since 2025-03-04 + */ +@RestController +@RequestMapping("/shop/category") +@RequiredArgsConstructor +public class ShopCategoryController extends BaseController { + private final CategoryApplicationService categoryApplicationService; + + /** + * 获取分类列表 + */ + @Operation(summary = "商品分类列表") +// @PreAuthorize("@permission.has('shop:goods:list')") + @GetMapping("/list") + public ResponseDTO> categoryList(SearchShopCategoryQuery query) { + PageDTO page = categoryApplicationService.getCategoryList(query); + return ResponseDTO.ok(page); + } + + /** + * 获取全部分类 + */ + @Operation(summary = "商品全部分类") +// @PreAuthorize("@permission.has('shop:goods:list')") + @GetMapping("/all") + public ResponseDTO> categoryAll() { + List page = categoryApplicationService.getCategoryAll(); + return ResponseDTO.ok(page); + } +} + diff --git a/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopGoodsController.java b/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopGoodsController.java index 6906d97..b302885 100644 --- a/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopGoodsController.java +++ b/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopGoodsController.java @@ -1,19 +1,33 @@ package com.agileboot.admin.controller.shop; +import com.agileboot.admin.customize.aop.accessLog.AccessLog; import com.agileboot.common.core.dto.ResponseDTO; import com.agileboot.common.core.page.PageDTO; +import com.agileboot.common.enums.common.BusinessTypeEnum; +import com.agileboot.domain.common.command.BulkOperationCommand; import com.agileboot.domain.shop.goods.GoodsApplicationService; import com.agileboot.domain.shop.goods.db.SearchGoodsDO; import com.agileboot.domain.shop.goods.dto.ShopGoodsDTO; import com.agileboot.domain.shop.goods.query.SearchShopGoodsQuery; import io.swagger.v3.oas.annotations.Operation; +import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.agileboot.common.core.base.BaseController; +import com.agileboot.domain.shop.goods.command.AddGoodsCommand; +import com.agileboot.domain.shop.goods.command.UpdateGoodsCommand; +import javax.validation.constraints.NotNull; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; /** *

@@ -26,6 +40,7 @@ import com.agileboot.common.core.base.BaseController; @RestController @RequestMapping("/shop/goods") @RequiredArgsConstructor +@Validated public class ShopGoodsController extends BaseController { private final GoodsApplicationService goodsApplicationService; @@ -39,5 +54,34 @@ public class ShopGoodsController extends BaseController { PageDTO page = goodsApplicationService.getGoodsList(query); return ResponseDTO.ok(page); } + + @Operation(summary = "新增商品") +// @PreAuthorize("@permission.has('shop:goods:add')") + @AccessLog(title = "商品管理", businessType = BusinessTypeEnum.ADD) + @PostMapping + public ResponseDTO add(@Validated @RequestBody AddGoodsCommand command) { + goodsApplicationService.addGoods(command); + return ResponseDTO.ok(); + } + + @Operation(summary = "删除商品") +// @PreAuthorize("@permission.has('shop:goods:remove')") + @AccessLog(title = "商品管理", businessType = BusinessTypeEnum.DELETE) + @DeleteMapping("/{goodsIds}") + public ResponseDTO remove(@PathVariable @NotNull List goodsIds) { + BulkOperationCommand bulkDeleteCommand = new BulkOperationCommand<>(goodsIds); + goodsApplicationService.deleteGoods(bulkDeleteCommand); + return ResponseDTO.ok(); + } + + @Operation(summary = "修改商品") +// @PreAuthorize("@permission.has('shop:goods:edit')") + @AccessLog(title = "商品管理", businessType = BusinessTypeEnum.MODIFY) + @PutMapping("/{goodsId}") + public ResponseDTO edit(@PathVariable Long goodsId, @Validated @RequestBody UpdateGoodsCommand command) { + command.setGoodsId(goodsId); + goodsApplicationService.updateGoods(command); + return ResponseDTO.ok(); + } } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/CategoryApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/CategoryApplicationService.java new file mode 100644 index 0000000..d8d3bc2 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/CategoryApplicationService.java @@ -0,0 +1,34 @@ +package com.agileboot.domain.shop.category; + +import com.agileboot.common.core.page.PageDTO; +import com.agileboot.domain.shop.category.db.ShopCategoryEntity; +import com.agileboot.domain.shop.category.db.ShopCategoryService; +import com.agileboot.domain.shop.category.dto.ShopCategoryDTO; +import com.agileboot.domain.shop.category.query.SearchShopCategoryQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CategoryApplicationService { + private final ShopCategoryService shopCategoryService; + + public PageDTO getCategoryList(SearchShopCategoryQuery query) { + Page categoryPage = shopCategoryService.getCategoryList(query); + List dtoList = categoryPage.getRecords().stream() + .map(ShopCategoryDTO::new) + .collect(Collectors.toList()); + return new PageDTO<>(dtoList, categoryPage.getTotal()); + } + + + public List getCategoryAll() { + return shopCategoryService.getCategoryAll().stream() + .map(ShopCategoryDTO::new) + .collect(Collectors.toList()); + } + +} \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryEntity.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryEntity.java new file mode 100644 index 0000000..634ddc8 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryEntity.java @@ -0,0 +1,52 @@ +package com.agileboot.domain.shop.category.db; + +import com.agileboot.common.core.base.BaseEntity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 商品分类表 + *

+ * + * @author valarchie + * @since 2025-03-04 + */ +@Getter +@Setter +@TableName("shop_category") +@ApiModel(value = "ShopCategoryEntity对象", description = "商品分类表") +public class ShopCategoryEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("分类唯一ID") + @TableId(value = "category_id", type = IdType.AUTO) + private Long categoryId; + + @ApiModelProperty("分类名称") + @TableField("category_name") + private String categoryName; + + @ApiModelProperty("排序权重") + @TableField("sort") + private Integer sort; + + @ApiModelProperty("分类描述") + @TableField("description") + private String description; + + + @Override + public Serializable pkVal() { + return this.categoryId; + } + +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryMapper.java new file mode 100644 index 0000000..72fb150 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryMapper.java @@ -0,0 +1,43 @@ +package com.agileboot.domain.shop.category.db; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + *

+ * 商品分类表 Mapper 接口 + *

+ * + * @author valarchie + * @since 2025-03-04 + */ +public interface ShopCategoryMapper extends BaseMapper { + /** + * 根据条件分页查询分类列表 + * @param page 分页对象 + * @param queryWrapper 查询条件 + * @return 分类分页列表 + */ + @Select("SELECT category_id, category_name, sort, description " + + "FROM shop_category " + + "${ew.customSqlSegment}") + Page getCategoryList( + Page page, + @Param(Constants.WRAPPER) Wrapper queryWrapper + ); + + /** + * 查询所有分类(未删除的) + * @return 分类列表 + */ + @Select("SELECT * " + + "FROM shop_category " + + "WHERE deleted = 0 " + + "ORDER BY sort ASC") + List selectAll(); +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryService.java new file mode 100644 index 0000000..ae62118 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryService.java @@ -0,0 +1,20 @@ +package com.agileboot.domain.shop.category.db; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.agileboot.common.core.page.AbstractPageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.List; + +/** + *

+ * 商品分类表 服务类 + *

+ * + * @author valarchie + * @since 2025-03-04 + */ +public interface ShopCategoryService extends IService { + Page getCategoryList(AbstractPageQuery query); + + List getCategoryAll(); +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryServiceImpl.java new file mode 100644 index 0000000..f93ccdb --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/db/ShopCategoryServiceImpl.java @@ -0,0 +1,28 @@ +package com.agileboot.domain.shop.category.db; + +import com.agileboot.common.core.page.AbstractPageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; + +/** + *

+ * 商品分类表 服务实现类 + *

+ * + * @author valarchie + * @since 2025-03-04 + */ +@Service +public class ShopCategoryServiceImpl extends ServiceImpl implements ShopCategoryService { + @Override + public Page getCategoryList(AbstractPageQuery query) { + return baseMapper.selectPage(query.toPage(), query.toQueryWrapper()); + } + + @Override + public List getCategoryAll() { + return baseMapper.selectAll(); + } +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/dto/ShopCategoryDTO.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/dto/ShopCategoryDTO.java new file mode 100644 index 0000000..c7b0536 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/dto/ShopCategoryDTO.java @@ -0,0 +1,48 @@ +package com.agileboot.domain.shop.category.dto; + +import cn.hutool.core.bean.BeanUtil; +import com.agileboot.common.annotation.ExcelColumn; +import com.agileboot.common.annotation.ExcelSheet; +import com.agileboot.domain.shop.category.db.ShopCategoryEntity; +import java.util.Date; +import lombok.Data; + +@ExcelSheet(name = "商品分类列表") +@Data +public class ShopCategoryDTO { + + public ShopCategoryDTO(ShopCategoryEntity entity) { + if (entity != null) { + BeanUtil.copyProperties(entity, this); + + // 如果需要关联查询,可参考以下方式(根据实际需求启用) + /* + SysUserEntity creator = CacheCenter.userCache.getObjectById(entity.getCreatorId()); + if (creator != null) { + this.creatorName = creator.getUsername(); + } + */ + } + } + + @ExcelColumn(name = "分类ID") + private Long categoryId; + + @ExcelColumn(name = "分类名称") + private String categoryName; + + @ExcelColumn(name = "排序权重") + private Integer sort; + + @ExcelColumn(name = "分类描述") + private String description; + + @ExcelColumn(name = "创建者ID") + private Long creatorId; + + @ExcelColumn(name = "创建者") + private String creatorName; + + @ExcelColumn(name = "创建时间") + private Date createTime; +} \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/query/SearchShopCategoryQuery.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/query/SearchShopCategoryQuery.java new file mode 100644 index 0000000..2f925ff --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/category/query/SearchShopCategoryQuery.java @@ -0,0 +1,28 @@ +package com.agileboot.domain.shop.category.query; + +import cn.hutool.core.util.StrUtil; +import com.agileboot.common.core.page.AbstractPageQuery; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class SearchShopCategoryQuery extends AbstractPageQuery { + + protected String categoryName; + + @Override + public QueryWrapper addQueryCondition() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + + queryWrapper + .like(StrUtil.isNotEmpty(categoryName), "category_name", categoryName) + .eq("deleted", 0) + .orderByAsc("sort"); + + this.timeRangeColumn = "create_time"; + + return queryWrapper; + } +} \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/GoodsApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/GoodsApplicationService.java index b82e1d2..2d0501a 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/GoodsApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/GoodsApplicationService.java @@ -1,9 +1,14 @@ package com.agileboot.domain.shop.goods; import com.agileboot.common.core.page.PageDTO; +import com.agileboot.domain.common.command.BulkOperationCommand; +import com.agileboot.domain.shop.goods.command.AddGoodsCommand; +import com.agileboot.domain.shop.goods.command.UpdateGoodsCommand; import com.agileboot.domain.shop.goods.db.SearchGoodsDO; import com.agileboot.domain.shop.goods.db.ShopGoodsService; import com.agileboot.domain.shop.goods.dto.ShopGoodsDTO; +import com.agileboot.domain.shop.goods.model.GoodsModel; +import com.agileboot.domain.shop.goods.model.GoodsModelFactory; import com.agileboot.domain.shop.goods.query.SearchShopGoodsQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import java.util.List; @@ -15,10 +20,38 @@ import org.springframework.stereotype.Service; @RequiredArgsConstructor public class GoodsApplicationService { private final ShopGoodsService shopGoodsService; + private final GoodsModelFactory goodsModelFactory; public PageDTO getGoodsList(SearchShopGoodsQuery query) { Page goodsPage = shopGoodsService.getGoodsList(query); List goodsDTOList = goodsPage.getRecords().stream().map(ShopGoodsDTO::new).collect(Collectors.toList()); return new PageDTO<>(goodsDTOList, goodsPage.getTotal()); } + + public void addGoods(AddGoodsCommand command) { + GoodsModel model = goodsModelFactory.create(); + model.loadAddGoodsCommand(command); + +/* model.checkGoodsNameUnique(); + model.checkCategoryExist();*/ + + model.insert(); + } + + public void updateGoods(UpdateGoodsCommand command) { + GoodsModel model = goodsModelFactory.loadById(command.getGoodsId()); + model.loadUpdateGoodsCommand(command); + +/* model.checkGoodsNameUnique(); + model.checkCategoryExist();*/ + + model.updateById(); + } + + public void deleteGoods(BulkOperationCommand command) { + for (Long goodsId : command.getIds()) { + GoodsModel model = goodsModelFactory.loadById(goodsId); + model.deleteById(); + } + } } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/AddGoodsCommand.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/AddGoodsCommand.java new file mode 100644 index 0000000..5778dab --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/AddGoodsCommand.java @@ -0,0 +1,11 @@ +package com.agileboot.domain.shop.goods.command; + +import com.agileboot.domain.shop.goods.db.ShopGoodsEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class AddGoodsCommand extends ShopGoodsEntity { + +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/UpdateGoodsCommand.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/UpdateGoodsCommand.java new file mode 100644 index 0000000..dde4a71 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/UpdateGoodsCommand.java @@ -0,0 +1,10 @@ +package com.agileboot.domain.shop.goods.command; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class UpdateGoodsCommand extends AddGoodsCommand { + +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/SearchGoodsDO.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/SearchGoodsDO.java index 9539b03..3af909e 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/SearchGoodsDO.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/SearchGoodsDO.java @@ -7,4 +7,5 @@ import lombok.EqualsAndHashCode; @Data public class SearchGoodsDO extends ShopGoodsEntity { + private String categoryName; } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsMapper.java index 04401dc..7dba089 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsMapper.java @@ -23,9 +23,9 @@ public interface ShopGoodsMapper extends BaseMapper { * @return 商品分页列表 */ @Select("SELECT g.goods_id, g.goods_name, g.category_id, g.price, " + - "g.stock, g.status, g.cover_img " + + "g.stock, g.status, g.cover_img, c.category_name " + "FROM shop_goods g " + -// "LEFT JOIN shop_category c ON g.category_id = c.category_id " + + "LEFT JOIN shop_category c ON g.category_id = c.category_id " + "${ew.customSqlSegment}") Page getGoodsList( Page page, diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/impl/ShopGoodsServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsServiceImpl.java similarity index 69% rename from agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/impl/ShopGoodsServiceImpl.java rename to agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsServiceImpl.java index 8e4587b..346d294 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/impl/ShopGoodsServiceImpl.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/ShopGoodsServiceImpl.java @@ -1,13 +1,9 @@ -package com.agileboot.domain.shop.goods.db.impl; +package com.agileboot.domain.shop.goods.db; import com.agileboot.common.core.page.AbstractPageQuery; -import com.agileboot.domain.shop.goods.db.SearchGoodsDO; -import com.agileboot.domain.shop.goods.db.ShopGoodsService; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; -import com.agileboot.domain.shop.goods.db.ShopGoodsEntity; -import com.agileboot.domain.shop.goods.db.ShopGoodsMapper; /** *

diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/model/GoodsModel.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/model/GoodsModel.java new file mode 100644 index 0000000..30172b4 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/model/GoodsModel.java @@ -0,0 +1,71 @@ +package com.agileboot.domain.shop.goods.model; + +import cn.hutool.core.bean.BeanUtil; +import com.agileboot.common.config.AgileBootConfig; +import com.agileboot.common.exception.ApiException; +import com.agileboot.common.exception.error.ErrorCode; +import com.agileboot.domain.shop.category.db.ShopCategoryService; +import com.agileboot.domain.shop.goods.command.AddGoodsCommand; +import com.agileboot.domain.shop.goods.command.UpdateGoodsCommand; +import com.agileboot.domain.shop.goods.db.ShopGoodsEntity; +import com.agileboot.domain.shop.goods.db.ShopGoodsService; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class GoodsModel extends ShopGoodsEntity { + + private ShopGoodsService goodsService; + private ShopCategoryService categoryService; + + public GoodsModel(ShopGoodsEntity entity, ShopGoodsService goodsService, + ShopCategoryService categoryService) { + this(goodsService, categoryService); + if (entity != null) { + BeanUtil.copyProperties(entity, this); + } + } + + public GoodsModel(ShopGoodsService goodsService, ShopCategoryService categoryService) { + this.goodsService = goodsService; + this.categoryService = categoryService; + } + + public void loadAddGoodsCommand(AddGoodsCommand command) { + if (command != null) { + BeanUtil.copyProperties(command, this, "goodsId"); + } + } + + public void loadUpdateGoodsCommand(UpdateGoodsCommand command) { + if (command != null) { + loadAddGoodsCommand(command); + } + } + +/* public void checkGoodsNameUnique() { + if (goodsService.isGoodsNameDuplicated(getGoodsName(), getGoodsId())) { + throw new ApiException(ErrorCode.FAILED, "商品名称已存在"); + } + } + + public void checkCategoryExist() { + if (getCategoryId() != null && !categoryService.existsCategory(getCategoryId())) { + throw new ApiException(ErrorCode.FAILED, "商品分类不存在"); + } + }*/ + + @Override + public boolean updateById() { + if (AgileBootConfig.isDemoEnabled() && isSpecialGoods()) { + throw new ApiException(ErrorCode.FAILED); + } + return super.updateById(); + } + + // 示例方法:判断是否为特殊商品(可根据业务需求实现) + private boolean isSpecialGoods() { + return false; + } +} \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/model/GoodsModelFactory.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/model/GoodsModelFactory.java new file mode 100644 index 0000000..76eae67 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/model/GoodsModelFactory.java @@ -0,0 +1,29 @@ +package com.agileboot.domain.shop.goods.model; + +import com.agileboot.common.exception.ApiException; +import com.agileboot.common.exception.error.ErrorCode; +import com.agileboot.domain.shop.category.db.ShopCategoryService; +import com.agileboot.domain.shop.goods.db.ShopGoodsEntity; +import com.agileboot.domain.shop.goods.db.ShopGoodsService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class GoodsModelFactory { + + private final ShopGoodsService goodsService; + private final ShopCategoryService categoryService; + + public GoodsModel loadById(Long goodsId) { + ShopGoodsEntity entity = goodsService.getById(goodsId); + if (entity == null) { + throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, goodsId, "商品"); + } + return new GoodsModel(entity, goodsService, categoryService); + } + + public GoodsModel create() { + return new GoodsModel(goodsService, categoryService); + } +} \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/query/SearchShopGoodsQuery.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/query/SearchShopGoodsQuery.java index 50469bd..760ffec 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/query/SearchShopGoodsQuery.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/query/SearchShopGoodsQuery.java @@ -22,12 +22,12 @@ public class SearchShopGoodsQuery extends AbstractPageQuery { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper - .like(StrUtil.isNotEmpty(goodsName), "goods_name", goodsName) - .eq(categoryId != null, "category_id", categoryId) - .eq(status != null, "status", status) - .ge(minPrice != null, "price", minPrice) - .le(maxPrice != null, "price", maxPrice) - .eq("deleted", 0); + .like(StrUtil.isNotEmpty(goodsName), "g.goods_name", goodsName) + .eq(categoryId != null, "g.category_id", categoryId) + .eq(status != null, "g.status", status) + .ge(minPrice != null, "g.price", minPrice) + .le(maxPrice != null, "g.price", maxPrice) + .eq("g.deleted", 0); this.timeRangeColumn = "create_time"; diff --git a/agileboot-domain/src/main/resources/mapper/shop/ShopCategoryMapper.xml b/agileboot-domain/src/main/resources/mapper/shop/ShopCategoryMapper.xml new file mode 100644 index 0000000..a686d8a --- /dev/null +++ b/agileboot-domain/src/main/resources/mapper/shop/ShopCategoryMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/mybatisplus/CodeGenerator.java b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/mybatisplus/CodeGenerator.java index ec1496a..db98377 100644 --- a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/mybatisplus/CodeGenerator.java +++ b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/mybatisplus/CodeGenerator.java @@ -61,7 +61,7 @@ public class CodeGenerator { //生成的类 放在orm子模块下的/target/generated-code目录底下 .module("/agileboot-orm/target/generated-code") .parentPackage("com.agileboot") - .tableName("shop_goods") + .tableName("shop_category") // 决定是否继承基类 .isExtendsFromBaseEntity(true) .build(); diff --git a/sql/20250304.sql b/sql/20250304.sql new file mode 100644 index 0000000..f42a45c --- /dev/null +++ b/sql/20250304.sql @@ -0,0 +1,35 @@ +CREATE TABLE `shop_goods` ( + `goods_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '商品唯一ID', + `goods_name` VARCHAR(255) NOT NULL COMMENT '商品名称', + `category_id` BIGINT NOT NULL COMMENT '商品分类ID', + `price` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '销售价格', + `stock` INT NOT NULL DEFAULT 0 COMMENT '库存数量', + `status` TINYINT NOT NULL DEFAULT 2 COMMENT '商品状态(1上架 2下架)', + `cover_img` VARCHAR(512) COMMENT '封面图URL', + `goods_detail` TEXT NOT NULL COMMENT '商品详情(支持2000汉字+10个图片链接)', + `creator_id` BIGINT NOT NULL DEFAULT 0 COMMENT '创建者ID', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater_id` BIGINT NOT NULL DEFAULT 0 COMMENT '更新者ID', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(512) DEFAULT NULL COMMENT '备注', + `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志(0存在 1删除)', + PRIMARY KEY (`goods_id`), + KEY `idx_category` (`category_id`), + KEY `idx_status` (`status`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品信息表'; + +CREATE TABLE `shop_category` ( + `category_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '分类唯一ID', + `category_name` VARCHAR(255) NOT NULL COMMENT '分类名称', + `sort` INT NOT NULL DEFAULT 0 COMMENT '排序权重', + `description` VARCHAR(512) DEFAULT NULL COMMENT '分类描述', + `creator_id` BIGINT NOT NULL DEFAULT 0 COMMENT '创建者ID', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater_id` BIGINT NOT NULL DEFAULT 0 COMMENT '更新者ID', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志(0存在 1删除)', + PRIMARY KEY (`category_id`), + KEY `idx_sort` (`sort`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品分类表'; \ No newline at end of file