From 5f6d0b3b19143cec742ea9f45dbfb1e455e3a641 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 May 2025 10:18:33 +0800 Subject: [PATCH] reactor:移除 mall-product 的 api 包 --- yudao-module-mall/pom.xml | 3 +-- yudao-module-mall/yudao-module-product-api/pom.xml | 34 ---------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java | 20 -------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java | 20 -------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java | 61 ------------------------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java | 4 ---- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java | 33 --------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java | 61 ------------------------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java | 71 ----------------------------------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java | 47 ----------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java | 56 -------------------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java | 104 -------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java | 12 ------------ yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java | 56 -------------------------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java | 15 --------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java | 38 -------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java | 41 ----------------------------------------- yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java | 48 ------------------------------------------------ yudao-module-mall/yudao-module-product-biz/pom.xml | 63 --------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java | 27 --------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java | 27 --------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java | 1 - yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java | 45 --------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java | 92 -------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java | 34 ---------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java | 14 -------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java | 13 ------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java | 30 ------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java | 22 ---------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java | 20 -------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java | 20 -------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java | 75 --------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java | 24 ------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java | 36 ------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java | 37 ------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http | 0 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java | 61 ------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java | 49 ------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java | 45 --------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java | 23 ----------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java | 82 ---------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java | 22 ---------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java | 53 ----------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java | 19 ------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java | 18 ------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java | 17 ----------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java | 19 ------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java | 58 ---------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java | 33 --------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java | 35 ----------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java | 83 ----------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java | 85 ------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java | 30 ------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java | 24 ------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java | 21 --------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java | 24 ------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java | 31 ------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java | 26 -------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http | 4 ---- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java | 140 -------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java | 74 -------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java | 58 ---------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java | 126 ------------------------------------------------------------------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java | 96 ------------------------------------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java | 41 ----------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java | 23 ----------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java | 57 --------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java | 28 ---------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http | 0 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java | 38 -------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java | 99 --------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java | 81 --------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java | 17 ----------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java | 10 ---------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java | 16 ---------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java | 27 --------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java | 74 -------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java | 17 ----------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java | 24 ------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java | 33 --------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java | 4 ---- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java | 4 ---- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java | 22 ---------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http | 18 ------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java | 110 -------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java | 97 ------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java | 56 -------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java | 36 ------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java | 62 -------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java | 54 ------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java | 56 -------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java | 42 ------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java | 53 ----------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java | 64 ---------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java | 159 --------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java | 43 ------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java | 42 ------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java | 47 ----------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java | 55 ------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java | 134 -------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java | 171 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java | 37 ------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java | 43 ------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java | 60 ------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java | 36 ------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java | 24 ------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java | 43 ------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java | 66 ------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java | 154 ---------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java | 6 ------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java | 24 ------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java | 4 ---- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java | 8 -------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java | 86 -------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java | 122 -------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java | 96 ------------------------------------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java | 184 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java | 72 ------------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java | 147 --------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java | 64 ---------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java | 73 ------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java | 42 ------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java | 66 ------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java | 72 ------------------------------------------------------------------------ yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java | 117 --------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java | 80 -------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java | 107 ----------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java | 122 -------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java | 278 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java | 155 ----------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java | 284 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java | 135 --------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java | 163 ------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java | 195 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java | 207 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java | 470 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml | 49 ------------------------------------------------- yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml | 4 ---- yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql | 7 ------- yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql | 157 ------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-product/pom.xml | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java | 20 ++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java | 27 +++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java | 20 ++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java | 27 +++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java | 4 ++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java | 33 +++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java | 34 ++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java | 14 ++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java | 13 +++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java | 30 ++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java | 22 ++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java | 20 ++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java | 20 ++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http | 0 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java | 23 +++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java | 22 ++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java | 19 +++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java | 18 ++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java | 17 +++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java | 19 +++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java | 33 +++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java | 35 +++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java | 30 ++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java | 21 +++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java | 31 +++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java | 26 ++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http | 4 ++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java | 41 +++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java | 23 +++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java | 28 ++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http | 0 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java | 38 ++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java | 17 +++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java | 10 ++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java | 16 ++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java | 27 +++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java | 17 +++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java | 33 +++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java | 4 ++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java | 4 ++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java | 22 ++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http | 18 ++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java | 42 ++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java | 42 ++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java | 12 ++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java | 15 +++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java | 38 ++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java | 41 +++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java | 6 ++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java | 4 ++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/package-info.java | 8 ++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java | 42 ++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java | 470 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/resources/application-unit-test.yaml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-product/src/test/resources/logback.xml | 4 ++++ yudao-module-mall/yudao-module-product/src/test/resources/sql/clean.sql | 7 +++++++ yudao-module-mall/yudao-module-product/src/test/resources/sql/create_tables.sql | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-promotion-biz/pom.xml | 8 ++++---- yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/CouponTakeByRegisterConsumer.java | 2 +- yudao-module-mall/yudao-module-statistics-biz/pom.xml | 6 +++--- yudao-module-mall/yudao-module-trade-biz/pom.xml | 8 ++++---- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java | 1 - 292 files changed, 8858 insertions(+), 8900 deletions(-) delete mode 100644 yudao-module-mall/yudao-module-product-api/pom.xml delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/pom.xml delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java delete mode 100755 yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql delete mode 100644 yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql create mode 100644 yudao-module-mall/yudao-module-product/pom.xml create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/package-info.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java create mode 100644 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java create mode 100755 yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java create mode 100644 yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java create mode 100644 yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java create mode 100644 yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java create mode 100755 yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java create mode 100644 yudao-module-mall/yudao-module-product/src/test/resources/application-unit-test.yaml create mode 100644 yudao-module-mall/yudao-module-product/src/test/resources/logback.xml create mode 100644 yudao-module-mall/yudao-module-product/src/test/resources/sql/clean.sql create mode 100644 yudao-module-mall/yudao-module-product/src/test/resources/sql/create_tables.sql diff --git a/yudao-module-mall/pom.xml b/yudao-module-mall/pom.xml index f4854ae..9066cb7 100644 --- a/yudao-module-mall/pom.xml +++ b/yudao-module-mall/pom.xml @@ -20,8 +20,7 @@ yudao-module-promotion-api yudao-module-promotion-biz - yudao-module-product-api - yudao-module-product-biz + yudao-module-product yudao-module-trade-api yudao-module-trade-biz yudao-module-statistics-api diff --git a/yudao-module-mall/yudao-module-product-api/pom.xml b/yudao-module-mall/yudao-module-product-api/pom.xml deleted file mode 100644 index 123e7c3..0000000 --- a/yudao-module-mall/yudao-module-product-api/pom.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - 4.0.0 - - cn.iocoder.boot - yudao-module-mall - ${revision} - - - yudao-module-product-api - jar - - ${project.artifactId} - - product 模块 API,暴露给其它模块调用 - - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework.boot - spring-boot-starter-validation - true - - - - diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java deleted file mode 100644 index 38feb96..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.product.api.category; - -import java.util.Collection; - -/** - * 商品分类 API 接口 - * - * @author owen - */ -public interface ProductCategoryApi { - - /** - * 校验商品分类是否有效。如下情况,视为无效: - * 1. 商品分类编号不存在 - * 2. 商品分类被禁用 - * - * @param ids 商品分类编号数组 - */ - void validateCategoryList(Collection ids); -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java deleted file mode 100644 index b0ba1f7..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.product.api.comment; - -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; - -/** - * 产品评论 API 接口 - * - * @author HUIHUI - */ -public interface ProductCommentApi { - - /** - * 创建评论 - * - * @param createReqDTO 评论参数 - * @return 返回评论创建后的 id - */ - Long createComment(ProductCommentCreateReqDTO createReqDTO); - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java deleted file mode 100644 index 66caeed..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.module.product.api.comment.dto; - -import lombok.Data; - -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 评论创建请求 DTO - * - * @author HUIHUI - */ -@Data -public class ProductCommentCreateReqDTO { - - /** - * 商品 SKU 编号 - */ - @NotNull(message = "商品 SKU 编号不能为空") - private Long skuId; - /** - * 订单编号 - */ - private Long orderId; - /** - * 交易订单项编号 - */ - private Long orderItemId; - - /** - * 描述星级 1-5 分 - */ - @NotNull(message = "描述星级不能为空") - private Integer descriptionScores; - /** - * 服务星级 1-5 分 - */ - @NotNull(message = "服务星级不能为空") - private Integer benefitScores; - /** - * 评论内容 - */ - @NotNull(message = "评论内容不能为空") - private String content; - /** - * 评论图片地址数组,以逗号分隔最多上传 9 张 - */ - private List picUrls; - - /** - * 是否匿名 - */ - @NotNull(message = "是否匿名不能为空") - private Boolean anonymous; - /** - * 评价人 - */ - @NotNull(message = "评价人不能为空") - private Long userId; - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java deleted file mode 100644 index b190928..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.module.product.api; \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java deleted file mode 100644 index 2a1ab71..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.product.api.property.dto; - -import lombok.Data; - -/** - * 商品属性项的明细 Response DTO - * - * @author 芋道源码 - */ -@Data -public class ProductPropertyValueDetailRespDTO { - - /** - * 属性的编号 - */ - private Long propertyId; - - /** - * 属性的名称 - */ - private String propertyName; - - /** - * 属性值的编号 - */ - private Long valueId; - - /** - * 属性值的名称 - */ - private String valueName; - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java deleted file mode 100644 index f6e6034..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.module.product.api.sku; - -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -/** - * 商品 SKU API 接口 - * - * @author LeeYan9 - * @since 2022-08-26 - */ -public interface ProductSkuApi { - - /** - * 查询 SKU 信息 - * - * @param id SKU 编号 - * @return SKU 信息 - */ - ProductSkuRespDTO getSku(Long id); - - /** - * 批量查询 SKU 数组 - * - * @param ids SKU 编号列表 - * @return SKU 数组 - */ - List getSkuList(Collection ids); - - /** - * 批量查询 SKU MAP - * - * @param ids SKU 编号列表 - * @return SKU MAP - */ - default Map getSkuMap(Collection ids) { - return convertMap(getSkuList(ids), ProductSkuRespDTO::getId); - } - - /** - * 批量查询 SKU 数组 - * - * @param spuIds SPU 编号列表 - * @return SKU 数组 - */ - List getSkuListBySpuId(Collection spuIds); - - /** - * 更新 SKU 库存(增加 or 减少) - * - * @param updateStockReqDTO 更新请求 - */ - void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java deleted file mode 100644 index 338c4dd..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.product.api.sku.dto; - -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; -import lombok.Data; - -import java.util.List; - -/** - * 商品 SKU 信息 Response DTO - * - * @author LeeYan9 - * @since 2022-08-26 - */ -@Data -public class ProductSkuRespDTO { - - /** - * 商品 SKU 编号,自增 - */ - private Long id; - /** - * SPU 编号 - */ - private Long spuId; - - /** - * 属性数组 - */ - private List properties; - /** - * 销售价格,单位:分 - */ - private Integer price; - /** - * 市场价,单位:分 - */ - private Integer marketPrice; - /** - * 成本价,单位:分 - */ - private Integer costPrice; - /** - * SKU 的条形码 - */ - private String barCode; - /** - * 图片地址 - */ - private String picUrl; - /** - * 库存 - */ - private Integer stock; - /** - * 商品重量,单位:kg 千克 - */ - private Double weight; - /** - * 商品体积,单位:m^3 平米 - */ - private Double volume; - /** - * 一级分销的佣金,单位:分 - */ - private Integer firstBrokeragePrice; - /** - * 二级分销的佣金,单位:分 - */ - private Integer secondBrokeragePrice; - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java deleted file mode 100644 index 98c63c7..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.product.api.sku.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 商品 SKU 更新库存 Request DTO - * - * @author LeeYan9 - * @since 2022-08-26 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class ProductSkuUpdateStockReqDTO { - - /** - * 商品 SKU - */ - @NotNull(message = "商品 SKU 不能为空") - private List items; - - @Data - public static class Item { - - /** - * 商品 SKU 编号 - */ - @NotNull(message = "商品 SKU 编号不能为空") - private Long id; - - /** - * 库存变化数量 - * - * 正数:增加库存 - * 负数:扣减库存 - */ - @NotNull(message = "库存变化数量不能为空") - private Integer incrCount; - - } - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java deleted file mode 100644 index 499a0ca..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.product.api.spu; - -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -/** - * 商品 SPU API 接口 - * - * @author LeeYan9 - * @since 2022-08-26 - */ -public interface ProductSpuApi { - - /** - * 批量查询 SPU 数组 - * - * @param ids SPU 编号列表 - * @return SPU 数组 - */ - List getSpuList(Collection ids); - - /** - * 批量查询 SPU MAP - * - * @param ids SPU 编号列表 - * @return SPU MAP - */ - default Map getSpuMap(Collection ids) { - return convertMap(getSpuList(ids), ProductSpuRespDTO::getId); - } - - /** - * 批量查询 SPU 数组,并且校验是否 SPU 是否有效。 - * - * 如下情况,视为无效: - * 1. 商品编号不存在 - * 2. 商品被禁用 - * - * @param ids SPU 编号列表 - * @return SPU 数组 - */ - List validateSpuList(Collection ids); - - /** - * 获得 SPU - * - * @return SPU - */ - ProductSpuRespDTO getSpu(Long id); - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java deleted file mode 100644 index 60fb0bc..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java +++ /dev/null @@ -1,104 +0,0 @@ -package cn.iocoder.yudao.module.product.api.spu.dto; - -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import lombok.Data; - -import java.util.List; - -/** - * 商品 SPU 信息 Response DTO - * - * @author LeeYan9 - * @since 2022-08-26 - */ -@Data -public class ProductSpuRespDTO { - - /** - * 商品 SPU 编号,自增 - */ - private Long id; - - // ========== 基本信息 ========= - - /** - * 商品名称 - */ - private String name; - - /** - * 商品分类编号 - */ - private Long categoryId; - /** - * 商品封面图 - */ - private String picUrl; - - /** - * 商品状态 - *

- * 枚举 {@link ProductSpuStatusEnum} - */ - private Integer status; - - // ========== SKU 相关字段 ========= - - /** - * 规格类型 - * - * false - 单规格 - * true - 多规格 - */ - private Boolean specType; - /** - * 商品价格,单位使用:分 - */ - private Integer price; - /** - * 市场价,单位使用:分 - */ - private Integer marketPrice; - /** - * 成本价,单位使用:分 - */ - private Integer costPrice; - /** - * 库存 - */ - private Integer stock; - - // ========== 物流相关字段 ========= - - /** - * 配送方式数组 - * - * 对应 DeliveryTypeEnum 枚举 - */ - private List deliveryTypes; - - /** - * 物流配置模板编号 - * - * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 - */ - private Long deliveryTemplateId; - - // ========== 营销相关字段 ========= - - /** - * 赠送积分 - */ - private Integer giveIntegral; - - // ========== 分销相关字段 ========= - - /** - * 分销类型 - * - * false - 默认 - * true - 自行设置 - */ - private Boolean subCommissionType; - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java deleted file mode 100644 index b96dde1..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.module.product.enums; - -/** - * product 字典类型的枚举类 - * - * @author HUIHUI - */ -public interface DictTypeConstants { - - String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态 - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java deleted file mode 100644 index 3531b14..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.product.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * Product 错误码枚举类 - * - * product 系统,使用 1-008-000-000 段 - */ -public interface ErrorCodeConstants { - - // ========== 商品分类相关 1-008-001-000 ============ - ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_008_001_000, "商品分类不存在"); - ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_008_001_001, "父分类不存在"); - ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_008_001_002, "父分类不能是二级分类"); - ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_008_001_003, "存在子分类,无法删除"); - ErrorCode CATEGORY_DISABLED = new ErrorCode(1_008_001_004, "商品分类({})已禁用,无法使用"); - ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1_008_001_005, "类别下存在商品,无法删除"); - - // ========== 商品品牌相关编号 1-008-002-000 ========== - ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1_008_002_000, "品牌不存在"); - ErrorCode BRAND_DISABLED = new ErrorCode(1_008_002_001, "品牌已禁用"); - ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1_008_002_002, "品牌名称已存在"); - - // ========== 商品属性项 1-008-003-000 ========== - ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1_008_003_000, "属性项不存在"); - ErrorCode PROPERTY_EXISTS = new ErrorCode(1_008_003_001, "属性项的名称已存在"); - ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1_008_003_002, "属性项下存在属性值,无法删除"); - - // ========== 商品属性值 1-008-004-000 ========== - ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1_008_004_000, "属性值不存在"); - ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1_008_004_001, "属性值的名称已存在"); - - // ========== 商品 SPU 1-008-005-000 ========== - ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在"); - ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下"); - ErrorCode SPU_SAVE_FAIL_COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_008_005_002, "商品 SPU 保存失败,原因:优惠劵不存在"); - ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_003, "商品 SPU【{}】不处于上架状态"); - ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_004, "商品 SPU 不处于回收站状态"); - - // ========== 商品 SKU 1-008-006-000 ========== - ErrorCode SKU_NOT_EXISTS = new ErrorCode(1_008_006_000, "商品 SKU 不存在"); - ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1_008_006_001, "商品 SKU 的属性组合存在重复"); - ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1_008_006_002, "一个 SPU 下的每个 SKU,其属性项必须一致"); - ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1_008_006_003, "一个 SPU 下的每个 SKU,必须不重复"); - ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1_008_006_004, "商品 SKU 库存不足"); - - // ========== 商品 评价 1-008-007-000 ========== - ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1_008_007_000, "商品评价不存在"); - ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1_008_007_001, "订单的商品评价已存在"); - - // ========== 商品 收藏 1-008-008-000 ========== - ErrorCode FAVORITE_EXISTS = new ErrorCode(1_008_008_000, "该商品已经被收藏"); - ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1_008_008_001, "商品收藏不存在"); - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java deleted file mode 100644 index f3570c5..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.product.enums; - -/** - * Product 常量 - * - * @author HUIHUI - */ -public interface ProductConstants { - - /** - * 警戒库存 TODO 警戒库存暂时为 10,后期需要使用常量或者数据库配置替换 - */ - int ALERT_STOCK = 10; - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java deleted file mode 100644 index f128a60..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.product.enums.comment; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 商品评论的审批状态枚举 - * - * @author 芋道源码 - */ -@Getter -@AllArgsConstructor -public enum ProductCommentAuditStatusEnum implements ArrayValuable { - - NONE(0, "待审核"), - APPROVE(1, "审批通过"), - REJECT(2, "审批不通过"),; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(ProductCommentAuditStatusEnum::getStatus).toArray(Integer[]::new); - - /** - * 审批状态 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java deleted file mode 100644 index 58c6a45..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.product.enums.comment; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 商品评论的星级枚举 - * - * @author wangzhs - */ -@Getter -@AllArgsConstructor -public enum ProductCommentScoresEnum implements ArrayValuable { - - ONE(1, "1星"), - TWO(2, "2星"), - THREE(3, "3星"), - FOUR(4, "4星"), - FIVE(5, "5星"); - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(ProductCommentScoresEnum::getScores).toArray(Integer[]::new); - - /** - * 星级 - */ - private final Integer scores; - - /** - * 星级名 - */ - private final String name; - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java deleted file mode 100644 index 5735f49..0000000 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.yudao.module.product.enums.spu; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 商品 SPU 状态 - * - * @author 芋道源码 - */ -@Getter -@AllArgsConstructor -public enum ProductSpuStatusEnum implements ArrayValuable { - - RECYCLE(-1, "回收站"), - DISABLE(0, "下架"), - ENABLE(1, "上架"); - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(ProductSpuStatusEnum::getStatus).toArray(Integer[]::new); - - /** - * 状态 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - - @Override - public Integer[] array() { - return ARRAYS; - } - - /** - * 判断是否处于【上架】状态 - * - * @param status 状态 - * @return 是否处于【上架】状态 - */ - public static boolean isEnable(Integer status) { - return ENABLE.getStatus().equals(status); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/pom.xml b/yudao-module-mall/yudao-module-product-biz/pom.xml deleted file mode 100644 index c8bad46..0000000 --- a/yudao-module-mall/yudao-module-product-biz/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - cn.iocoder.boot - yudao-module-mall - ${revision} - - 4.0.0 - yudao-module-product-biz - jar - - ${project.artifactId} - - product 模块,主要实现商品相关功能 - 例如:品牌、商品分类、spu、sku等功能。 - - - - - cn.iocoder.boot - yudao-module-product-api - ${revision} - - - cn.iocoder.boot - yudao-module-member-api - ${revision} - - - - - - - cn.iocoder.boot - yudao-spring-boot-starter-web - - - cn.iocoder.boot - yudao-spring-boot-starter-security - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mybatis - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - - - - - cn.iocoder.boot - yudao-spring-boot-starter-excel - - - - diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java deleted file mode 100644 index b339a47..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.product.api.category; - -import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import jakarta.annotation.Resource; -import java.util.Collection; - -/** - * 商品分类 API 接口实现类 - * - * @author owen - */ -@Service -@Validated -public class ProductCategoryApiImpl implements ProductCategoryApi { - - @Resource - private ProductCategoryService productCategoryService; - - @Override - public void validateCategoryList(Collection ids) { - productCategoryService.validateCategoryList(ids); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java deleted file mode 100644 index 7bda131..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.product.api.comment; - -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; -import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import jakarta.annotation.Resource; - -/** - * 商品评论 API 实现类 - * - * @author HUIHUI - */ -@Service -@Validated -public class ProductCommentApiImpl implements ProductCommentApi { - - @Resource - private ProductCommentService productCommentService; - - @Override - public Long createComment(ProductCommentCreateReqDTO createReqDTO) { - return productCommentService.createComment(createReqDTO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java deleted file mode 100644 index 162453c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.product.api; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java deleted file mode 100644 index dbdc37e..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.product.api.sku; - -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; -import java.util.List; - -/** - * 商品 SKU API 实现类 - * - * @author LeeYan9 - * @since 2022-09-06 - */ -@Service -@Validated -public class ProductSkuApiImpl implements ProductSkuApi { - - @Resource - private ProductSkuService productSkuService; - - @Override - public ProductSkuRespDTO getSku(Long id) { - ProductSkuDO sku = productSkuService.getSku(id); - return BeanUtils.toBean(sku, ProductSkuRespDTO.class); - } - - @Override - public List getSkuList(Collection ids) { - List skus = productSkuService.getSkuList(ids); - return BeanUtils.toBean(skus, ProductSkuRespDTO.class); - } - - @Override - public List getSkuListBySpuId(Collection spuIds) { - List skus = productSkuService.getSkuListBySpuId(spuIds); - return BeanUtils.toBean(skus, ProductSkuRespDTO.class); - } - - @Override - public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) { - productSkuService.updateSkuStock(updateStockReqDTO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java deleted file mode 100644 index 050f9f5..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.product.api.spu; - -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; -import java.util.List; - -/** - * 商品 SPU API 接口实现类 - * - * @author LeeYan9 - * @since 2022-09-06 - */ -@Service -@Validated -public class ProductSpuApiImpl implements ProductSpuApi { - - @Resource - private ProductSpuService spuService; - - @Override - public List getSpuList(Collection ids) { - List spus = spuService.getSpuList(ids); - return BeanUtils.toBean(spus, ProductSpuRespDTO.class); - } - - @Override - public List validateSpuList(Collection ids) { - List spus = spuService.validateSpuList(ids); - return BeanUtils.toBean(spus, ProductSpuRespDTO.class); - } - - @Override - public ProductSpuRespDTO getSpu(Long id) { - ProductSpuDO spu = spuService.getSpu(id); - return BeanUtils.toBean(spu, ProductSpuRespDTO.class); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java deleted file mode 100644 index aff47c7..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java +++ /dev/null @@ -1,92 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; -import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import java.util.Comparator; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - 商品品牌") -@RestController -@RequestMapping("/product/brand") -@Validated -public class ProductBrandController { - - @Resource - private ProductBrandService brandService; - - @PostMapping("/create") - @Operation(summary = "创建品牌") - @PreAuthorize("@ss.hasPermission('product:brand:create')") - public CommonResult createBrand(@Valid @RequestBody ProductBrandCreateReqVO createReqVO) { - return success(brandService.createBrand(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新品牌") - @PreAuthorize("@ss.hasPermission('product:brand:update')") - public CommonResult updateBrand(@Valid @RequestBody ProductBrandUpdateReqVO updateReqVO) { - brandService.updateBrand(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除品牌") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:brand:delete')") - public CommonResult deleteBrand(@RequestParam("id") Long id) { - brandService.deleteBrand(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得品牌") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:brand:query')") - public CommonResult getBrand(@RequestParam("id") Long id) { - ProductBrandDO brand = brandService.getBrand(id); - return success(ProductBrandConvert.INSTANCE.convert(brand)); - } - - @GetMapping("/list-all-simple") - @Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项") - public CommonResult> getSimpleBrandList() { - // 获取品牌列表,只要开启状态的 - List list = brandService.getBrandListByStatus(CommonStatusEnum.ENABLE.getStatus()); - // 排序后,返回给前端 - return success(ProductBrandConvert.INSTANCE.convertList1(list)); - } - - @GetMapping("/page") - @Operation(summary = "获得品牌分页") - @PreAuthorize("@ss.hasPermission('product:brand:query')") - public CommonResult> getBrandPage(@Valid ProductBrandPageReqVO pageVO) { - PageResult pageResult = brandService.getBrandPage(pageVO); - return success(ProductBrandConvert.INSTANCE.convertPage(pageResult)); - } - - @GetMapping("/list") - @Operation(summary = "获得品牌列表") - @PreAuthorize("@ss.hasPermission('product:brand:query')") - public CommonResult> getBrandList(@Valid ProductBrandListReqVO listVO) { - List list = brandService.getBrandList(listVO); - list.sort(Comparator.comparing(ProductBrandDO::getSort)); - return success(ProductBrandConvert.INSTANCE.convertList(list)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java deleted file mode 100644 index 152de72..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** -* 商品品牌 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class ProductBrandBaseVO { - - @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") - @NotNull(message = "品牌名称不能为空") - private String name; - - @Schema(description = "品牌图片", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "品牌图片不能为空") - private String picUrl; - - @Schema(description = "品牌排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "品牌排序不能为空") - private Integer sort; - - @Schema(description = "品牌描述", example = "描述") - private String description; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "状态不能为空") - private Integer status; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java deleted file mode 100644 index dc85a47..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 商品品牌创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductBrandCreateReqVO extends ProductBrandBaseVO { - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java deleted file mode 100644 index ed93ff0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - 商品品牌分页 Request VO") -@Data -public class ProductBrandListReqVO { - - @Schema(description = "品牌名称", example = "苹果") - private String name; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java deleted file mode 100644 index 3a6efc9..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 商品品牌分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductBrandPageReqVO extends PageParam { - - @Schema(description = "品牌名称", example = "苹果") - private String name; - - @Schema(description = "状态", example = "0") - private Integer status; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java deleted file mode 100644 index 486fe76..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 品牌 Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductBrandRespVO extends ProductBrandBaseVO { - - @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java deleted file mode 100644 index 6379a5f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Schema(description = "管理后台 - 品牌精简信息 Response VO") -@Data -@NoArgsConstructor -@AllArgsConstructor -public class ProductBrandSimpleRespVO { - - @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") - private String name; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java deleted file mode 100644 index b9585b6..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.brand.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 商品品牌更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductBrandUpdateReqVO extends ProductBrandBaseVO { - - @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "品牌编号不能为空") - private Long id; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java deleted file mode 100644 index f3f5980..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.category; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Comparator; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - 商品分类") -@RestController -@RequestMapping("/product/category") -@Validated -public class ProductCategoryController { - - @Resource - private ProductCategoryService categoryService; - - @PostMapping("/create") - @Operation(summary = "创建商品分类") - @PreAuthorize("@ss.hasPermission('product:category:create')") - public CommonResult createCategory(@Valid @RequestBody ProductCategorySaveReqVO createReqVO) { - return success(categoryService.createCategory(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新商品分类") - @PreAuthorize("@ss.hasPermission('product:category:update')") - public CommonResult updateCategory(@Valid @RequestBody ProductCategorySaveReqVO updateReqVO) { - categoryService.updateCategory(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除商品分类") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('product:category:delete')") - public CommonResult deleteCategory(@RequestParam("id") Long id) { - categoryService.deleteCategory(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得商品分类") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:category:query')") - public CommonResult getCategory(@RequestParam("id") Long id) { - ProductCategoryDO category = categoryService.getCategory(id); - return success(BeanUtils.toBean(category, ProductCategoryRespVO.class)); - } - - @GetMapping("/list") - @Operation(summary = "获得商品分类列表") - @PreAuthorize("@ss.hasPermission('product:category:query')") - public CommonResult> getCategoryList(@Valid ProductCategoryListReqVO listReqVO) { - List list = categoryService.getCategoryList(listReqVO); - list.sort(Comparator.comparing(ProductCategoryDO::getSort)); - return success(BeanUtils.toBean(list, ProductCategoryRespVO.class)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java deleted file mode 100644 index 9e5364c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.category.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.Collection; - -@Schema(description = "管理后台 - 商品分类列表查询 Request VO") -@Data -public class ProductCategoryListReqVO { - - @Schema(description = "分类名称", example = "办公文具") - private String name; - - @Schema(description = "开启状态", example = "0") - private Integer status; - - @Schema(description = "父分类编号", example = "1") - private Long parentId; - - @Schema(description = "父分类编号数组", example = "1,2,3") - private Collection parentIds; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java deleted file mode 100644 index c8ef92e..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.category.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 商品分类 Response VO") -@Data -public class ProductCategoryRespVO { - - @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Long id; - - @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long parentId; - - @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具") - private String name; - - @Schema(description = "移动端分类图", requiredMode = Schema.RequiredMode.REQUIRED) - private String picUrl; - - @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer sort; - - @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - private Integer status; - - @Schema(description = "分类描述", example = "描述") - private String description; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java deleted file mode 100644 index 5f03df1..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.category.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - 商品分类新增/更新 Request VO") -@Data -public class ProductCategorySaveReqVO { - - @Schema(description = "分类编号", example = "2") - private Long id; - - @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "父分类编号不能为空") - private Long parentId; - - @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具") - @NotBlank(message = "分类名称不能为空") - private String name; - - @Schema(description = "移动端分类图", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "移动端分类图不能为空") - private String picUrl; - - @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer sort; - - @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "开启状态不能为空") - private Integer status; - - @Schema(description = "分类描述", example = "描述") - private String description; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http deleted file mode 100644 index e69de29..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http +++ /dev/null diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java deleted file mode 100644 index 3cac6d0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.comment; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - 商品评价") -@RestController -@RequestMapping("/product/comment") -@Validated -public class ProductCommentController { - - @Resource - private ProductCommentService productCommentService; - - @GetMapping("/page") - @Operation(summary = "获得商品评价分页") - @PreAuthorize("@ss.hasPermission('product:comment:query')") - public CommonResult> getCommentPage(@Valid ProductCommentPageReqVO pageVO) { - PageResult pageResult = productCommentService.getCommentPage(pageVO); - return success(BeanUtils.toBean(pageResult, ProductCommentRespVO.class)); - } - - @PutMapping("/update-visible") - @Operation(summary = "显示 / 隐藏评论") - @PreAuthorize("@ss.hasPermission('product:comment:update')") - public CommonResult updateCommentVisible(@Valid @RequestBody ProductCommentUpdateVisibleReqVO updateReqVO) { - productCommentService.updateCommentVisible(updateReqVO); - return success(true); - } - - @PutMapping("/reply") - @Operation(summary = "商家回复") - @PreAuthorize("@ss.hasPermission('product:comment:update')") - public CommonResult commentReply(@Valid @RequestBody ProductCommentReplyReqVO replyVO) { - productCommentService.replyComment(replyVO, getLoginUserId()); - return success(true); - } - - @PostMapping("/create") - @Operation(summary = "添加自评") - @PreAuthorize("@ss.hasPermission('product:comment:update')") - public CommonResult createComment(@Valid @RequestBody ProductCommentCreateReqVO createReqVO) { - productCommentService.createComment(createReqVO); - return success(true); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java deleted file mode 100644 index b411db0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.comment.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - 商品评价创建 Request VO") -@Data -public class ProductCommentCreateReqVO { - - @Schema(description = "评价人", requiredMode = Schema.RequiredMode.REQUIRED, example = "16868") - private Long userId; - - @Schema(description = "评价订单项", requiredMode = Schema.RequiredMode.REQUIRED, example = "19292") - private Long orderItemId; - - @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小姑凉") - @NotNull(message = "评价人名称不能为空") - private String userNickname; - - @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - @NotNull(message = "评价人头像不能为空") - private String userAvatar; - - @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品 SKU 编号不能为空") - private Long skuId; - - @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "描述星级不能为空") - private Integer descriptionScores; - - @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "服务星级分不能为空") - private Integer benefitScores; - - @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿起来非常丝滑凉快") - @NotNull(message = "评论内容不能为空") - private String content; - - @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, - example = "[https://www.iocoder.cn/xx.png]") - @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") - private List picUrls; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java deleted file mode 100644 index 3791f57..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.comment.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 商品评价分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductCommentPageReqVO extends PageParam { - - @Schema(description = "评价人名称", example = "王二狗") - private String userNickname; - - @Schema(description = "交易订单编号", example = "24428") - private Long orderId; - - @Schema(description = "商品SPU编号", example = "29502") - private Long spuId; - - @Schema(description = "商品SPU名称", example = "感冒药") - private String spuName; - - @Schema(description = "评分星级 1-5 分", example = "5") - @InEnum(ProductCommentScoresEnum.class) - private Integer scores; - - @Schema(description = "商家是否回复", example = "true") - private Boolean replyStatus; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java deleted file mode 100644 index 9d2aa42..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.comment.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 商品评价的商家回复 Request VO") -@Data -@ToString(callSuper = true) -public class ProductCommentReplyReqVO { - - @Schema(description = "评价编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721") - @NotNull(message = "评价编号不能为空") - private Long id; - - @Schema(description = "商家回复内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "谢谢亲") - @NotEmpty(message = "商家回复内容不能为空") - private String replyContent; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java deleted file mode 100644 index 605019a..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.comment.vo; - -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - 商品评价 Response VO") -@Data -public class ProductCommentRespVO { - - @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24965") - private Long id; - - @Schema(description = "评价人", requiredMode = Schema.RequiredMode.REQUIRED, example = "16868") - private Long userId; - - @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小姑凉") - private String userNickname; - - @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - private String userAvatar; - @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean anonymous; - - @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24428") - private Long orderId; - - @Schema(description = "评价订单项", requiredMode = Schema.RequiredMode.REQUIRED, example = "19292") - private Long orderItemId; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖") - private Long spuId; - - @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long skuId; - - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") - private String spuName; - - @Schema(description = "商品 SKU 图片地址", example = "https://www.iocoder.cn/yudao.jpg") - private String skuPicUrl; - - @Schema(description = "商品 SKU 规格值数组") - private List skuProperties; - - @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED) - private Boolean visible; - - @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - private Integer scores; - - @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - private Integer descriptionScores; - - @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - private Integer benefitScores; - - @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿起来非常丝滑凉快") - private String content; - - @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]") - private List picUrls; - - @Schema(description = "商家是否回复", requiredMode = Schema.RequiredMode.REQUIRED) - private Boolean replyStatus; - - @Schema(description = "回复管理员编号", example = "9527") - private Long replyUserId; - - @Schema(description = "商家回复内容", example = "感谢好评哦亲(づ ̄3 ̄)づ╭❤~") - private String replyContent; - - @Schema(description = "商家回复时间", example = "2023-08-08 12:20:55") - private LocalDateTime replyTime; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java deleted file mode 100644 index d970c3f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.comment.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 商品评价可见修改 Request VO") -@Data -@ToString(callSuper = true) -public class ProductCommentUpdateVisibleReqVO { - - @Schema(description = "评价编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721") - @NotNull(message = "评价编号不能为空") - private Long id; - - @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - @NotNull(message = "是否可见不能为空") - private Boolean visible; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java deleted file mode 100644 index b0ff22c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.favorite; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoriteRespVO; -import cn.iocoder.yudao.module.product.convert.favorite.ProductFavoriteConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.service.favorite.ProductFavoriteService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -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 jakarta.annotation.Resource; -import jakarta.validation.Valid; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; - -@Tag(name = "管理后台 - 商品收藏") -@RestController -@RequestMapping("/product/favorite") -@Validated -public class ProductFavoriteController { - - @Resource - private ProductFavoriteService productFavoriteService; - - @Resource - private ProductSpuService productSpuService; - - @GetMapping("/page") - @Operation(summary = "获得商品收藏分页") - @PreAuthorize("@ss.hasPermission('product:favorite:query')") - public CommonResult> getFavoritePage(@Valid ProductFavoritePageReqVO pageVO) { - PageResult pageResult = productFavoriteService.getFavoritePage(pageVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - // 拼接数据 - List spuList = productSpuService.getSpuList(convertSet(pageResult.getList(), ProductFavoriteDO::getSpuId)); - return success(ProductFavoriteConvert.INSTANCE.convertPage(pageResult, spuList)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java deleted file mode 100644 index 9ecf2fc..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** - * 商品收藏 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class ProductFavoriteBaseVO { - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5036") - @NotNull(message = "用户编号不能为空") - private Long userId; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java deleted file mode 100644 index 3d78883..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 商品收藏分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductFavoritePageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "5036") - private Long userId; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java deleted file mode 100644 index 8233100..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 商品收藏的单个 Response VO") -@Data -@ToString(callSuper = true) -public class ProductFavoriteReqVO extends ProductFavoriteBaseVO { - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32734") - @NotNull(message = "商品 SPU 编号不能为空") - private Long spuId; -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java deleted file mode 100644 index 3c09aa8..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; - -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -@Schema(description = "管理后台 - 商品收藏 Response VO") -@Data -@ToString(callSuper = true) -public class ProductFavoriteRespVO extends ProductSpuRespVO { - - @Schema(description = "userId", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - private Long userId; - - @Schema(description = "spuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - private Long spuId; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java deleted file mode 100644 index 38c888b..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.history; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryRespVO; -import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.service.history.ProductBrowseHistoryService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -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 java.util.Map; -import java.util.Optional; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; - -@Tag(name = "管理后台 - 商品浏览记录") -@RestController -@RequestMapping("/product/browse-history") -@Validated -public class ProductBrowseHistoryController { - - @Resource - private ProductBrowseHistoryService browseHistoryService; - @Resource - private ProductSpuService productSpuService; - - @GetMapping("/page") - @Operation(summary = "获得商品浏览记录分页") - @PreAuthorize("@ss.hasPermission('product:browse-history:query')") - public CommonResult> getBrowseHistoryPage(@Valid ProductBrowseHistoryPageReqVO pageReqVO) { - PageResult pageResult = browseHistoryService.getBrowseHistoryPage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - - // 得到商品 spu 信息 - Map spuMap = productSpuService.getSpuMap( - convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId)); - return success(BeanUtils.toBean(pageResult, ProductBrowseHistoryRespVO.class, - vo -> Optional.ofNullable(spuMap.get(vo.getSpuId())) - .ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice()) - .setSalesCount(spu.getSalesCount()).setStock(spu.getStock())))); - } - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java deleted file mode 100644 index aa30102..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.history.vo; - -import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 商品浏览记录分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductBrowseHistoryPageReqVO extends SortablePageParam { - - @Schema(description = "用户编号", example = "4314") - private Long userId; - - @Schema(description = "用户是否删除", example = "false") - private Boolean userDeleted; - - @Schema(description = "商品 SPU 编号", example = "42") - private Long spuId; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java deleted file mode 100644 index df8ae8c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.history.vo; - -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - 商品浏览记录 Response VO") -@Data -@ExcelIgnoreUnannotated -public class ProductBrowseHistoryRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") - private Long spuId; - - // ========== 商品相关字段 ========== - - @Schema(description = "商品 SPU 名称", example = "赵六") - private String spuName; - - @Schema(description = "商品封面图", example = "https://domain/pic.png") - private String picUrl; - - @Schema(description = "商品单价", example = "100") - private Integer price; - - @Schema(description = "商品销量", example = "100") - private Integer salesCount; - - @Schema(description = "库存", example = "100") - private Integer stock; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java deleted file mode 100644 index 1ff2d9c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java +++ /dev/null @@ -1,83 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertySaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - 商品属性项") -@RestController -@RequestMapping("/product/property") -@Validated -public class ProductPropertyController { - - @Resource - private ProductPropertyService productPropertyService; - - @PostMapping("/create") - @Operation(summary = "创建属性项") - @PreAuthorize("@ss.hasPermission('product:property:create')") - public CommonResult createProperty(@Valid @RequestBody ProductPropertySaveReqVO createReqVO) { - return success(productPropertyService.createProperty(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新属性项") - @PreAuthorize("@ss.hasPermission('product:property:update')") - public CommonResult updateProperty(@Valid @RequestBody ProductPropertySaveReqVO updateReqVO) { - productPropertyService.updateProperty(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除属性项") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('product:property:delete')") - public CommonResult deleteProperty(@RequestParam("id") Long id) { - productPropertyService.deleteProperty(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得属性项") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:property:query')") - public CommonResult getProperty(@RequestParam("id") Long id) { - ProductPropertyDO property = productPropertyService.getProperty(id); - return success(BeanUtils.toBean(property, ProductPropertyRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得属性项分页") - @PreAuthorize("@ss.hasPermission('product:property:query')") - public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { - PageResult pageResult = productPropertyService.getPropertyPage(pageVO); - return success(BeanUtils.toBean(pageResult, ProductPropertyRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得属性项精简列表") - public CommonResult> getPropertySimpleList() { - List list = productPropertyService.getPropertyList(); - return success(convertList(list, property -> new ProductPropertyRespVO() // 只返回 id、name 属性 - .setId(property.getId()).setName(property.getName()))); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java deleted file mode 100644 index 647df87..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueSaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.singleton; - -@Tag(name = "管理后台 - 商品属性值") -@RestController -@RequestMapping("/product/property/value") -@Validated -public class ProductPropertyValueController { - - @Resource - private ProductPropertyValueService productPropertyValueService; - - @PostMapping("/create") - @Operation(summary = "创建属性值") - @PreAuthorize("@ss.hasPermission('product:property:create')") - public CommonResult createPropertyValue(@Valid @RequestBody ProductPropertyValueSaveReqVO createReqVO) { - return success(productPropertyValueService.createPropertyValue(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新属性值") - @PreAuthorize("@ss.hasPermission('product:property:update')") - public CommonResult updatePropertyValue(@Valid @RequestBody ProductPropertyValueSaveReqVO updateReqVO) { - productPropertyValueService.updatePropertyValue(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除属性值") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:property:delete')") - public CommonResult deletePropertyValue(@RequestParam("id") Long id) { - productPropertyValueService.deletePropertyValue(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得属性值") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:property:query')") - public CommonResult getPropertyValue(@RequestParam("id") Long id) { - ProductPropertyValueDO value = productPropertyValueService.getPropertyValue(id); - return success(BeanUtils.toBean(value, ProductPropertyValueRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得属性值分页") - @PreAuthorize("@ss.hasPermission('product:property:query')") - public CommonResult> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) { - PageResult pageResult = productPropertyValueService.getPropertyValuePage(pageVO); - return success(BeanUtils.toBean(pageResult, ProductPropertyValueRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得属性值精简列表") - @Parameter(name = "propertyId", description = "属性项编号", required = true, example = "1024") - public CommonResult> getPropertyValueSimpleList(@RequestParam("propertyId") Long propertyId) { - List list = productPropertyValueService.getPropertyValueListByPropertyId(singleton(propertyId)); - return success(convertList(list, value -> new ProductPropertyValueRespVO() // 只返回 id、name 属性 - .setId(value.getId()).setName(value.getName()))); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java deleted file mode 100644 index 97b959d..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 属性项 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductPropertyPageReqVO extends PageParam { - - @Schema(description = "名称", example = "颜色") - private String name; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java deleted file mode 100644 index 82a3a0c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 属性项 Response VO") -@Data -public class ProductPropertyRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色") - private String name; - - @Schema(description = "备注", example = "颜色") - private String remark; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java deleted file mode 100644 index 69ebf9f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -@Schema(description = "管理后台 - 属性项新增/更新 Request VO") -@Data -public class ProductPropertySaveReqVO { - - @Schema(description = "主键", example = "1") - private Long id; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色") - @NotBlank(message = "名称不能为空") - private String name; - - @Schema(description = "备注", example = "颜色") - private String remark; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java deleted file mode 100644 index ff0c326..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 商品属性值分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductPropertyValuePageReqVO extends PageParam { - - @Schema(description = "属性项的编号", example = "1024") - private String propertyId; - - @Schema(description = "名称", example = "红色") - private String name; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java deleted file mode 100644 index 1eedf9f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 商品属性值 Response VO") -@Data -public class ProductPropertyValueRespVO { - - @Schema(description = "主键", example = "1024") - private Long id; - - @Schema(description = "属性项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "属性项的编号不能为空") - private Long propertyId; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色") - @NotEmpty(message = "名称名字不能为空") - private String name; - - @Schema(description = "备注", example = "颜色") - private String remark; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java deleted file mode 100644 index 1a57c6a..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - 商品属性值新增/更新 Request VO") -@Data -public class ProductPropertyValueSaveReqVO { - - @Schema(description = "主键", example = "1024") - private Long id; - - @Schema(description = "属性项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "属性项的编号不能为空") - private Long propertyId; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色") - @NotEmpty(message = "名称名字不能为空") - private String name; - - @Schema(description = "备注", example = "颜色") - private String remark; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http deleted file mode 100644 index 8b20673..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http +++ /dev/null @@ -1,4 +0,0 @@ -### 获得商品 SPU 明细 -GET {{baseUrl}}/product/spu/get-detail?id=4 -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java deleted file mode 100755 index 0761701..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java +++ /dev/null @@ -1,140 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu; - -import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; -import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; - -@Tag(name = "管理后台 - 商品 SPU") -@RestController -@RequestMapping("/product/spu") -@Validated -public class ProductSpuController { - - @Resource - private ProductSpuService productSpuService; - @Resource - private ProductSkuService productSkuService; - - @PostMapping("/create") - @Operation(summary = "创建商品 SPU") - @PreAuthorize("@ss.hasPermission('product:spu:create')") - public CommonResult createProductSpu(@Valid @RequestBody ProductSpuSaveReqVO createReqVO) { - return success(productSpuService.createSpu(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新商品 SPU") - @PreAuthorize("@ss.hasPermission('product:spu:update')") - public CommonResult updateSpu(@Valid @RequestBody ProductSpuSaveReqVO updateReqVO) { - productSpuService.updateSpu(updateReqVO); - return success(true); - } - - @PutMapping("/update-status") - @Operation(summary = "更新商品 SPU Status") - @PreAuthorize("@ss.hasPermission('product:spu:update')") - public CommonResult updateStatus(@Valid @RequestBody ProductSpuUpdateStatusReqVO updateReqVO) { - productSpuService.updateSpuStatus(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除商品 SPU") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:spu:delete')") - public CommonResult deleteSpu(@RequestParam("id") Long id) { - productSpuService.deleteSpu(id); - return success(true); - } - - @GetMapping("/get-detail") - @Operation(summary = "获得商品 SPU 明细") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult getSpuDetail(@RequestParam("id") Long id) { - // 获得商品 SPU - ProductSpuDO spu = productSpuService.getSpu(id); - if (spu == null) { - return success(null); - } - // 查询商品 SKU - List skus = productSkuService.getSkuListBySpuId(spu.getId()); - return success(ProductSpuConvert.INSTANCE.convert(spu, skus)); - } - - @GetMapping("/list-all-simple") - @Operation(summary = "获得商品 SPU 精简列表") - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getSpuSimpleList() { - List list = productSpuService.getSpuListByStatus(ProductSpuStatusEnum.ENABLE.getStatus()); - // 降序排序后,返回给前端 - list.sort(Comparator.comparing(ProductSpuDO::getSort).reversed()); - return success(BeanUtils.toBean(list, ProductSpuSimpleRespVO.class)); - } - - @GetMapping("/list") - @Operation(summary = "获得商品 SPU 详情列表") - @Parameter(name = "spuIds", description = "spu 编号列表", required = true, example = "[1,2,3]") - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getSpuList(@RequestParam("spuIds") Collection spuIds) { - return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO( - productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds))); - } - - @GetMapping("/page") - @Operation(summary = "获得商品 SPU 分页") - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) { - PageResult pageResult = productSpuService.getSpuPage(pageVO); - return success(BeanUtils.toBean(pageResult, ProductSpuRespVO.class)); - } - - @GetMapping("/get-count") - @Operation(summary = "获得商品 SPU 分页 tab count") - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getSpuCount() { - return success(productSpuService.getTabsCount()); - } - - @GetMapping("/export") - @Operation(summary = "导出商品") - @PreAuthorize("@ss.hasPermission('product:spu:export')") - @ApiAccessLog(operateType = EXPORT) - public void exportSpuList(@Validated ProductSpuPageReqVO reqVO, - HttpServletResponse response) throws IOException { - reqVO.setPageSize(PAGE_SIZE_NONE); - List list = productSpuService.getSpuPage(reqVO).getList(); - // 导出 Excel - ExcelUtils.write(response, "商品列表.xls", "数据", ProductSpuRespVO.class, - BeanUtils.toBean(list, ProductSpuRespVO.class)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java deleted file mode 100755 index f977d33..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - 商品 SKU Response VO") -@Data -public class ProductSkuRespVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") - private String name; - - @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") - private Integer price; - - @Schema(description = "市场价", example = "2999") - private Integer marketPrice; - - @Schema(description = "成本价", example = "19") - private Integer costPrice; - - @Schema(description = "条形码", example = "15156165456") - private String barCode; - - @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - private String picUrl; - - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") - private Integer stock; - - @Schema(description = "商品重量,单位:kg 千克", example = "1.2") - private Double weight; - - @Schema(description = "商品体积,单位:m^3 平米", example = "2.5") - private Double volume; - - @Schema(description = "一级分销的佣金,单位:分", example = "199") - private Integer firstBrokeragePrice; - - @Schema(description = "二级分销的佣金,单位:分", example = "19") - private Integer secondBrokeragePrice; - - @Schema(description = "属性数组") - private List properties; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java deleted file mode 100755 index 43b1a59..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.*; - -import java.util.List; - -@Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO") -@Data -public class ProductSkuSaveReqVO { - - @Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") - @NotEmpty(message = "商品 SKU 名字不能为空") - private String name; - - @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") - @NotNull(message = "销售价格,单位:分不能为空") - private Integer price; - - @Schema(description = "市场价", example = "2999") - private Integer marketPrice; - - @Schema(description = "成本价", example = "19") - private Integer costPrice; - - @Schema(description = "条形码", example = "15156165456") - private String barCode; - - @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - @NotNull(message = "图片地址不能为空") - private String picUrl; - - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") - @NotNull(message = "库存不能为空") - private Integer stock; - - @Schema(description = "商品重量,单位:kg 千克", example = "1.2") - private Double weight; - - @Schema(description = "商品体积,单位:m^3 平米", example = "2.5") - private Double volume; - - @Schema(description = "一级分销的佣金,单位:分", example = "199") - private Integer firstBrokeragePrice; - - @Schema(description = "二级分销的佣金,单位:分", example = "19") - private Integer secondBrokeragePrice; - - @Schema(description = "属性数组") - private List properties; - - @Schema(description = "商品属性") - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class Property { - - @Schema(description = "属性编号", example = "10") - private Long propertyId; - - @Schema(description = "属性名字", example = "颜色") - private String propertyName; - - @Schema(description = "属性值编号", example = "10") - private Long valueId; - - @Schema(description = "属性值名字", example = "红色") - private String valueName; - - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java deleted file mode 100755 index 81cff42..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 商品 SPU 分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductSpuPageReqVO extends PageParam { - - /** - * 出售中商品 - */ - public static final Integer FOR_SALE = 0; - - /** - * 仓库中商品 - */ - public static final Integer IN_WAREHOUSE = 1; - - /** - * 已售空商品 - */ - public static final Integer SOLD_OUT = 2; - - /** - * 警戒库存 - */ - public static final Integer ALERT_STOCK = 3; - - /** - * 商品回收站 - */ - public static final Integer RECYCLE_BIN = 4; - - @Schema(description = "商品名称", example = "清凉小短袖") - private String name; - - @Schema(description = "前端请求的tab类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer tabType; - - @Schema(description = "商品分类编号", example = "1") - private Long categoryId; - - @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java deleted file mode 100755 index fbc7552..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java +++ /dev/null @@ -1,126 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; -import cn.iocoder.yudao.module.product.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - 商品 SPU Response VO") -@Data -@ExcelIgnoreUnannotated -public class ProductSpuRespVO { - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - @ExcelProperty("商品编号") - private Long id; - - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") - @ExcelProperty("商品名称") - private String name; - - @Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗") - @ExcelProperty("关键字") - private String keyword; - - @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介") - @ExcelProperty("商品简介") - private String introduction; - - @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情") - @ExcelProperty("商品详情") - private String description; - - @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("商品分类编号") - private Long categoryId; - - @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("商品品牌编号") - private Long brandId; - - @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - @ExcelProperty("商品封面图") - private String picUrl; - - @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") - private List sliderPicUrls; - - @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("排序字段") - private Integer sort; - - @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty(value = "商品状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.PRODUCT_SPU_STATUS) - private Integer status; - - @Schema(description = "商品创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-05-24 00:00:00") - @ExcelProperty("创建时间") - private LocalDateTime createTime; - - // ========== SKU 相关字段 ========= - - @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @ExcelProperty("规格类型") - private Boolean specType; - - @Schema(description = "商品价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") - @ExcelProperty(value = "商品价格", converter = MoneyConvert.class) - private Integer price; - - @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199") - @ExcelProperty(value = "市场价", converter = MoneyConvert.class) - private Integer marketPrice; - - @Schema(description = "成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19") - @ExcelProperty(value = "成本价", converter = MoneyConvert.class) - private Integer costPrice; - - @Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") - @ExcelProperty("库存") - private Integer stock; - - @Schema(description = "SKU 数组") - private List skus; - - // ========== 物流相关字段 ========= - - @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private List deliveryTypes; - - @Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - @ExcelProperty("物流配置模板编号") - private Long deliveryTemplateId; - - // ========== 营销相关字段 ========= - - @Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - @ExcelProperty("赠送积分") - private Integer giveIntegral; - - @Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @ExcelProperty("分销类型") - private Boolean subCommissionType; - - // ========== 统计相关字段 ========= - - @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") - @ExcelProperty("商品销量") - private Integer salesCount; - - @Schema(description = "虚拟销量", example = "66") - @ExcelProperty("虚拟销量") - private Integer virtualSalesCount; - - @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") - @ExcelProperty("商品点击量") - private Integer browseCount; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java deleted file mode 100755 index b842df0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - 商品 SPU 新增/更新 Request VO") -@Data -public class ProductSpuSaveReqVO { - - @Schema(description = "商品编号", example = "1") - private Long id; - - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") - @NotEmpty(message = "商品名称不能为空") - private String name; - - @Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗") - @NotEmpty(message = "商品关键字不能为空") - private String keyword; - - @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介") - @NotEmpty(message = "商品简介不能为空") - private String introduction; - - @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情") - @NotEmpty(message = "商品详情不能为空") - private String description; - - @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品分类不能为空") - private Long categoryId; - - @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品品牌不能为空") - private Long brandId; - - @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - @NotEmpty(message = "商品封面图不能为空") - private String picUrl; - - @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, - example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") - private List sliderPicUrls; - - @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品排序字段不能为空") - private Integer sort; - - // ========== SKU 相关字段 ========= - - @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "商品规格类型不能为空") - private Boolean specType; - - // ========== 物流相关字段 ========= - - @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotEmpty(message = "配送方式不能为空") - private List deliveryTypes; - - @Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - private Long deliveryTemplateId; - - // ========== 营销相关字段 ========= - - @Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") - @NotNull(message = "商品赠送积分不能为空") - private Integer giveIntegral; - - @Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "商品分销类型不能为空") - private Boolean subCommissionType; - - // ========== 统计相关字段 ========= - - @Schema(description = "虚拟销量", example = "66") - private Integer virtualSalesCount; - - @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") - private Integer salesCount; - - @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") - private Integer browseCount; - - // ========== SKU 相关字段 ========= - - @Schema(description = "SKU 数组") - @Valid - private List skus; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java deleted file mode 100755 index 7d9d0d0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -@Schema(description = "管理后台 - 商品 SPU 精简 Response VO") -@Data -@ToString(callSuper = true) -public class ProductSpuSimpleRespVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "213") - private Long id; - - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") - private String name; - - @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") - private Integer price; - - @Schema(description = "商品市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199") - private Integer marketPrice; - - @Schema(description = "商品成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19") - private Integer costPrice; - - @Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") - private Integer stock; - - // ========== 统计相关字段 ========= - - @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") - private Integer salesCount; - - @Schema(description = "商品虚拟销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20000") - private Integer virtualSalesCount; - - @Schema(description = "商品浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") - private Integer browseCount; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java deleted file mode 100644 index 0bc0158..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.spu.vo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO") -@Data -public class ProductSpuUpdateStatusReqVO{ - - @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品编号不能为空") - private Long id; - - @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品状态不能为空") - @InEnum(ProductSpuStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java deleted file mode 100644 index b8a3605..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.category; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryRespVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -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.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "用户 APP - 商品分类") -@RestController -@RequestMapping("/product/category") -@Validated -public class AppCategoryController { - - @Resource - private ProductCategoryService categoryService; - - @GetMapping("/list") - @Operation(summary = "获得商品分类列表") - @PermitAll - public CommonResult> getProductCategoryList() { - List list = categoryService.getEnableCategoryList(); - list.sort(Comparator.comparing(ProductCategoryDO::getSort)); - return success(BeanUtils.toBean(list, AppCategoryRespVO.class)); - } - - @GetMapping("/list-by-ids") - @Operation(summary = "获得商品分类列表,指定编号") - @Parameter(name = "ids", description = "商品分类编号数组", required = true) - @PermitAll - public CommonResult> getProductCategoryList(@RequestParam("ids") List ids) { - if (CollUtil.isEmpty(ids)) { - return success(Collections.emptyList()); - } - List list = categoryService.getEnableCategoryList(ids); - list.sort(Comparator.comparing(ProductCategoryDO::getSort)); - return success(BeanUtils.toBean(list, AppCategoryRespVO.class)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java deleted file mode 100644 index 1ddec5f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.category.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -@Data -@Schema(description = "用户 APP - 商品分类 Response VO") -public class AppCategoryRespVO { - - @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Long id; - - @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "父分类编号不能为空") - private Long parentId; - - @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具") - @NotBlank(message = "分类名称不能为空") - private String name; - - @Schema(description = "分类图片", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "分类图片不能为空") - private String picUrl; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http deleted file mode 100644 index e69de29..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http +++ /dev/null diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java deleted file mode 100644 index b57d58f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.comment; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.validation.Valid; -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 static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "用户 APP - 商品评价") -@RestController -@RequestMapping("/product/comment") -@Validated -public class AppProductCommentController { - - @Resource - private ProductCommentService productCommentService; - - @GetMapping("/page") - @Operation(summary = "获得商品评价分页") - @PermitAll - public CommonResult> getCommentPage(@Valid AppCommentPageReqVO pageVO) { - // 查询评论分页 - PageResult pageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty(pageResult.getTotal())); - } - - // 拼接返回 - pageResult.getList().forEach(item -> { - if (Boolean.TRUE.equals(item.getAnonymous())) { - item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS); - } - }); - return success(BeanUtils.toBean(pageResult, AppProductCommentRespVO.class)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java deleted file mode 100644 index 854a1c7..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.comment.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "用户 App - 商品评价分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class AppCommentPageReqVO extends PageParam { - - /** - * 好评 - */ - public static final Integer GOOD_COMMENT = 1; - /** - * 中评 - */ - public static final Integer MEDIOCRE_COMMENT = 2; - /** - * 差评 - */ - public static final Integer NEGATIVE_COMMENT = 3; - - @Schema(description = "商品 SPU 编号", example = "29502") - @NotNull(message = "商品 SPU 编号不能为空") - private Long spuId; - - @Schema(description = "app 评论页 tab 类型 (0 全部、1 好评、2 中评、3 差评)", example = "0") - @NotNull(message = "商品 SPU 编号不能为空") - private Integer type; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java deleted file mode 100644 index 31e50c0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java +++ /dev/null @@ -1,99 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.comment.vo; - -import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "用户 App - 商品评价详情 Response VO") -@Data -@ToString(callSuper = true) -public class AppProductCommentRespVO { - - @Schema(description = "评价人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721") - private Long userId; - - @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - private String userNickname; - - @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - private String userAvatar; - - @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24965") - private Long id; - - @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean anonymous; - - @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24428") - private Long orderId; - - @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8233") - private Long orderItemId; - - @Schema(description = "商家是否回复", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean replyStatus; - - @Schema(description = "回复管理员编号", example = "22212") - private Long replyUserId; - - @Schema(description = "商家回复内容", example = "亲,你的好评就是我的动力(*^▽^*)") - private String replyContent; - - @Schema(description = "商家回复时间") - private LocalDateTime replyTime; - - @Schema(description = "追加评价内容", example = "穿了很久都很丝滑诶") - private String additionalContent; - - @Schema(description = "追评评价图片地址数组,以逗号分隔最多上传 9 张", example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") - private List additionalPicUrls; - - @Schema(description = "追加评价时间") - private LocalDateTime additionalTime; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192") - @NotNull(message = "商品 SPU 编号不能为空") - private Long spuId; - - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖") - @NotNull(message = "商品 SPU 名称不能为空") - private String spuName; - - @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192") - @NotNull(message = "商品 SKU 编号不能为空") - private Long skuId; - - @Schema(description = "商品 SKU 属性", requiredMode = Schema.RequiredMode.REQUIRED) - private List skuProperties; - - @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "评分星级 1-5 分不能为空") - private Integer scores; - - @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "描述星级 1-5 分不能为空") - private Integer descriptionScores; - - @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "服务星级 1-5 分不能为空") - private Integer benefitScores; - - @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "哇,真的很丝滑凉快诶,好评") - @NotNull(message = "评论内容不能为空") - private String content; - - @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, - example = "[https://www.iocoder.cn/xx.png]") - @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") - private List picUrls; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java deleted file mode 100644 index fa0903c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java +++ /dev/null @@ -1,81 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.favorite; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoriteReqVO; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoriteRespVO; -import cn.iocoder.yudao.module.product.convert.favorite.ProductFavoriteConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.service.favorite.ProductFavoriteService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "用户 APP - 商品收藏") -@RestController -@RequestMapping("/product/favorite") -public class AppFavoriteController { - - @Resource - private ProductFavoriteService productFavoriteService; - @Resource - private ProductSpuService productSpuService; - - @PostMapping(value = "/create") - @Operation(summary = "添加商品收藏") - public CommonResult createFavorite(@RequestBody @Valid AppFavoriteReqVO reqVO) { - return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId())); - } - - @DeleteMapping(value = "/delete") - @Operation(summary = "取消单个商品收藏") - public CommonResult deleteFavorite(@RequestBody @Valid AppFavoriteReqVO reqVO) { - productFavoriteService.deleteFavorite(getLoginUserId(), reqVO.getSpuId()); - return success(Boolean.TRUE); - } - - @GetMapping(value = "/page") - @Operation(summary = "获得商品收藏分页") - public CommonResult> getFavoritePage(AppFavoritePageReqVO reqVO) { - PageResult favoritePage = productFavoriteService.getFavoritePage(getLoginUserId(), reqVO); - if (CollUtil.isEmpty(favoritePage.getList())) { - return success(PageResult.empty()); - } - - // 得到商品 spu 信息 - List favorites = favoritePage.getList(); - List spuIds = convertList(favorites, ProductFavoriteDO::getSpuId); - List spus = productSpuService.getSpuList(spuIds); - - // 转换 VO 结果 - PageResult pageResult = new PageResult<>(favoritePage.getTotal()); - pageResult.setList(ProductFavoriteConvert.INSTANCE.convertList(favorites, spus)); - return success(pageResult); - } - - @GetMapping(value = "/exits") - @Operation(summary = "检查是否收藏过商品") - public CommonResult isFavoriteExists(AppFavoriteReqVO reqVO) { - ProductFavoriteDO favorite = productFavoriteService.getFavorite(getLoginUserId(), reqVO.getSpuId()); - return success(favorite != null); - } - - @GetMapping(value = "/get-count") - @Operation(summary = "获得商品收藏数量") - public CommonResult getFavoriteCount() { - return success(productFavoriteService.getFavoriteCount(getLoginUserId())); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java deleted file mode 100644 index 2bf2e9d..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.favorite.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import java.util.List; - -@Schema(description = "用户 APP - 商品收藏的批量 Request VO") // 用于收藏、取消收藏、获取收藏 -@Data -public class AppFavoriteBatchReqVO { - - @Schema(description = "商品 SPU 编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") - @NotEmpty(message = "商品 SPU 编号数组不能为空") - private List spuIds; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java deleted file mode 100644 index 2aacc3e..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.favorite.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 App - 商品收藏分页查询 Request VO") -@Data -public class AppFavoritePageReqVO extends PageParam { -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java deleted file mode 100644 index 4d7ba0e..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.favorite.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "用户 APP - 商品收藏的单个 Request VO") // 用于收藏、取消收藏、获取收藏 -@Data -public class AppFavoriteReqVO { - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") - @NotNull(message = "商品 SPU 编号不能为空") - private Long spuId; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java deleted file mode 100644 index 653ab91..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.favorite.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 App - 商品收藏 Response VO") -@Data -public class AppFavoriteRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") - private Long spuId; - - // ========== 商品相关字段 ========== - - @Schema(description = "商品 SPU 名称", example = "赵六") - private String spuName; - - @Schema(description = "商品封面图", example = "https://domain/pic.png") - private String picUrl; - - @Schema(description = "商品单价", example = "100") - private Integer price; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java deleted file mode 100644 index 89c435c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.history; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.history.vo.AppProductBrowseHistoryDeleteReqVO; -import cn.iocoder.yudao.module.product.controller.app.history.vo.AppProductBrowseHistoryPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.history.vo.AppProductBrowseHistoryRespVO; -import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.service.history.ProductBrowseHistoryService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.web.bind.annotation.*; - -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "用户 APP - 商品浏览记录") -@RestController -@RequestMapping("/product/browse-history") -public class AppProductBrowseHistoryController { - - @Resource - private ProductBrowseHistoryService productBrowseHistoryService; - @Resource - private ProductSpuService productSpuService; - - @DeleteMapping(value = "/delete") - @Operation(summary = "删除商品浏览记录") - public CommonResult deleteBrowseHistory(@RequestBody @Valid AppProductBrowseHistoryDeleteReqVO reqVO) { - productBrowseHistoryService.hideUserBrowseHistory(getLoginUserId(), reqVO.getSpuIds()); - return success(Boolean.TRUE); - } - - @DeleteMapping(value = "/clean") - @Operation(summary = "清空商品浏览记录") - public CommonResult deleteBrowseHistory() { - productBrowseHistoryService.hideUserBrowseHistory(getLoginUserId(), null); - return success(Boolean.TRUE); - } - - @GetMapping(value = "/page") - @Operation(summary = "获得商品浏览记录分页") - public CommonResult> getBrowseHistoryPage(AppProductBrowseHistoryPageReqVO reqVO) { - ProductBrowseHistoryPageReqVO pageReqVO = BeanUtils.toBean(reqVO, ProductBrowseHistoryPageReqVO.class) - .setUserId(getLoginUserId()) - .setUserDeleted(false); // 排除用户已删除的(隐藏的) - PageResult pageResult = productBrowseHistoryService.getBrowseHistoryPage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - - // 得到商品 spu 信息 - Set spuIds = convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId); - Map spuMap = convertMap(productSpuService.getSpuList(spuIds), ProductSpuDO::getId); - return success(BeanUtils.toBean(pageResult, AppProductBrowseHistoryRespVO.class, - vo -> Optional.ofNullable(spuMap.get(vo.getSpuId())) - .ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice()) - .setSalesCount(spu.getSalesCount()).setStock(spu.getStock())))); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java deleted file mode 100644 index aada3fa..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.history.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -import java.util.List; - -@Schema(description = "用户 APP - 删除商品浏览记录的 Request VO") -@Data -public class AppProductBrowseHistoryDeleteReqVO { - - @Schema(description = "商品 SPU 编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") - @NotEmpty(message = "商品 SPU 编号数组不能为空") - private List spuIds; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java deleted file mode 100644 index f959fd0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.history.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "用户 APP - 商品浏览记录分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class AppProductBrowseHistoryPageReqVO extends PageParam { - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java deleted file mode 100644 index d5f8e9d..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.history.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 App - 商品浏览记录 Response VO") -@Data -public class AppProductBrowseHistoryRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") - private Long spuId; - - // ========== 商品相关字段 ========== - - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") - private String spuName; - - @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/pic.png") - private String picUrl; - - @Schema(description = "商品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") - private Integer price; - - @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "60") - private Integer salesCount; - - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") - private Integer stock; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java deleted file mode 100644 index 379e851..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位符,无时间作用,避免 package 缩进 - */ -package cn.iocoder.yudao.module.product.controller.app.property; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java deleted file mode 100644 index 6538bea..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位符,无时间作用,避免 package 缩进 - */ -package cn.iocoder.yudao.module.product.controller.app.property.vo.property; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java deleted file mode 100644 index 5cac091..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.property.vo.value; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 App - 商品属性值的明细 Response VO") -@Data -public class AppProductPropertyValueDetailRespVO { - - @Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long propertyId; - - @Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色") - private String propertyName; - - @Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long valueId; - - @Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色") - private String valueName; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http deleted file mode 100644 index 784c464..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http +++ /dev/null @@ -1,18 +0,0 @@ -### 获得订单交易的分页(默认) -GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10 -Authorization: Bearer {{appToken}} -tenant-id: {{appTenantId}} - -### 获得订单交易的分页(价格) -GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10&sortField=price&sortAsc=true -Authorization: Bearer {{appToken}} -tenant-id: {{appTenantId}} - -### 获得订单交易的分页(销售) -GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10&sortField=salesCount&sortAsc=true -Authorization: Bearer {{appToken}} -tenant-id: {{appTenantId}} - -### 获得商品 SPU 明细 -GET {{appApi}}/product/spu/get-detail?id=102 -tenant-id: {{appTenantId}} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java deleted file mode 100644 index 87b0f29..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java +++ /dev/null @@ -1,110 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuRespVO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import cn.iocoder.yudao.module.product.service.history.ProductBrowseHistoryService; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.validation.Valid; -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.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; - -@Tag(name = "用户 APP - 商品 SPU") -@RestController -@RequestMapping("/product/spu") -@Validated -public class AppProductSpuController { - - @Resource - private ProductSpuService productSpuService; - @Resource - private ProductSkuService productSkuService; - @Resource - private ProductBrowseHistoryService productBrowseHistoryService; - - @GetMapping("/list-by-ids") - @Operation(summary = "获得商品 SPU 列表") - @Parameter(name = "ids", description = "编号列表", required = true) - @PermitAll - public CommonResult> getSpuList(@RequestParam("ids") Set ids) { - List list = productSpuService.getSpuList(ids); - if (CollUtil.isEmpty(list)) { - return success(Collections.emptyList()); - } - - // 拼接返回 - list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount())); - List voList = BeanUtils.toBean(list, AppProductSpuRespVO.class); - return success(voList); - } - - @GetMapping("/page") - @Operation(summary = "获得商品 SPU 分页") - @PermitAll - public CommonResult> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) { - PageResult pageResult = productSpuService.getSpuPage(pageVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty(pageResult.getTotal())); - } - - // 拼接返回 - pageResult.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount())); - PageResult voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class); - return success(voPageResult); - } - - @GetMapping("/get-detail") - @Operation(summary = "获得商品 SPU 明细") - @Parameter(name = "id", description = "编号", required = true) - @PermitAll - public CommonResult getSpuDetail(@RequestParam("id") Long id) { - // 获得商品 SPU - ProductSpuDO spu = productSpuService.getSpu(id); - if (spu == null) { - throw exception(SPU_NOT_EXISTS); - } - if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { - throw exception(SPU_NOT_ENABLE, spu.getName()); - } - // 获得商品 SKU - List skus = productSkuService.getSkuListBySpuId(spu.getId()); - - // 增加浏览量 - productSpuService.updateBrowseCount(id, 1); - // 保存浏览记录 - productBrowseHistoryService.createBrowseHistory(getLoginUserId(), id); - - // 拼接返回 - spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()); - AppProductSpuDetailRespVO spuVO = BeanUtils.toBean(spu, AppProductSpuDetailRespVO.class) - .setSkus(BeanUtils.toBean(skus, AppProductSpuDetailRespVO.Sku.class)); - return success(spuVO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java deleted file mode 100644 index 525f224..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu.vo; - -import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -@Schema(description = "用户 App - 商品 SPU 明细 Response VO") -@Data -public class AppProductSpuDetailRespVO { - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - // ========== 基本信息 ========= - - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") - private String name; - - @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个快乐简介") - private String introduction; - - @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是商品描述") - private String description; - - @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long categoryId; - - @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED) - private String picUrl; - - @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED) - private List sliderPicUrls; - - // ========== 营销相关字段 ========= - - // ========== SKU 相关字段 ========= - - @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean specType; - - @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer price; - - @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer marketPrice; - - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private Integer stock; - - /** - * SKU 数组 - */ - private List skus; - - // ========== 统计相关字段 ========= - - @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer salesCount; - - @Schema(description = "用户 App - 商品 SPU 明细的 SKU 信息") - @Data - public static class Sku { - - @Schema(description = "商品 SKU 编号", example = "1") - private Long id; - - /** - * 商品属性数组 - */ - private List properties; - - @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer price; - - @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer marketPrice; - - @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格 - private Integer vipPrice; - - @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") - private String picUrl; - - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer stock; - - @Schema(description = "商品重量", example = "1") // 单位:kg 千克 - private Double weight; - - @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米 - private Double volume; - - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java deleted file mode 100644 index 9e7930e..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu.vo; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.AssertTrue; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import java.util.List; - -@Schema(description = "用户 App - 商品 SPU 分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class AppProductSpuPageReqVO extends PageParam { - - public static final String SORT_FIELD_PRICE = "price"; - public static final String SORT_FIELD_SALES_COUNT = "salesCount"; - public static final String SORT_FIELD_CREATE_TIME = "createTime"; - - @Schema(description = "商品 SPU 编号数组", example = "1,3,5") - private List ids; - - @Schema(description = "分类编号", example = "1") - private Long categoryId; - - @Schema(description = "分类编号数组", example = "1,2,3") - private List categoryIds; - - @Schema(description = "关键字", example = "好看") - private String keyword; - - @Schema(description = "排序字段", example = "price") // 参见 AppProductSpuPageReqVO.SORT_FIELD_XXX 常量 - private String sortField; - - @Schema(description = "排序方式", example = "true") - private Boolean sortAsc; - - @AssertTrue(message = "排序字段不合法") - @JsonIgnore - public boolean isSortFieldValid() { - if (StrUtil.isEmpty(sortField)) { - return true; - } - return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java deleted file mode 100644 index db606cc..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -@Schema(description = "用户 App - 商品 SPU Response VO") -@Data -public class AppProductSpuRespVO { - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") - private String name; - - @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介") - private String introduction; - - @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED) - private Long categoryId; - - @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED) - private String picUrl; - - @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED) - private List sliderPicUrls; - - // ========== SKU 相关字段 ========= - - @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean specType; - - @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer price; - - @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer marketPrice; - - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private Integer stock; - - // ========== 营销相关字段 ========= - - // ========== 统计相关字段 ========= - - @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer salesCount; - - // ========== 物流相关字段 ========= - - @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private List deliveryTypes; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java deleted file mode 100644 index e6c72fb..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.product.convert.brand; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandRespVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandSimpleRespVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 品牌 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface ProductBrandConvert { - - ProductBrandConvert INSTANCE = Mappers.getMapper(ProductBrandConvert.class); - - ProductBrandDO convert(ProductBrandCreateReqVO bean); - - ProductBrandDO convert(ProductBrandUpdateReqVO bean); - - ProductBrandRespVO convert(ProductBrandDO bean); - - List convertList1(List list); - - List convertList(List list); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java deleted file mode 100644 index 7a3a3c0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.iocoder.yudao.module.product.convert.comment; - -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.math.BigDecimal; -import java.math.RoundingMode; - -/** - * 商品评价 Convert - * - * @author wangzhs - */ -@Mapper -public interface ProductCommentConvert { - - ProductCommentConvert INSTANCE = Mappers.getMapper(ProductCommentConvert.class); - - default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, - ProductSpuDO spu, ProductSkuDO sku, MemberUserRespDTO user) { - ProductCommentDO comment = BeanUtils.toBean(createReqDTO, ProductCommentDO.class) - .setScores(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores())); - if (user != null) { - comment.setUserId(user.getId()).setUserNickname(user.getNickname()).setUserAvatar(user.getAvatar()); - } - if (spu != null) { - comment.setSpuId(spu.getId()).setSpuName(spu.getName()); - } - if (sku != null) { - comment.setSkuPicUrl(sku.getPicUrl()).setSkuProperties(sku.getProperties()); - } - return comment; - } - - default ProductCommentDO convert(ProductCommentCreateReqVO createReq, ProductSpuDO spu, ProductSkuDO sku) { - ProductCommentDO comment = BeanUtils.toBean(createReq, ProductCommentDO.class) - .setVisible(true).setUserId(0L).setAnonymous(false) - .setScores(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores())); - if (spu != null) { - comment.setSpuId(spu.getId()).setSpuName(spu.getName()); - } - if (sku != null) { - comment.setSkuPicUrl(sku.getPicUrl()).setSkuProperties(sku.getProperties()); - } - return comment; - } - - default Integer convertScores(Integer descriptionScores, Integer benefitScores) { - // 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2 - BigDecimal sumScore = new BigDecimal(descriptionScores + benefitScores); - BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN); - return divide.intValue(); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java deleted file mode 100644 index 7b419b6..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.product.convert.favorite; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoriteRespVO; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoriteRespVO; -import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -@Mapper -public interface ProductFavoriteConvert { - - ProductFavoriteConvert INSTANCE = Mappers.getMapper(ProductFavoriteConvert.class); - - ProductFavoriteDO convert(Long userId, Long spuId); - - @Mapping(target = "id", source = "favorite.id") - @Mapping(target = "spuName", source = "spu.name") - AppFavoriteRespVO convert(ProductSpuDO spu, ProductFavoriteDO favorite); - - default List convertList(List favorites, List spus) { - List resultList = new ArrayList<>(favorites.size()); - Map spuMap = convertMap(spus, ProductSpuDO::getId); - for (ProductFavoriteDO favorite : favorites) { - ProductSpuDO spuDO = spuMap.get(favorite.getSpuId()); - resultList.add(convert(spuDO, favorite)); - } - return resultList; - } - - default PageResult convertPage(PageResult pageResult, List spuList) { - Map spuMap = convertMap(spuList, ProductSpuDO::getId); - List voList = CollectionUtils.convertList(pageResult.getList(), favorite -> { - ProductSpuDO spu = spuMap.get(favorite.getSpuId()); - return convert02(spu, favorite); - }); - return new PageResult<>(voList, pageResult.getTotal()); - } - @Mapping(target = "id", source = "favorite.id") - @Mapping(target = "userId", source = "favorite.userId") - @Mapping(target = "spuId", source = "favorite.spuId") - @Mapping(target = "createTime", source = "favorite.createTime") - ProductFavoriteRespVO convert02(ProductSpuDO spu, ProductFavoriteDO favorite); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java deleted file mode 100755 index 492f483..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.product.convert.sku; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.*; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -/** - * 商品 SKU Convert - * - * @author 芋道源码 - */ -@Mapper -public interface ProductSkuConvert { - - ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class); - - /** - * 获得 SPU 的库存变化 Map - * - * @param items SKU 库存变化 - * @param skus SKU 列表 - * @return SPU 的库存变化 Map - */ - default Map convertSpuStockMap(List items, - List skus) { - Map skuIdAndSpuIdMap = convertMap(skus, ProductSkuDO::getId, ProductSkuDO::getSpuId); // SKU 与 SKU 编号的 Map 关系 - Map spuIdAndStockMap = new HashMap<>(); // SPU 的库存变化 Map 关系 - items.forEach(item -> { - Long spuId = skuIdAndSpuIdMap.get(item.getId()); - if (spuId == null) { - return; - } - Integer stock = spuIdAndStockMap.getOrDefault(spuId, 0) + item.getIncrCount(); - spuIdAndStockMap.put(spuId, stock); - }); - return spuIdAndStockMap; - } - - default String buildPropertyKey(ProductSkuDO bean) { - if (CollUtil.isEmpty(bean.getProperties())) { - return StrUtil.EMPTY; - } - List properties = new ArrayList<>(bean.getProperties()); - properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId)); - return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining()); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java deleted file mode 100755 index 3644342..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.product.convert.spu; - -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuRespVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; - -/** - * 商品 SPU Convert - * - * @author 芋道源码 - */ -@Mapper -public interface ProductSpuConvert { - - ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class); - - ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean); - - default ProductSpuRespVO convert(ProductSpuDO spu, List skus) { - ProductSpuRespVO spuVO = BeanUtils.toBean(spu, ProductSpuRespVO.class); - spuVO.setSkus(BeanUtils.toBean(skus, ProductSkuRespVO.class)); - return spuVO; - } - - default List convertForSpuDetailRespListVO(List spus, List skus) { - Map> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId); - return CollectionUtils.convertList(spus, spu -> convert(spu, skuMultiMap.get(spu.getId()))); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java deleted file mode 100644 index 7265440..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.brand; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 商品品牌 DO - * - * @author 芋道源码 - */ -@TableName("product_brand") -@KeySequence("product_brand_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductBrandDO extends BaseDO { - - /** - * 品牌编号 - */ - @TableId - private Long id; - /** - * 品牌名称 - */ - private String name; - /** - * 品牌图片 - */ - private String picUrl; - /** - * 品牌排序 - */ - private Integer sort; - /** - * 品牌描述 - */ - private String description; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java deleted file mode 100644 index 44c6c09..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.category; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 商品分类 DO - * - * @author 芋道源码 - */ -@TableName("product_category") -@KeySequence("product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductCategoryDO extends BaseDO { - - /** - * 父分类编号 - 根分类 - */ - public static final Long PARENT_ID_NULL = 0L; - /** - * 限定分类层级 - */ - public static final int CATEGORY_LEVEL = 2; - - /** - * 分类编号 - */ - @TableId - private Long id; - /** - * 父分类编号 - */ - private Long parentId; - /** - * 分类名称 - */ - private String name; - /** - * 移动端分类图 - * - * 建议 180*180 分辨率 - */ - private String picUrl; - /** - * 分类排序 - */ - private Integer sort; - /** - * 开启状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java deleted file mode 100644 index 86d70f0..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java +++ /dev/null @@ -1,159 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.comment; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.*; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 商品评论 DO - * - * @author 芋道源码 - */ -@TableName(value = "product_comment", autoResultMap = true) -@KeySequence("product_comment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductCommentDO extends BaseDO { - - /** - * 默认匿名昵称 - */ - public static final String NICKNAME_ANONYMOUS = "匿名用户"; - - /** - * 评论编号,主键自增 - */ - @TableId - private Long id; - - /** - * 评价人的用户编号 - * - * 关联 MemberUserDO 的 id 编号 - */ - private Long userId; - /** - * 评价人名称 - */ - private String userNickname; - /** - * 评价人头像 - */ - private String userAvatar; - /** - * 是否匿名 - */ - private Boolean anonymous; - - /** - * 交易订单编号 - * - * 关联 TradeOrderDO 的 id 编号 - */ - private Long orderId; - /** - * 交易订单项编号 - * - * 关联 TradeOrderItemDO 的 id 编号 - */ - private Long orderItemId; - - /** - * 商品 SPU 编号 - * - * 关联 {@link ProductSpuDO#getId()} - */ - private Long spuId; - /** - * 商品 SPU 名称 - * - * 关联 {@link ProductSpuDO#getName()} - */ - private String spuName; - /** - * 商品 SKU 编号 - * - * 关联 {@link ProductSkuDO#getId()} - */ - private Long skuId; - /** - * 商品 SKU 图片地址 - * - * 关联 {@link ProductSkuDO#getPicUrl()} - */ - private String skuPicUrl; - /** - * 属性数组,JSON 格式 - * - * 关联 {@link ProductSkuDO#getProperties()} - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List skuProperties; - - /** - * 是否可见 - * - * true:显示 - * false:隐藏 - */ - private Boolean visible; - /** - * 评分星级 - * - * 1-5 分 - */ - private Integer scores; - /** - * 描述星级 - * - * 1-5 星 - */ - private Integer descriptionScores; - /** - * 服务星级 - * - * 1-5 星 - */ - private Integer benefitScores; - /** - * 评论内容 - */ - private String content; - /** - * 评论图片地址数组 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List picUrls; - - /** - * 商家是否回复 - */ - private Boolean replyStatus; - /** - * 回复管理员编号 - * 关联 AdminUserDO 的 id 编号 - */ - private Long replyUserId; - /** - * 商家回复内容 - */ - private String replyContent; - /** - * 商家回复时间 - */ - private LocalDateTime replyTime; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java deleted file mode 100644 index 6e00eaa..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.favorite; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 商品收藏 DO - * - * @author 芋道源码 - */ -@TableName("product_favorite") -@KeySequence("product_favorite_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductFavoriteDO extends BaseDO { - - /** - * 编号,主键自增 - */ - @TableId - private Long id; - /** - * 用户编号 - * - * 关联 MemberUserDO 的 id 编号 - */ - private Long userId; - /** - * 商品 SPU 编号 - * - * 关联 {@link ProductSpuDO#getId()} - */ - private Long spuId; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java deleted file mode 100644 index 472574b..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.history; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 商品浏览记录 DO - * - * @author owen - */ -@TableName("product_browse_history") -@KeySequence("product_browse_history_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductBrowseHistoryDO extends BaseDO { - - /** - * 记录编号 - */ - @TableId - private Long id; - /** - * 商品 SPU 编号 - */ - private Long spuId; - /** - * 用户编号 - */ - private Long userId; - /** - * 用户是否删除 - */ - private Boolean userDeleted; - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java deleted file mode 100644 index d23a828..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.property; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 商品属性项 DO - * - * @author 芋道源码 - */ -@TableName("product_property") -@KeySequence("product_property_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductPropertyDO extends BaseDO { - - /** - * SPU 单规格时,默认属性 id - */ - public static final Long ID_DEFAULT = 0L; - /** - * SPU 单规格时,默认属性名字 - */ - public static final String NAME_DEFAULT = "默认"; - - /** - * 主键 - */ - @TableId - private Long id; - /** - * 名称 - */ - private String name; - /** - * 备注 - */ - private String remark; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java deleted file mode 100644 index cefa2d9..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.property; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - - -/** - * 商品属性值 DO - * - * @author 芋道源码 - */ -@TableName("product_property_value") -@KeySequence("product_property_value_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductPropertyValueDO extends BaseDO { - - /** - * SPU 单规格时,默认属性值 id - */ - public static final Long ID_DEFAULT = 0L; - /** - * SPU 单规格时,默认属性值名字 - */ - public static final String NAME_DEFAULT = "默认"; - - /** - * 主键 - */ - @TableId - private Long id; - /** - * 属性项的编号 - * - * 关联 {@link ProductPropertyDO#getId()} - */ - private Long propertyId; - /** - * 名称 - */ - private String name; - /** - * 备注 - * - */ - private String remark; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java deleted file mode 100755 index 267756a..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java +++ /dev/null @@ -1,134 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.sku; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.*; - -import java.util.List; - -/** - * 商品 SKU DO - * - * @author 芋道源码 - */ -@TableName(value = "product_sku", autoResultMap = true) -@KeySequence("product_sku_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductSkuDO extends BaseDO { - - /** - * 商品 SKU 编号,自增 - */ - @TableId - private Long id; - /** - * SPU 编号 - * - * 关联 {@link ProductSpuDO#getId()} - */ - private Long spuId; - /** - * 属性数组,JSON 格式 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List properties; - /** - * 商品价格,单位:分 - */ - private Integer price; - /** - * 市场价,单位:分 - */ - private Integer marketPrice; - /** - * 成本价,单位:分 - */ - private Integer costPrice; - /** - * 商品条码 - */ - private String barCode; - /** - * 图片地址 - */ - private String picUrl; - /** - * 库存 - */ - private Integer stock; - /** - * 商品重量,单位:kg 千克 - */ - private Double weight; - /** - * 商品体积,单位:m^3 平米 - */ - private Double volume; - - /** - * 一级分销的佣金,单位:分 - */ - private Integer firstBrokeragePrice; - /** - * 二级分销的佣金,单位:分 - */ - private Integer secondBrokeragePrice; - - // ========== 营销相关字段 ========= - - // ========== 统计相关字段 ========= - /** - * 商品销量 - */ - private Integer salesCount; - - /** - * 商品属性 - */ - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class Property { - - /** - * 属性编号 - * 关联 {@link ProductPropertyDO#getId()} - */ - private Long propertyId; - /** - * 属性名字 - * 冗余 {@link ProductPropertyDO#getName()} - * - * 注意:每次属性名字发生变化时,需要更新该冗余 - */ - private String propertyName; - - /** - * 属性值编号 - * 关联 {@link ProductPropertyValueDO#getId()} - */ - private Long valueId; - /** - * 属性值名字 - * 冗余 {@link ProductPropertyValueDO#getName()} - * - * 注意:每次属性值名字发生变化时,需要更新该冗余 - */ - private String valueName; - - } - -} - diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java deleted file mode 100755 index d2b5195..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java +++ /dev/null @@ -1,171 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.dataobject.spu; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.*; - -import java.util.List; - -/** - * 商品 SPU DO - * - * @author 芋道源码 - */ -@TableName(value = "product_spu", autoResultMap = true) -@KeySequence("product_spu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ProductSpuDO extends BaseDO { - - /** - * 商品 SPU 编号,自增 - */ - @TableId - private Long id; - - // ========== 基本信息 ========= - - /** - * 商品名称 - */ - private String name; - /** - * 关键字 - */ - private String keyword; - /** - * 商品简介 - */ - private String introduction; - /** - * 商品详情 - */ - private String description; - - /** - * 商品分类编号 - * - * 关联 {@link ProductCategoryDO#getId()} - */ - private Long categoryId; - /** - * 商品品牌编号 - * - * 关联 {@link ProductBrandDO#getId()} - */ - private Long brandId; - /** - * 商品封面图 - */ - private String picUrl; - /** - * 商品轮播图 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List sliderPicUrls; - - /** - * 排序字段 - */ - private Integer sort; - /** - * 商品状态 - * - * 枚举 {@link ProductSpuStatusEnum} - */ - private Integer status; - - // ========== SKU 相关字段 ========= - - /** - * 规格类型 - * - * false - 单规格 - * true - 多规格 - */ - private Boolean specType; - /** - * 商品价格,单位使用:分 - * - * 基于其对应的 {@link ProductSkuDO#getPrice()} sku单价最低的商品的 - */ - private Integer price; - /** - * 市场价,单位使用:分 - * - * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} sku单价最低的商品的 - */ - private Integer marketPrice; - /** - * 成本价,单位使用:分 - * - * 基于其对应的 {@link ProductSkuDO#getCostPrice()} sku单价最低的商品的 - */ - private Integer costPrice; - /** - * 库存 - * - * 基于其对应的 {@link ProductSkuDO#getStock()} 求和 - */ - private Integer stock; - - // ========== 物流相关字段 ========= - - /** - * 配送方式数组 - * - * 对应 DeliveryTypeEnum 枚举 - */ - @TableField(typeHandler = IntegerListTypeHandler.class) - private List deliveryTypes; - /** - * 物流配置模板编号 - * - * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 - */ - private Long deliveryTemplateId; - - // ========== 营销相关字段 ========= - - /** - * 赠送积分 - */ - private Integer giveIntegral; - - // TODO @puhui999:字段估计要改成 brokerageType - /** - * 分销类型 - * - * false - 默认 - * true - 自行设置 - */ - private Boolean subCommissionType; - - // ========== 统计相关字段 ========= - - /** - * 商品销量 - */ - private Integer salesCount; - /** - * 虚拟销量 - */ - private Integer virtualSalesCount; - /** - * 浏览量 - */ - private Integer browseCount; -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java deleted file mode 100644 index b2c4bd5..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.brand; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface ProductBrandMapper extends BaseMapperX { - - default PageResult selectPage(ProductBrandPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(ProductBrandDO::getName, reqVO.getName()) - .eqIfPresent(ProductBrandDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(ProductBrandDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductBrandDO::getId)); - } - - - default List selectList(ProductBrandListReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(ProductBrandDO::getName, reqVO.getName())); - } - - default ProductBrandDO selectByName(String name) { - return selectOne(ProductBrandDO::getName, name); - } - - default List selectListByStatus(Integer status) { - return selectList(ProductBrandDO::getStatus, status); - } -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java deleted file mode 100644 index 4c212de..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.category; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -/** - * 商品分类 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface ProductCategoryMapper extends BaseMapperX { - - default List selectList(ProductCategoryListReqVO listReqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(ProductCategoryDO::getName, listReqVO.getName()) - .eqIfPresent(ProductCategoryDO::getParentId, listReqVO.getParentId()) - .inIfPresent(ProductCategoryDO::getId, listReqVO.getParentIds()) - .eqIfPresent(ProductCategoryDO::getStatus, listReqVO.getStatus()) - .orderByDesc(ProductCategoryDO::getId)); - } - - default Long selectCountByParentId(Long parentId) { - return selectCount(ProductCategoryDO::getParentId, parentId); - } - - default List selectListByStatus(Integer status) { - return selectList(ProductCategoryDO::getStatus, status); - } - - default List selectListByIdAndStatus(Collection ids, Integer status) { - return selectList(new LambdaQueryWrapperX() - .in(ProductCategoryDO::getId, ids) - .eq(ProductCategoryDO::getStatus, status)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java deleted file mode 100644 index 47421d3..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java +++ /dev/null @@ -1,60 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.comment; - -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface ProductCommentMapper extends BaseMapperX { - - default PageResult selectPage(ProductCommentPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(ProductCommentDO::getUserNickname, reqVO.getUserNickname()) - .eqIfPresent(ProductCommentDO::getOrderId, reqVO.getOrderId()) - .eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId()) - .eqIfPresent(ProductCommentDO::getScores, reqVO.getScores()) - .eqIfPresent(ProductCommentDO::getReplyStatus, reqVO.getReplyStatus()) - .betweenIfPresent(ProductCommentDO::getCreateTime, reqVO.getCreateTime()) - .likeIfPresent(ProductCommentDO::getSpuName, reqVO.getSpuName()) - .orderByDesc(ProductCommentDO::getId)); - } - - static void appendTabQuery(LambdaQueryWrapperX queryWrapper, Integer type) { - // 构建好评查询语句:好评计算 总评 >= 4 - if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) { - queryWrapper.ge(ProductCommentDO::getScores, 4); - } - // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4 - if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) { - queryWrapper.ge(ProductCommentDO::getScores, 3); - queryWrapper.lt(ProductCommentDO::getScores, 4); - } - // 构建差评查询语句:差评计算 总评 < 3 - if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) { - queryWrapper.lt(ProductCommentDO::getScores, 3); - } - } - - default PageResult selectPage(AppCommentPageReqVO reqVO, Boolean visible) { - LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX() - .eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId()) - .eqIfPresent(ProductCommentDO::getVisible, visible); - // 构建评价查询语句 - appendTabQuery(queryWrapper, reqVO.getType()); - // 按评价时间排序最新的显示在前面 - queryWrapper.orderByDesc(ProductCommentDO::getCreateTime); - return selectPage(reqVO, queryWrapper); - } - - default ProductCommentDO selectByUserIdAndOrderItemId(Long userId, Long orderItemId) { - return selectOne(new LambdaQueryWrapperX() - .eq(ProductCommentDO::getUserId, userId) - .eq(ProductCommentDO::getOrderItemId, orderItemId)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java deleted file mode 100644 index a681d42..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.favorite; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface ProductFavoriteMapper extends BaseMapperX { - - default ProductFavoriteDO selectByUserIdAndSpuId(Long userId, Long spuId) { - return selectOne(ProductFavoriteDO::getUserId, userId, - ProductFavoriteDO::getSpuId, spuId); - } - - default PageResult selectPageByUserAndType(Long userId, AppFavoritePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapper() - .eq(ProductFavoriteDO::getUserId, userId) - .orderByDesc(ProductFavoriteDO::getId)); - } - - default PageResult selectPageByUserId(ProductFavoritePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(ProductFavoriteDO::getUserId, reqVO.getUserId()) - .orderByDesc(ProductFavoriteDO::getId)); - } - - default Long selectCountByUserId(Long userId) { - return selectCount(ProductFavoriteDO::getUserId, userId); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java deleted file mode 100644 index 8ea2ca5..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.history; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; - -/** - * 商品浏览记录 Mapper - * - * @author owen - */ -@Mapper -public interface ProductBrowseHistoryMapper extends BaseMapperX { - - default ProductBrowseHistoryDO selectByUserIdAndSpuId(Long userId, Long spuId) { - return selectFirstOne(ProductBrowseHistoryDO::getUserId, userId, - ProductBrowseHistoryDO::getSpuId, spuId); - } - - default PageResult selectPage(ProductBrowseHistoryPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(ProductBrowseHistoryDO::getUserId, reqVO.getUserId()) - .eqIfPresent(ProductBrowseHistoryDO::getUserDeleted, reqVO.getUserDeleted()) - .eqIfPresent(ProductBrowseHistoryDO::getSpuId, reqVO.getSpuId()) - .betweenIfPresent(ProductBrowseHistoryDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductBrowseHistoryDO::getId)); - } - - default void updateUserDeletedByUserId(Long userId, Collection spuIds, Boolean userDeleted) { - update(new LambdaUpdateWrapper() - .eq(ProductBrowseHistoryDO::getUserId, userId) - .in(CollUtil.isNotEmpty(spuIds), ProductBrowseHistoryDO::getSpuId, spuIds) - .set(ProductBrowseHistoryDO::getUserDeleted, userDeleted)); - } - - default Page selectPageByUserIdOrderByCreateTimeAsc(Long userId, Integer pageNo, Integer pageSize) { - Page page = Page.of(pageNo, pageSize); - return selectPage(page, new LambdaQueryWrapperX() - .eqIfPresent(ProductBrowseHistoryDO::getUserId, userId) - .orderByAsc(ProductBrowseHistoryDO::getCreateTime)); - } - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java deleted file mode 100644 index 8a55eaf..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.property; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface ProductPropertyMapper extends BaseMapperX { - - default PageResult selectPage(ProductPropertyPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(ProductPropertyDO::getName, reqVO.getName()) - .betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductPropertyDO::getId)); - } - - default ProductPropertyDO selectByName(String name) { - return selectOne(ProductPropertyDO::getName, name); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java deleted file mode 100644 index 402df51..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.property; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface ProductPropertyValueMapper extends BaseMapperX { - - default List selectListByPropertyId(Collection propertyIds) { - return selectList(new LambdaQueryWrapperX() - .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds)); - } - - default ProductPropertyValueDO selectByName(Long propertyId, String name) { - return selectOne(new LambdaQueryWrapperX() - .eq(ProductPropertyValueDO::getPropertyId, propertyId) - .eq(ProductPropertyValueDO::getName, name)); - } - - default void deleteByPropertyId(Long propertyId) { - delete(new LambdaQueryWrapperX() - .eq(ProductPropertyValueDO::getPropertyId, propertyId)); - } - - default PageResult selectPage(ProductPropertyValuePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId()) - .likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName()) - .orderByDesc(ProductPropertyValueDO::getId)); - } - - default Integer selectCountByPropertyId(Long propertyId) { - return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue(); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java deleted file mode 100755 index da920a5..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.sku; - -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface ProductSkuMapper extends BaseMapperX { - - @Select("SELECT * FROM product_sku WHERE id = #{id}") - ProductSkuDO selectByIdIncludeDeleted(@Param("id") Long id); - - default List selectListBySpuId(Long spuId) { - return selectList(ProductSkuDO::getSpuId, spuId); - } - - default List selectListBySpuId(Collection spuIds) { - return selectList(ProductSkuDO::getSpuId, spuIds); - } - - default void deleteBySpuId(Long spuId) { - delete(new LambdaQueryWrapperX().eq(ProductSkuDO::getSpuId, spuId)); - } - - /** - * 更新 SKU 库存(增加)、销量(减少) - * - * @param id 编号 - * @param incrCount 增加库存(正数) - */ - default void updateStockIncr(Long id, Integer incrCount) { - Assert.isTrue(incrCount > 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" stock = stock + " + incrCount - + ", sales_count = sales_count - " + incrCount) - .eq(ProductSkuDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新 SKU 库存(减少)、销量(增加) - * - * @param id 编号 - * @param incrCount 减少库存(负数) - * @return 更新条数 - */ - default int updateStockDecr(Long id, Integer incrCount) { - Assert.isTrue(incrCount < 0); - incrCount = - incrCount; // 取正 - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() - .setSql(" stock = stock - " + incrCount - + ", sales_count = sales_count + " + incrCount) - .eq(ProductSkuDO::getId, id) - .ge(ProductSkuDO::getStock, incrCount); - return update(null, updateWrapper); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java deleted file mode 100755 index fc00ae7..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java +++ /dev/null @@ -1,154 +0,0 @@ -package cn.iocoder.yudao.module.product.dal.mysql.spu; - -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.enums.ProductConstants; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.Objects; -import java.util.Set; - -@Mapper -public interface ProductSpuMapper extends BaseMapperX { - - @Select("SELECT * FROM product_spu WHERE id = #{id}") - ProductSpuDO selectByIdIncludeDeleted(@Param("id") Long id); - - /** - * 获取商品 SPU 分页列表数据 - * - * @param reqVO 分页请求参数 - * @return 商品 SPU 分页列表数据 - */ - default PageResult selectPage(ProductSpuPageReqVO reqVO) { - Integer tabType = reqVO.getTabType(); - LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX() - .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) - .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) - .betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ProductSpuDO::getSort) - .orderByDesc(ProductSpuDO::getId); - appendTabQuery(tabType, queryWrapper); - return selectPage(reqVO, queryWrapper); - } - - /** - * 查询触发警戒库存的 SPU 数量 - * - * @return 触发警戒库存的 SPU 数量 - */ - default Long selectCount() { - LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX<>(); - // 库存小于等于警戒库存 - queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK) - // 如果库存触发警戒库存且状态为回收站的话则不计入触发警戒库存的个数 - .notIn(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()); - return selectCount(queryWrapper); - } - - /** - * 获得商品 SPU 分页,提供给用户 App 使用 - */ - default PageResult selectPage(AppProductSpuPageReqVO pageReqVO, Set categoryIds) { - LambdaQueryWrapperX query = new LambdaQueryWrapperX() - // 关键字匹配,目前只匹配商品名 - .likeIfPresent(ProductSpuDO::getName, pageReqVO.getKeyword()) - // 分类 - .inIfPresent(ProductSpuDO::getCategoryId, categoryIds); - // 上架状态 且有库存 - query.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()); - - // 排序逻辑 - if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) { - query.last(String.format(" ORDER BY (sales_count + virtual_sales_count) %s, sort DESC, id DESC", - pageReqVO.getSortAsc() ? "ASC" : "DESC")); - } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) { - query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getPrice) - .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); - } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_CREATE_TIME)) { - query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getCreateTime) - .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); - } else { - query.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); - } - return selectPage(pageReqVO, query); - } - - /** - * 更新商品 SPU 库存 - * - * @param id 商品 SPU 编号 - * @param incrCount 增加的库存数量 - */ - default void updateStock(Long id, Integer incrCount) { - // 拼接 SQL - if (incrCount == 0) { - return; - } - String sql; - if (incrCount > 0) { - sql = " stock = stock + " + incrCount + ", sales_count = sales_count - " + incrCount; - } else { - sql = " stock = stock - " + Math.abs(incrCount) + ", sales_count = sales_count + " + Math.abs(incrCount); - } - // 执行更新 - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() - .setSql(sql) - .eq(ProductSpuDO::getId, id); - update(null, updateWrapper); - } - - /** - * 添加后台 Tab 选项的查询条件 - * - * @param tabType 标签类型 - * @param query 查询条件 - */ - static void appendTabQuery(Integer tabType, LambdaQueryWrapperX query) { - // 出售中商品 - if (ObjectUtil.equals(ProductSpuPageReqVO.FOR_SALE, tabType)) { - query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()); - } - // 仓储中商品 - if (ObjectUtil.equals(ProductSpuPageReqVO.IN_WAREHOUSE, tabType)) { - query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()); - } - // 已售空商品 - if (ObjectUtil.equals(ProductSpuPageReqVO.SOLD_OUT, tabType)) { - query.eqIfPresent(ProductSpuDO::getStock, 0); - } - // 警戒库存 - if (ObjectUtil.equals(ProductSpuPageReqVO.ALERT_STOCK, tabType)) { - query.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK) - // 如果库存触发警戒库存且状态为回收站的话则不在警戒库存列表展示 - .notIn(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()); - } - // 回收站 - if (ObjectUtil.equals(ProductSpuPageReqVO.RECYCLE_BIN, tabType)) { - query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()); - } - } - - /** - * 更新商品 SPU 浏览量 - * - * @param id 商品 SPU 编号 - * @param incrCount 增加的数量 - */ - default void updateBrowseCount(Long id, int incrCount) { - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() - .setSql(" browse_count = browse_count +" + incrCount) - .eq(ProductSpuDO::getId, id); - update(null, updateWrapper); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java deleted file mode 100644 index d2e1c93..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 属于 product 模块的 framework 封装 - * - * @author 芋道源码 - */ -package cn.iocoder.yudao.module.product.framework; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java deleted file mode 100644 index 7da1799..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.product.framework.web.config; - -import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; -import org.springdoc.core.models.GroupedOpenApi; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * product 模块的 web 组件的 Configuration - * - * @author 芋道源码 - */ -@Configuration(proxyBeanMethods = false) -public class ProductWebConfiguration { - - /** - * product 模块的 API 分组 - */ - @Bean - public GroupedOpenApi productGroupedOpenApi() { - return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("product"); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java deleted file mode 100644 index f4adb2d..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * product 模块的 web 配置 - */ -package cn.iocoder.yudao.module.product.framework.web; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java deleted file mode 100644 index e329429..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * product 模块,主要实现交易相关功能 - * 例如:订单、退款、购物车等功能。 - * - * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突 - * 2. DataObject 表名:以 product_ 开头,方便在数据库中区分 - */ -package cn.iocoder.yudao.module.product; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java deleted file mode 100644 index a7ed6b4..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.product.service.brand; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; - -import jakarta.validation.Valid; -import java.util.Collection; -import java.util.List; - -/** - * 商品品牌 Service 接口 - * - * @author 芋道源码 - */ -public interface ProductBrandService { - - /** - * 创建品牌 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createBrand(@Valid ProductBrandCreateReqVO createReqVO); - - /** - * 更新品牌 - * - * @param updateReqVO 更新信息 - */ - void updateBrand(@Valid ProductBrandUpdateReqVO updateReqVO); - - /** - * 删除品牌 - * - * @param id 编号 - */ - void deleteBrand(Long id); - - /** - * 获得品牌 - * - * @param id 编号 - * @return 品牌 - */ - ProductBrandDO getBrand(Long id); - - /** - * 获得品牌列表 - * - * @param ids 编号 - * @return 品牌列表 - */ - List getBrandList(Collection ids); - - /** - * 获得品牌列表 - * - * @param listReqVO 请求参数 - * @return 品牌列表 - */ - List getBrandList(ProductBrandListReqVO listReqVO); - - /** - * 验证选择的商品分类是否合法 - * - * @param id 分类编号 - */ - void validateProductBrand(Long id); - - /** - * 获得品牌分页 - * - * @param pageReqVO 分页查询 - * @return 品牌分页 - */ - PageResult getBrandPage(ProductBrandPageReqVO pageReqVO); - - /** - * 获取指定状态的品牌列表 - * - * @param status 状态 - * @return 返回品牌列表 - */ - List getBrandListByStatus(Integer status); -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java deleted file mode 100644 index a3fc918..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -package cn.iocoder.yudao.module.product.service.brand; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; -import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper; -import com.google.common.annotations.VisibleForTesting; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import jakarta.annotation.Resource; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 品牌 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class ProductBrandServiceImpl implements ProductBrandService { - - @Resource - private ProductBrandMapper brandMapper; - - @Override - public Long createBrand(ProductBrandCreateReqVO createReqVO) { - // 校验 - validateBrandNameUnique(null, createReqVO.getName()); - - // 插入 - ProductBrandDO brand = ProductBrandConvert.INSTANCE.convert(createReqVO); - brandMapper.insert(brand); - // 返回 - return brand.getId(); - } - - @Override - public void updateBrand(ProductBrandUpdateReqVO updateReqVO) { - // 校验存在 - validateBrandExists(updateReqVO.getId()); - validateBrandNameUnique(updateReqVO.getId(), updateReqVO.getName()); - // 更新 - ProductBrandDO updateObj = ProductBrandConvert.INSTANCE.convert(updateReqVO); - brandMapper.updateById(updateObj); - } - - @Override - public void deleteBrand(Long id) { - // 校验存在 - validateBrandExists(id); - // 删除 - brandMapper.deleteById(id); - } - - private void validateBrandExists(Long id) { - if (brandMapper.selectById(id) == null) { - throw exception(BRAND_NOT_EXISTS); - } - } - - @VisibleForTesting - public void validateBrandNameUnique(Long id, String name) { - ProductBrandDO brand = brandMapper.selectByName(name); - if (brand == null) { - return; - } - // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 - if (id == null) { - throw exception(BRAND_NAME_EXISTS); - } - if (!brand.getId().equals(id)) { - throw exception(BRAND_NAME_EXISTS); - } - } - - @Override - public ProductBrandDO getBrand(Long id) { - return brandMapper.selectById(id); - } - - @Override - public List getBrandList(Collection ids) { - return brandMapper.selectBatchIds(ids); - } - - @Override - public List getBrandList(ProductBrandListReqVO listReqVO) { - return brandMapper.selectList(listReqVO); - } - - @Override - public void validateProductBrand(Long id) { - ProductBrandDO brand = brandMapper.selectById(id); - if (brand == null) { - throw exception(BRAND_NOT_EXISTS); - } - if (brand.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { - throw exception(BRAND_DISABLED); - } - } - - @Override - public PageResult getBrandPage(ProductBrandPageReqVO pageReqVO) { - return brandMapper.selectPage(pageReqVO); - } - - @Override - public List getBrandListByStatus(Integer status) { - return brandMapper.selectListByStatus(status); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java deleted file mode 100644 index 59495a1..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.iocoder.yudao.module.product.service.category; - -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import jakarta.validation.Valid; - -import java.util.Collection; -import java.util.List; - -/** - * 商品分类 Service 接口 - * - * @author 芋道源码 - */ -public interface ProductCategoryService { - - /** - * 创建商品分类 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createCategory(@Valid ProductCategorySaveReqVO createReqVO); - - /** - * 更新商品分类 - * - * @param updateReqVO 更新信息 - */ - void updateCategory(@Valid ProductCategorySaveReqVO updateReqVO); - - /** - * 删除商品分类 - * - * @param id 编号 - */ - void deleteCategory(Long id); - - /** - * 获得商品分类 - * - * @param id 编号 - * @return 商品分类 - */ - ProductCategoryDO getCategory(Long id); - - /** - * 校验商品分类 - * - * @param id 分类编号 - */ - void validateCategory(Long id); - - /** - * 获得商品分类的层级 - * - * @param id 编号 - * @return 商品分类的层级 - */ - Integer getCategoryLevel(Long id); - - /** - * 获得商品分类列表 - * - * @param listReqVO 查询条件 - * @return 商品分类列表 - */ - List getCategoryList(ProductCategoryListReqVO listReqVO); - - /** - * 获得开启状态的商品分类列表 - * - * @return 商品分类列表 - */ - List getEnableCategoryList(); - - /** - * 获得开启状态的商品分类列表,指定编号 - * - * @param ids 商品分类编号数组 - * @return 商品分类列表 - */ - List getEnableCategoryList(List ids); - - /** - * 校验商品分类是否有效。如下情况,视为无效: - * 1. 商品分类编号不存在 - * 2. 商品分类被禁用 - * 3. 商品分类层级校验,必须使用第二级的商品分类及以下 - * - * @param ids 商品分类编号数组 - */ - void validateCategoryList(Collection ids); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java deleted file mode 100644 index 0d30dd5..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java +++ /dev/null @@ -1,184 +0,0 @@ -package cn.iocoder.yudao.module.product.service.category; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL; -import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 商品分类 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class ProductCategoryServiceImpl implements ProductCategoryService { - - @Resource - private ProductCategoryMapper productCategoryMapper; - @Resource - @Lazy // 循环依赖,避免报错 - private ProductSpuService productSpuService; - - @Override - public Long createCategory(ProductCategorySaveReqVO createReqVO) { - // 校验父分类存在 - validateParentProductCategory(createReqVO.getParentId()); - - // 插入 - ProductCategoryDO category = BeanUtils.toBean(createReqVO, ProductCategoryDO.class); - productCategoryMapper.insert(category); - // 返回 - return category.getId(); - } - - @Override - public void updateCategory(ProductCategorySaveReqVO updateReqVO) { - // 校验分类是否存在 - validateProductCategoryExists(updateReqVO.getId()); - // 校验父分类存在 - validateParentProductCategory(updateReqVO.getParentId()); - - // 更新 - ProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ProductCategoryDO.class); - productCategoryMapper.updateById(updateObj); - } - - @Override - public void deleteCategory(Long id) { - // 校验分类是否存在 - validateProductCategoryExists(id); - // 校验是否还有子分类 - if (productCategoryMapper.selectCountByParentId(id) > 0) { - throw exception(CATEGORY_EXISTS_CHILDREN); - } - // 校验分类是否绑定了 SPU - Long spuCount = productSpuService.getSpuCountByCategoryId(id); - if (spuCount > 0) { - throw exception(CATEGORY_HAVE_BIND_SPU); - } - // 删除 - productCategoryMapper.deleteById(id); - } - - private void validateParentProductCategory(Long id) { - // 如果是根分类,无需验证 - if (Objects.equals(id, PARENT_ID_NULL)) { - return; - } - // 父分类不存在 - ProductCategoryDO category = productCategoryMapper.selectById(id); - if (category == null) { - throw exception(CATEGORY_PARENT_NOT_EXISTS); - } - // 父分类不能是二级分类 - if (!Objects.equals(category.getParentId(), PARENT_ID_NULL)) { - throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL); - } - } - - private void validateProductCategoryExists(Long id) { - ProductCategoryDO category = productCategoryMapper.selectById(id); - if (category == null) { - throw exception(CATEGORY_NOT_EXISTS); - } - } - - @Override - public void validateCategoryList(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return; - } - // 获得商品分类信息 - List list = productCategoryMapper.selectBatchIds(ids); - Map categoryMap = CollectionUtils.convertMap(list, ProductCategoryDO::getId); - // 校验 - ids.forEach(id -> { - // 校验分类是否存在 - ProductCategoryDO category = categoryMap.get(id); - if (category == null) { - throw exception(CATEGORY_NOT_EXISTS); - } - // 校验分类是否启用 - if (!CommonStatusEnum.ENABLE.getStatus().equals(category.getStatus())) { - throw exception(CATEGORY_DISABLED, category.getName()); - } - // 商品分类层级校验,必须使用第二级的商品分类 - if (getCategoryLevel(id) < CATEGORY_LEVEL) { - throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR); - } - }); - } - - @Override - public ProductCategoryDO getCategory(Long id) { - return productCategoryMapper.selectById(id); - } - - @Override - public void validateCategory(Long id) { - ProductCategoryDO category = productCategoryMapper.selectById(id); - if (category == null) { - throw exception(CATEGORY_NOT_EXISTS); - } - if (Objects.equals(category.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { - throw exception(CATEGORY_DISABLED, category.getName()); - } - } - - @Override - public Integer getCategoryLevel(Long id) { - if (Objects.equals(id, PARENT_ID_NULL)) { - return 0; - } - int level = 1; - // for 的原因,是因为避免脏数据,导致可能的死循环。一般不会超过 100 层哈 - for (int i = 0; i < Byte.MAX_VALUE; i++) { - // 如果没有父节点,break 结束 - ProductCategoryDO category = productCategoryMapper.selectById(id); - if (category == null - || Objects.equals(category.getParentId(), PARENT_ID_NULL)) { - break; - } - // 继续递归父节点 - level++; - id = category.getParentId(); - } - return level; - } - - @Override - public List getCategoryList(ProductCategoryListReqVO listReqVO) { - return productCategoryMapper.selectList(listReqVO); - } - - @Override - public List getEnableCategoryList() { - return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); - } - - @Override - public List getEnableCategoryList(List ids) { - return productCategoryMapper.selectListByIdAndStatus(ids, CommonStatusEnum.ENABLE.getStatus()); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java deleted file mode 100644 index b54e219..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.product.service.comment; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -/** - * 商品评论 Service 接口 - * - * @author wangzhs - */ -@Service -@Validated -public interface ProductCommentService { - - /** - * 创建商品评论 - * 后台管理员创建评论使用 - * - * @param createReqVO 商品评价创建 Request VO 对象 - */ - void createComment(ProductCommentCreateReqVO createReqVO); - - /** - * 创建评论 - * 创建商品评论 APP 端创建商品评论使用 - * - * @param createReqDTO 创建请求 dto - * @return 返回评论 id - */ - Long createComment(ProductCommentCreateReqDTO createReqDTO); - - /** - * 修改评论是否可见 - * - * @param updateReqVO 修改评论可见 - */ - void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO); - - /** - * 商家回复 - * - * @param replyVO 商家回复 - * @param userId 管理后台商家登陆人 ID - */ - void replyComment(ProductCommentReplyReqVO replyVO, Long userId); - - /** - * 【管理员】获得商品评价分页 - * - * @param pageReqVO 分页查询 - * @return 商品评价分页 - */ - PageResult getCommentPage(ProductCommentPageReqVO pageReqVO); - - /** - * 【会员】获得商品评价分页 - * - * @param pageVO 分页查询 - * @param visible 是否可见 - * @return 商品评价分页 - */ - PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java deleted file mode 100644 index 34b0766..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java +++ /dev/null @@ -1,147 +0,0 @@ -package cn.iocoder.yudao.module.product.service.comment; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 商品评论 Service 实现类 - * - * @author wangzhs - */ -@Service -@Validated -public class ProductCommentServiceImpl implements ProductCommentService { - - @Resource - private ProductCommentMapper productCommentMapper; - - @Resource - private ProductSpuService productSpuService; - - @Resource - @Lazy - private ProductSkuService productSkuService; - - @Resource - private MemberUserApi memberUserApi; - - @Override - public void createComment(ProductCommentCreateReqVO createReqVO) { - // 校验 SKU - ProductSkuDO sku = validateSku(createReqVO.getSkuId()); - // 校验 SPU - ProductSpuDO spu = validateSpu(sku.getSpuId()); - - // 创建评论 - ProductCommentDO comment = ProductCommentConvert.INSTANCE.convert(createReqVO, spu, sku); - productCommentMapper.insert(comment); - } - - @Override - public Long createComment(ProductCommentCreateReqDTO createReqDTO) { - // 校验 SKU - ProductSkuDO sku = validateSku(createReqDTO.getSkuId()); - // 校验 SPU - ProductSpuDO spu = validateSpu(sku.getSpuId()); - // 校验评论 - validateCommentExists(createReqDTO.getUserId(), createReqDTO.getOrderItemId()); - // 获取用户详细信息 - MemberUserRespDTO user = memberUserApi.getUser(createReqDTO.getUserId()); - - // 创建评论 - ProductCommentDO comment = ProductCommentConvert.INSTANCE.convert(createReqDTO, spu, sku, user); - productCommentMapper.insert(comment); - return comment.getId(); - } - - /** - * 判断当前订单的当前商品用户是否评价过 - * - * @param userId 用户编号 - * @param orderItemId 订单项编号 - */ - private void validateCommentExists(Long userId, Long orderItemId) { - ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemId(userId, orderItemId); - if (exist != null) { - throw exception(COMMENT_ORDER_EXISTS); - } - } - - private ProductSkuDO validateSku(Long skuId) { - ProductSkuDO sku = productSkuService.getSku(skuId, true); - if (sku == null) { - throw exception(SKU_NOT_EXISTS); - } - return sku; - } - - private ProductSpuDO validateSpu(Long spuId) { - ProductSpuDO spu = productSpuService.getSpu(spuId, true); - if (null == spu) { - throw exception(SPU_NOT_EXISTS); - } - return spu; - } - - @Override - public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) { - // 校验评论是否存在 - validateCommentExists(updateReqVO.getId()); - - // 更新可见状态 - productCommentMapper.updateById(new ProductCommentDO().setId(updateReqVO.getId()) - .setVisible(updateReqVO.getVisible())); - } - - @Override - public void replyComment(ProductCommentReplyReqVO replyVO, Long userId) { - // 校验评论是否存在 - validateCommentExists(replyVO.getId()); - // 回复评论 - productCommentMapper.updateById(new ProductCommentDO().setId(replyVO.getId()) - .setReplyTime(LocalDateTime.now()).setReplyUserId(userId) - .setReplyStatus(Boolean.TRUE).setReplyContent(replyVO.getReplyContent())); - } - - private ProductCommentDO validateCommentExists(Long id) { - ProductCommentDO productComment = productCommentMapper.selectById(id); - if (productComment == null) { - throw exception(COMMENT_NOT_EXISTS); - } - return productComment; - } - - @Override - public PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) { - return productCommentMapper.selectPage(pageVO, visible); - } - - @Override - public PageResult getCommentPage(ProductCommentPageReqVO pageReqVO) { - return productCommentMapper.selectPage(pageReqVO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java deleted file mode 100644 index e71424d..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.product.service.favorite; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; - -import jakarta.validation.Valid; - -/** - * 商品收藏 Service 接口 - * - * @author jason - */ -public interface ProductFavoriteService { - - /** - * 创建商品收藏 - * - * @param userId 用户编号 - * @param spuId SPU 编号 - */ - Long createFavorite(Long userId, Long spuId); - - /** - * 取消商品收藏 - * - * @param userId 用户编号 - * @param spuId SPU 编号 - */ - void deleteFavorite(Long userId, Long spuId); - - /** - * 分页查询用户收藏列表 - * - * @param userId 用户编号 - * @param reqVO 请求 vo - */ - PageResult getFavoritePage(Long userId, @Valid AppFavoritePageReqVO reqVO); - - /** - * 分页查询用户收藏列表 - * - * @param reqVO 请求 vo - */ - PageResult getFavoritePage(@Valid ProductFavoritePageReqVO reqVO); - - /** - * 获取收藏过商品 - * - * @param userId 用户编号 - * @param spuId SPU 编号 - */ - ProductFavoriteDO getFavorite(Long userId, Long spuId); - - /** - * 获取用户收藏数量 - * - * @param userId 用户编号 - * @return 数量 - */ - Long getFavoriteCount(Long userId); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java deleted file mode 100644 index 61b4963..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java +++ /dev/null @@ -1,73 +0,0 @@ -package cn.iocoder.yudao.module.product.service.favorite; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; -import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; -import cn.iocoder.yudao.module.product.convert.favorite.ProductFavoriteConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; -import cn.iocoder.yudao.module.product.dal.mysql.favorite.ProductFavoriteMapper; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import jakarta.annotation.Resource; -import jakarta.validation.Valid; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.FAVORITE_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.FAVORITE_NOT_EXISTS; - -/** - * 商品收藏 Service 实现类 - * - * @author jason - */ -@Service -@Validated -public class ProductFavoriteServiceImpl implements ProductFavoriteService { - - @Resource - private ProductFavoriteMapper productFavoriteMapper; - - @Override - public Long createFavorite(Long userId, Long spuId) { - ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); - if (favorite != null) { - throw exception(FAVORITE_EXISTS); - } - - ProductFavoriteDO entity = ProductFavoriteConvert.INSTANCE.convert(userId, spuId); - productFavoriteMapper.insert(entity); - return entity.getId(); - } - - @Override - public void deleteFavorite(Long userId, Long spuId) { - ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); - if (favorite == null) { - throw exception(FAVORITE_NOT_EXISTS); - } - - productFavoriteMapper.deleteById(favorite.getId()); - } - - @Override - public PageResult getFavoritePage(Long userId, @Valid AppFavoritePageReqVO reqVO) { - return productFavoriteMapper.selectPageByUserAndType(userId, reqVO); - } - - @Override - public PageResult getFavoritePage(@Valid ProductFavoritePageReqVO reqVO) { - return productFavoriteMapper.selectPageByUserId(reqVO); - } - - @Override - public ProductFavoriteDO getFavorite(Long userId, Long spuId) { - return productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); - } - - @Override - public Long getFavoriteCount(Long userId) { - return productFavoriteMapper.selectCountByUserId(userId); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java deleted file mode 100644 index 10f3a71..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.product.service.history; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; -import org.springframework.scheduling.annotation.Async; - -import java.util.Collection; - -/** - * 商品浏览记录 Service 接口 - * - * @author owen - */ -public interface ProductBrowseHistoryService { - - /** - * 创建商品浏览记录 - * - * @param userId 用户编号 - * @param spuId SPU 编号 - */ - @Async - void createBrowseHistory(Long userId, Long spuId); - - /** - * 隐藏用户商品浏览记录 - * - * @param userId 用户编号 - * @param spuId SPU 编号 - */ - void hideUserBrowseHistory(Long userId, Collection spuId); - - /** - * 获得商品浏览记录分页 - * - * @param pageReqVO 分页查询 - * @return 商品浏览记录分页 - */ - PageResult getBrowseHistoryPage(ProductBrowseHistoryPageReqVO pageReqVO); - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java deleted file mode 100644 index b015299..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.product.service.history; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; -import cn.iocoder.yudao.module.product.dal.mysql.history.ProductBrowseHistoryMapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; - -/** - * 商品浏览记录 Service 实现类 - * - * @author owen - */ -@Service -@Validated -public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryService { - - private static final int USER_STORE_MAXIMUM = 100; - - @Resource - private ProductBrowseHistoryMapper browseHistoryMapper; - - @Override - public void createBrowseHistory(Long userId, Long spuId) { - // 用户未登录时不记录 - if (userId == null) { - return; - } - - // 情况一:同一个商品,只保留最新的一条记录 - ProductBrowseHistoryDO history = browseHistoryMapper.selectByUserIdAndSpuId(userId, spuId); - if (history != null) { - browseHistoryMapper.deleteById(history); - } else { - // 情况二:限制每个用户的浏览记录的条数(只查一条最早地记录、记录总数) - // TODO @疯狂:这里最好先查询一次数量。如果发现超过了,再删除;主要考虑,可能有部分不超过,提前就多了一次 sql 查询了 - Page pageResult = browseHistoryMapper.selectPageByUserIdOrderByCreateTimeAsc(userId, 1, 1); - if (pageResult.getTotal() >= USER_STORE_MAXIMUM) { - browseHistoryMapper.deleteById(CollUtil.getFirst(pageResult.getRecords())); - } - } - - // 插入 - ProductBrowseHistoryDO browseHistory = new ProductBrowseHistoryDO() - .setUserId(userId) - .setSpuId(spuId); - browseHistoryMapper.insert(browseHistory); - } - - @Override - public void hideUserBrowseHistory(Long userId, Collection spuIds) { - browseHistoryMapper.updateUserDeletedByUserId(userId, spuIds, true); - } - - @Override - public PageResult getBrowseHistoryPage(ProductBrowseHistoryPageReqVO pageReqVO) { - return browseHistoryMapper.selectPage(pageReqVO); - } - -} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java deleted file mode 100644 index 0872136..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.product.service.property; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; - -import jakarta.validation.Valid; -import java.util.Collection; -import java.util.List; - -/** - * 商品属性项 Service 接口 - * - * @author 芋道源码 - */ -public interface ProductPropertyService { - - /** - * 创建属性项 - * 注意,如果已经存在该属性项,直接返回它的编号即可 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createProperty(@Valid ProductPropertySaveReqVO createReqVO); - - /** - * 更新属性项 - * - * @param updateReqVO 更新信息 - */ - void updateProperty(@Valid ProductPropertySaveReqVO updateReqVO); - - /** - * 删除属性项 - * - * @param id 编号 - */ - void deleteProperty(Long id); - - /** - * 获取属性名称分页 - * - * @param pageReqVO 分页条件 - * @return 属性项分页 - */ - PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO); - - /** - * 获得指定编号的属性项 - * - * @param id 编号 - * @return 属性项 - */ - ProductPropertyDO getProperty(Long id); - - /** - * 根据属性项的编号的集合,获得对应的属性项数组 - * - * @param ids 属性项的编号的集合 - * @return 属性项数组 - */ - List getPropertyList(Collection ids); - - /** - * 获得指定状态的属性项列表 - * - * @return 属性项列表 - */ - List getPropertyList(); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java deleted file mode 100644 index 6c1d328..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -package cn.iocoder.yudao.module.product.service.property; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertySaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 商品属性项 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class ProductPropertyServiceImpl implements ProductPropertyService { - - @Resource - private ProductPropertyMapper productPropertyMapper; - - @Resource - @Lazy // 延迟加载,解决循环依赖问题 - private ProductPropertyValueService productPropertyValueService; - - @Resource - private ProductSkuService productSkuService; - - @Override - @Transactional(rollbackFor = Exception.class) - public Long createProperty(ProductPropertySaveReqVO createReqVO) { - // 如果已经添加过该属性项,直接返回 - ProductPropertyDO dbProperty = productPropertyMapper.selectByName(createReqVO.getName()); - if (dbProperty != null) { - return dbProperty.getId(); - } - - // 插入 - ProductPropertyDO property = BeanUtils.toBean(createReqVO, ProductPropertyDO.class); - productPropertyMapper.insert(property); - // 返回 - return property.getId(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateProperty(ProductPropertySaveReqVO updateReqVO) { - validatePropertyExists(updateReqVO.getId()); - // 校验名字重复 - ProductPropertyDO property = productPropertyMapper.selectByName(updateReqVO.getName()); - if (property != null && - ObjUtil.notEqual(property.getId(), updateReqVO.getId())) { - throw exception(PROPERTY_EXISTS); - } - - // 更新 - ProductPropertyDO updateObj = BeanUtils.toBean(updateReqVO, ProductPropertyDO.class); - productPropertyMapper.updateById(updateObj); - // 更新 sku 相关属性 - productSkuService.updateSkuProperty(updateObj.getId(), updateObj.getName()); - } - - @Override - public void deleteProperty(Long id) { - // 校验存在 - validatePropertyExists(id); - // 校验其下是否有规格值 - if (productPropertyValueService.getPropertyValueCountByPropertyId(id) > 0) { - throw exception(PROPERTY_DELETE_FAIL_VALUE_EXISTS); - } - - // 删除 - productPropertyMapper.deleteById(id); - // 同步删除属性值 - productPropertyValueService.deletePropertyValueByPropertyId(id); - } - - private void validatePropertyExists(Long id) { - if (productPropertyMapper.selectById(id) == null) { - throw exception(PROPERTY_NOT_EXISTS); - } - } - - @Override - public PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO) { - return productPropertyMapper.selectPage(pageReqVO); - } - - @Override - public ProductPropertyDO getProperty(Long id) { - return productPropertyMapper.selectById(id); - } - - @Override - public List getPropertyList(Collection ids) { - return productPropertyMapper.selectBatchIds(ids); - } - - @Override - public List getPropertyList() { - return productPropertyMapper.selectList(); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java deleted file mode 100644 index aaa7ff1..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java +++ /dev/null @@ -1,80 +0,0 @@ -package cn.iocoder.yudao.module.product.service.property; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueSaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; - -import java.util.Collection; -import java.util.List; - -/** - * 商品属性值 Service 接口 - * - * @author LuoWenFeng - */ -public interface ProductPropertyValueService { - - /** - * 创建属性值 - * 注意,如果已经存在该属性值,直接返回它的编号即可 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createPropertyValue(ProductPropertyValueSaveReqVO createReqVO); - - /** - * 更新属性值 - * - * @param updateReqVO 更新信息 - */ - void updatePropertyValue(ProductPropertyValueSaveReqVO updateReqVO); - - /** - * 删除属性值 - * - * @param id 编号 - */ - void deletePropertyValue(Long id); - - /** - * 获得属性值 - * - * @param id 编号 - * @return 属性值 - */ - ProductPropertyValueDO getPropertyValue(Long id); - - /** - * 根据属性项编号数组,获得属性值列表 - * - * @param propertyIds 属性项目编号数组 - * @return 属性值列表 - */ - List getPropertyValueListByPropertyId(Collection propertyIds); - - /** - * 根据属性项编号,活的属性值数量 - * - * @param propertyId 属性项编号数 - * @return 属性值数量 - */ - Integer getPropertyValueCountByPropertyId(Long propertyId); - - /** - * 获取属性值的分页 - * - * @param pageReqVO 查询条件 - * @return 属性值的分页 - */ - PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO); - - /** - * 删除指定属性项编号下的属性值们 - * - * @param propertyId 属性项的编号 - */ - void deletePropertyValueByPropertyId(Long propertyId); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java deleted file mode 100644 index 1293458..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.iocoder.yudao.module.product.service.property; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueSaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; -import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS; - -/** - * 商品属性值 Service 实现类 - * - * @author LuoWenFeng - */ -@Service -@Validated -public class ProductPropertyValueServiceImpl implements ProductPropertyValueService { - - @Resource - private ProductPropertyValueMapper productPropertyValueMapper; - - @Resource - @Lazy // 延迟加载,避免循环依赖 - private ProductSkuService productSkuService; - - @Override - public Long createPropertyValue(ProductPropertyValueSaveReqVO createReqVO) { - // 如果已经添加过该属性值,直接返回 - ProductPropertyValueDO dbValue = productPropertyValueMapper.selectByName( - createReqVO.getPropertyId(), createReqVO.getName()); - if (dbValue != null) { - return dbValue.getId(); - } - - // 新增 - ProductPropertyValueDO value = BeanUtils.toBean(createReqVO, ProductPropertyValueDO.class); - productPropertyValueMapper.insert(value); - return value.getId(); - } - - @Override - public void updatePropertyValue(ProductPropertyValueSaveReqVO updateReqVO) { - validatePropertyValueExists(updateReqVO.getId()); - // 校验名字唯一 - ProductPropertyValueDO value = productPropertyValueMapper.selectByName - (updateReqVO.getPropertyId(), updateReqVO.getName()); - if (value != null && !value.getId().equals(updateReqVO.getId())) { - throw exception(PROPERTY_VALUE_EXISTS); - } - - // 更新 - ProductPropertyValueDO updateObj = BeanUtils.toBean(updateReqVO, ProductPropertyValueDO.class); - productPropertyValueMapper.updateById(updateObj); - // 更新 sku 相关属性 - productSkuService.updateSkuPropertyValue(updateObj.getId(), updateObj.getName()); - } - - @Override - public void deletePropertyValue(Long id) { - validatePropertyValueExists(id); - productPropertyValueMapper.deleteById(id); - } - - private void validatePropertyValueExists(Long id) { - if (productPropertyValueMapper.selectById(id) == null) { - throw exception(PROPERTY_VALUE_NOT_EXISTS); - } - } - - @Override - public ProductPropertyValueDO getPropertyValue(Long id) { - return productPropertyValueMapper.selectById(id); - } - - @Override - public List getPropertyValueListByPropertyId(Collection propertyIds) { - return productPropertyValueMapper.selectListByPropertyId(propertyIds); - } - - @Override - public Integer getPropertyValueCountByPropertyId(Long propertyId) { - return productPropertyValueMapper.selectCountByPropertyId(propertyId); - } - - @Override - public PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO) { - return productPropertyValueMapper.selectPage(pageReqVO); - } - - @Override - public void deletePropertyValueByPropertyId(Long propertyId) { - productPropertyValueMapper.deleteByPropertyId(propertyId); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java deleted file mode 100755 index 749ef45..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ /dev/null @@ -1,122 +0,0 @@ -package cn.iocoder.yudao.module.product.service.sku; - -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; - -import java.util.Collection; -import java.util.List; - -/** - * 商品 SKU Service 接口 - * - * @author 芋道源码 - */ -public interface ProductSkuService { - - /** - * 删除商品 SKU - * - * @param id 编号 - */ - void deleteSku(Long id); - - /** - * 获得商品 SKU 信息 - * - * @param id 编号 - * @return 商品 SKU 信息 - */ - ProductSkuDO getSku(Long id); - - /** - * 获得商品 SKU 信息 - * - * @param id 编号 - * @param includeDeleted 是否包含已删除的 - * @return 商品 SKU 信息 - */ - ProductSkuDO getSku(Long id, boolean includeDeleted); - - /** - * 获得商品 SKU 列表 - * - * @param ids 编号 - * @return 商品sku列表 - */ - List getSkuList(Collection ids); - - /** - * 对 sku 的组合的属性等进行合法性校验 - * - * @param list sku组合的集合 - */ - void validateSkuList(List list, Boolean specType); - - /** - * 批量创建 SKU - * - * @param spuId 商品 SPU 编号 - * @param list SKU 对象集合 - */ - void createSkuList(Long spuId, List list); - - /** - * 根据 SPU 编号,批量更新它的 SKU 信息 - * - * @param spuId SPU 编码 - * @param skus SKU 的集合 - */ - void updateSkuList(Long spuId, List skus); - - /** - * 更新 SKU 库存(增量) - *

- * 如果更新的库存不足,会抛出异常 - * - * @param updateStockReqDTO 更行请求 - */ - void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); - - /** - * 获得商品 SKU 集合 - * - * @param spuId spu 编号 - * @return 商品sku 集合 - */ - List getSkuListBySpuId(Long spuId); - - /** - * 获得 spu 对应的 SKU 集合 - * - * @param spuIds spu 编码集合 - * @return 商品 sku 集合 - */ - List getSkuListBySpuId(Collection spuIds); - - /** - * 通过 spuId 删除 sku 信息 - * - * @param spuId spu 编码 - */ - void deleteSkuBySpuId(Long spuId); - - /** - * 更新 sku 属性 - * - * @param propertyId 属性 id - * @param propertyName 属性名 - * @return int 影响的行数 - */ - int updateSkuProperty(Long propertyId, String propertyName); - - /** - * 更新 sku 属性值 - * - * @param propertyValueId 属性值 id - * @param propertyValueName 属性值名字 - * @return int 影响的行数 - */ - int updateSkuPropertyValue(Long propertyValueId, String propertyValueName); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java deleted file mode 100755 index d79e067..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java +++ /dev/null @@ -1,278 +0,0 @@ -package cn.iocoder.yudao.module.product.service.sku; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import java.util.*; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 商品 SKU Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class ProductSkuServiceImpl implements ProductSkuService { - - @Resource - private ProductSkuMapper productSkuMapper; - - @Resource - @Lazy // 循环依赖,避免报错 - private ProductSpuService productSpuService; - @Resource - @Lazy // 循环依赖,避免报错 - private ProductPropertyService productPropertyService; - @Resource - private ProductPropertyValueService productPropertyValueService; - - @Override - public void deleteSku(Long id) { - // 校验存在 - validateSkuExists(id); - // 删除 - productSkuMapper.deleteById(id); - } - - private void validateSkuExists(Long id) { - if (productSkuMapper.selectById(id) == null) { - throw exception(SKU_NOT_EXISTS); - } - } - - @Override - public ProductSkuDO getSku(Long id) { - return productSkuMapper.selectById(id); - } - - @Override - public ProductSkuDO getSku(Long id, boolean includeDeleted) { - if (includeDeleted) { - return productSkuMapper.selectByIdIncludeDeleted(id); - } - return getSku(id); - } - - @Override - public List getSkuList(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return productSkuMapper.selectBatchIds(ids); - } - - @Override - public void validateSkuList(List skus, Boolean specType) { - // 0、校验skus是否为空 - if (CollUtil.isEmpty(skus)) { - throw exception(SKU_NOT_EXISTS); - } - // 单规格,赋予单规格默认属性 - if (ObjectUtil.equal(specType, false)) { - ProductSkuSaveReqVO skuVO = skus.get(0); - List properties = new ArrayList<>(); - ProductSkuSaveReqVO.Property property = new ProductSkuSaveReqVO.Property() - .setPropertyId(ProductPropertyDO.ID_DEFAULT).setPropertyName(ProductPropertyDO.NAME_DEFAULT) - .setValueId(ProductPropertyValueDO.ID_DEFAULT).setValueName(ProductPropertyValueDO.NAME_DEFAULT); - properties.add(property); - skuVO.setProperties(properties); - return; // 单规格不需要后续的校验 - } - - // 1、校验属性项存在 - Set propertyIds = skus.stream().filter(p -> p.getProperties() != null) - // 遍历多个 Property 属性 - .flatMap(p -> p.getProperties().stream()) - // 将每个 Property 转换成对应的 propertyId,最后形成集合 - .map(ProductSkuSaveReqVO.Property::getPropertyId) - .collect(Collectors.toSet()); - List propertyList = productPropertyService.getPropertyList(propertyIds); - if (propertyList.size() != propertyIds.size()) { - throw exception(PROPERTY_NOT_EXISTS); - } - - // 2. 校验,一个 SKU 下,没有重复的属性。校验方式是,遍历每个 SKU ,看看是否有重复的属性 propertyId - Map propertyValueMap = convertMap(productPropertyValueService.getPropertyValueListByPropertyId(propertyIds), ProductPropertyValueDO::getId); - skus.forEach(sku -> { - Set skuPropertyIds = convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId()); - if (skuPropertyIds.size() != sku.getProperties().size()) { - throw exception(SKU_PROPERTIES_DUPLICATED); - } - }); - - // 3. 再校验,每个 Sku 的属性值的数量,是一致的。 - int attrValueIdsSize = skus.get(0).getProperties().size(); - for (int i = 1; i < skus.size(); i++) { - if (attrValueIdsSize != skus.get(i).getProperties().size()) { - throw exception(SPU_ATTR_NUMBERS_MUST_BE_EQUALS); - } - } - - // 4. 最后校验,每个 Sku 之间不是重复的 - // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. - Set> skuAttrValues = new HashSet<>(); - for (ProductSkuSaveReqVO sku : skus) { - // 添加失败,说明重复 - if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuSaveReqVO.Property::getValueId))) { - throw exception(SPU_SKU_NOT_DUPLICATE); - } - } - } - - @Override - public void createSkuList(Long spuId, List skuCreateReqList) { - List skus = BeanUtils.toBean(skuCreateReqList, ProductSkuDO.class, sku -> sku.setSpuId(spuId)); - productSkuMapper.insertBatch(skus); - } - - @Override - public List getSkuListBySpuId(Long spuId) { - return productSkuMapper.selectListBySpuId(spuId); - } - - @Override - public List getSkuListBySpuId(Collection spuIds) { - if (CollUtil.isEmpty(spuIds)) { - return Collections.emptyList(); - } - return productSkuMapper.selectListBySpuId(spuIds); - } - - @Override - public void deleteSkuBySpuId(Long spuId) { - productSkuMapper.deleteBySpuId(spuId); - } - - @Override - public int updateSkuProperty(Long propertyId, String propertyName) { - // 获取所有的 sku - List skuDOList = productSkuMapper.selectList(); - // 处理后需要更新的 sku - List updateSkus = new ArrayList<>(); - if (CollUtil.isEmpty(skuDOList)) { - return 0; - } - skuDOList.stream().filter(sku -> sku.getProperties() != null) - .forEach(sku -> sku.getProperties().forEach(property -> { - if (property.getPropertyId().equals(propertyId)) { - property.setPropertyName(propertyName); - updateSkus.add(sku); - } - })); - if (CollUtil.isEmpty(updateSkus)) { - return 0; - } - - productSkuMapper.updateBatch(updateSkus); - return updateSkus.size(); - } - - @Override - public int updateSkuPropertyValue(Long propertyValueId, String propertyValueName) { - // 获取所有的 sku - List skuDOList = productSkuMapper.selectList(); - // 处理后需要更新的 sku - List updateSkus = new ArrayList<>(); - if (CollUtil.isEmpty(skuDOList)) { - return 0; - } - skuDOList.stream() - .filter(sku -> sku.getProperties() != null) - .forEach(sku -> sku.getProperties().forEach(property -> { - if (property.getValueId().equals(propertyValueId)) { - property.setValueName(propertyValueName); - updateSkus.add(sku); - } - })); - if (CollUtil.isEmpty(updateSkus)) { - return 0; - } - - productSkuMapper.updateBatch(updateSkus); - return updateSkus.size(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateSkuList(Long spuId, List skus) { - // 构建属性与 SKU 的映射关系; - Map existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId), - ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId); - - // 拆分三个集合,新插入的、需要更新的、需要删除的 - List insertSkus = new ArrayList<>(); - List updateSkus = new ArrayList<>(); - List allUpdateSkus = BeanUtils.toBean(skus, ProductSkuDO.class, sku -> sku.setSpuId(spuId)); - allUpdateSkus.forEach(sku -> { - String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku); - // 1、找得到的,进行更新 - Long existsSkuId = existsSkuMap.remove(propertiesKey); - if (existsSkuId != null) { - sku.setId(existsSkuId); - updateSkus.add(sku); - return; - } - // 2、找不到,进行插入 - sku.setSpuId(spuId); - insertSkus.add(sku); - }); - - // 执行最终的批量操作 - if (CollUtil.isNotEmpty(insertSkus)) { - productSkuMapper.insertBatch(insertSkus); - } - if (CollUtil.isNotEmpty(updateSkus)) { - updateSkus.forEach(sku -> productSkuMapper.updateById(sku)); - } - if (CollUtil.isNotEmpty(existsSkuMap)) { - productSkuMapper.deleteBatchIds(existsSkuMap.values()); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) { - // 更新 SKU 库存 - updateStockReqDTO.getItems().forEach(item -> { - if (item.getIncrCount() > 0) { - productSkuMapper.updateStockIncr(item.getId(), item.getIncrCount()); - } else if (item.getIncrCount() < 0) { - int updateStockIncr = productSkuMapper.updateStockDecr(item.getId(), item.getIncrCount()); - if (updateStockIncr == 0) { - throw exception(SKU_STOCK_NOT_ENOUGH); - } - } - }); - - // 更新 SPU 库存 - List skus = productSkuMapper.selectBatchIds( - convertSet(updateStockReqDTO.getItems(), ProductSkuUpdateStockReqDTO.Item::getId)); - Map spuStockIncrCounts = ProductSkuConvert.INSTANCE.convertSpuStockMap( - updateStockReqDTO.getItems(), skus); - productSpuService.updateSpuStock(spuStockIncrCounts); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java deleted file mode 100755 index 6ed9460..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java +++ /dev/null @@ -1,155 +0,0 @@ -package cn.iocoder.yudao.module.product.service.spu; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import jakarta.validation.Valid; -import org.springframework.scheduling.annotation.Async; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * 商品 SPU Service 接口 - * - * @author 芋道源码 - */ -public interface ProductSpuService { - - /** - * 创建商品 SPU - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createSpu(@Valid ProductSpuSaveReqVO createReqVO); - - /** - * 更新商品 SPU - * - * @param updateReqVO 更新信息 - */ - void updateSpu(@Valid ProductSpuSaveReqVO updateReqVO); - - /** - * 删除商品 SPU - * - * @param id 编号 - */ - void deleteSpu(Long id); - - /** - * 获得商品 SPU - * - * @param id 编号 - * @return 商品 SPU - */ - ProductSpuDO getSpu(Long id); - - /** - * 获得商品 SPU - * - * @param id 编号 - * @param includeDeleted 是否包含已删除的 - * @return 商品 SPU - */ - ProductSpuDO getSpu(Long id, boolean includeDeleted); - - /** - * 获得商品 SPU 列表 - * - * @param ids 编号数组 - * @return 商品 SPU 列表 - */ - List getSpuList(Collection ids); - - /** - * 获得商品 SPU Map - * - * @param ids 编号数组 - * @return 商品 SPU Map - */ - default Map getSpuMap(Collection ids) { - List list = getSpuList(ids); - return CollectionUtils.convertMap(list, ProductSpuDO::getId); - } - - /** - * 获得指定状态的商品 SPU 列表 - * - * @param status 状态 - * @return 商品 SPU 列表 - */ - List getSpuListByStatus(Integer status); - - /** - * 获得商品 SPU 分页,提供给挂你兰后台使用 - * - * @param pageReqVO 分页查询 - * @return 商品spu分页 - */ - PageResult getSpuPage(ProductSpuPageReqVO pageReqVO); - - /** - * 获得商品 SPU 分页,提供给用户 App 使用 - * - * @param pageReqVO 分页查询 - * @return 商品 SPU 分页 - */ - PageResult getSpuPage(AppProductSpuPageReqVO pageReqVO); - - /** - * 更新商品 SPU 库存(增量) - * - * @param stockIncrCounts SPU 编号与库存变化(增量)的映射 - */ - void updateSpuStock(Map stockIncrCounts); - - /** - * 更新 SPU 状态 - * - * @param updateReqVO 更新请求 - */ - void updateSpuStatus(ProductSpuUpdateStatusReqVO updateReqVO); - - /** - * 获取 SPU 列表标签对应的 Count 数量 - * - * @return Count 数量 - */ - Map getTabsCount(); - - /** - * 通过分类 categoryId 查询 SPU 个数 - * - * @param categoryId 分类 categoryId - * @return SPU 数量 - */ - Long getSpuCountByCategoryId(Long categoryId); - - - /** - * 校验商品是否有效。如下情况,视为无效: - * 1. 商品编号不存在 - * 2. 商品被禁用 - * - * @param ids 商品编号数组 - * @return 商品 SPU 列表 - */ - List validateSpuList(Collection ids); - - /** - * 更新商品 SPU 浏览量 - * - * @param id 商品 SPU 编号 - * @param incrCount 增加的数量 - */ - @Async - void updateBrowseCount(Long id, int incrCount); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java deleted file mode 100755 index fd7f96f..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ /dev/null @@ -1,284 +0,0 @@ -package cn.iocoder.yudao.module.product.service.spu; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; -import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import com.google.common.collect.Maps; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import java.util.*; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; - -/** - * 商品 SPU Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class ProductSpuServiceImpl implements ProductSpuService { - - @Resource - private ProductSpuMapper productSpuMapper; - - @Resource - @Lazy // 循环依赖,避免报错 - private ProductSkuService productSkuService; - @Resource - private ProductBrandService brandService; - @Resource - private ProductCategoryService categoryService; - - @Override - @Transactional(rollbackFor = Exception.class) - public Long createSpu(ProductSpuSaveReqVO createReqVO) { - // 校验分类、品牌 - validateCategory(createReqVO.getCategoryId()); - brandService.validateProductBrand(createReqVO.getBrandId()); - // 校验 SKU - List skuSaveReqList = createReqVO.getSkus(); - productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); - - ProductSpuDO spu = BeanUtils.toBean(createReqVO, ProductSpuDO.class); - // 初始化 SPU 中 SKU 相关属性 - initSpuFromSkus(spu, skuSaveReqList); - // 插入 SPU - productSpuMapper.insert(spu); - // 插入 SKU - productSkuService.createSkuList(spu.getId(), skuSaveReqList); - // 返回 - return spu.getId(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateSpu(ProductSpuSaveReqVO updateReqVO) { - // 校验 SPU 是否存在 - ProductSpuDO spu = validateSpuExists(updateReqVO.getId()); - // 校验分类、品牌 - validateCategory(updateReqVO.getCategoryId()); - brandService.validateProductBrand(updateReqVO.getBrandId()); - // 校验SKU - List skuSaveReqList = updateReqVO.getSkus(); - productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType()); - - // 更新 SPU - ProductSpuDO updateObj = BeanUtils.toBean(updateReqVO, ProductSpuDO.class).setStatus(spu.getStatus()); - initSpuFromSkus(updateObj, skuSaveReqList); - productSpuMapper.updateById(updateObj); - // 批量更新 SKU - productSkuService.updateSkuList(updateObj.getId(), updateReqVO.getSkus()); - } - - /** - * 基于 SKU 的信息,初始化 SPU 的信息 - * 主要是计数相关的字段,例如说市场价、最大最小价、库存等等 - * - * @param spu 商品 SPU - * @param skus 商品 SKU 数组 - */ - private void initSpuFromSkus(ProductSpuDO spu, List skus) { - // sku 单价最低的商品的价格 - spu.setPrice(getMinValue(skus, ProductSkuSaveReqVO::getPrice)); - // sku 单价最低的商品的市场价格 - spu.setMarketPrice(getMinValue(skus, ProductSkuSaveReqVO::getMarketPrice)); - // sku 单价最低的商品的成本价格 - spu.setCostPrice(getMinValue(skus, ProductSkuSaveReqVO::getCostPrice)); - // skus 库存总数 - spu.setStock(getSumValue(skus, ProductSkuSaveReqVO::getStock, Integer::sum)); - // 若是 spu 已有状态则不处理 - if (spu.getStatus() == null) { - spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); // 默认状态为上架 - spu.setSalesCount(0); // 默认商品销量 - spu.setBrowseCount(0); // 默认商品浏览量 - } - } - - /** - * 校验商品分类是否合法 - * - * @param id 商品分类编号 - */ - private void validateCategory(Long id) { - categoryService.validateCategory(id); - // 校验层级 - if (categoryService.getCategoryLevel(id) < CATEGORY_LEVEL) { - throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR); - } - } - - @Override - public List validateSpuList(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return Collections.emptyList(); - } - // 获得商品信息 - List list = productSpuMapper.selectBatchIds(ids); - Map spuMap = CollectionUtils.convertMap(list, ProductSpuDO::getId); - // 校验 - ids.forEach(id -> { - ProductSpuDO spu = spuMap.get(id); - if (spu == null) { - throw exception(SPU_NOT_EXISTS); - } - if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { - throw exception(SPU_NOT_ENABLE, spu.getName()); - } - }); - return list; - } - - @Override - public void updateBrowseCount(Long id, int incrCount) { - productSpuMapper.updateBrowseCount(id , incrCount); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteSpu(Long id) { - // 校验存在 - validateSpuExists(id); - // 校验商品状态不是回收站不能删除 - ProductSpuDO spuDO = productSpuMapper.selectById(id); - // 判断 SPU 状态是否为回收站 - if (ObjectUtil.notEqual(spuDO.getStatus(), ProductSpuStatusEnum.RECYCLE.getStatus())) { - throw exception(SPU_NOT_RECYCLE); - } - // TODO 芋艿:【可选】参与活动中的商品,不允许删除??? - - // 删除 SPU - productSpuMapper.deleteById(id); - // 删除关联的 SKU - productSkuService.deleteSkuBySpuId(id); - } - - private ProductSpuDO validateSpuExists(Long id) { - ProductSpuDO spuDO = productSpuMapper.selectById(id); - if (spuDO == null) { - throw exception(SPU_NOT_EXISTS); - } - return spuDO; - } - - @Override - public ProductSpuDO getSpu(Long id) { - return productSpuMapper.selectById(id); - } - - @Override - public ProductSpuDO getSpu(Long id, boolean includeDeleted) { - if (includeDeleted) { - return productSpuMapper.selectByIdIncludeDeleted(id); - } - return getSpu(id); - } - - @Override - public List getSpuList(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return Collections.emptyList(); - } - Map spuMap = convertMap(productSpuMapper.selectBatchIds(ids), ProductSpuDO::getId); - // 需要按照 ids 顺序返回。例如说:店铺装修选择了 [3, 1, 2] 三个商品,返回结果还是 [3, 1, 2] 这样的顺序 - return convertList(ids, spuMap::get); - } - - @Override - public List getSpuListByStatus(Integer status) { - return productSpuMapper.selectList(ProductSpuDO::getStatus, status); - } - - @Override - public PageResult getSpuPage(ProductSpuPageReqVO pageReqVO) { - return productSpuMapper.selectPage(pageReqVO); - } - - @Override - public PageResult getSpuPage(AppProductSpuPageReqVO pageReqVO) { - // 查找时,如果查找某个分类编号,则包含它的子分类。因为顶级分类不包含商品 - Set categoryIds = new HashSet<>(); - if (pageReqVO.getCategoryId() != null && pageReqVO.getCategoryId() > 0) { - categoryIds.add(pageReqVO.getCategoryId()); - List categoryChildren = categoryService.getCategoryList(new ProductCategoryListReqVO() - .setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentId(pageReqVO.getCategoryId())); - categoryIds.addAll(convertList(categoryChildren, ProductCategoryDO::getId)); - } - if (CollUtil.isNotEmpty(pageReqVO.getCategoryIds())) { - categoryIds.addAll(pageReqVO.getCategoryIds()); - List categoryChildren = categoryService.getCategoryList(new ProductCategoryListReqVO() - .setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentIds(pageReqVO.getCategoryIds())); - categoryIds.addAll(convertList(categoryChildren, ProductCategoryDO::getId)); - } - // 分页查询 - return productSpuMapper.selectPage(pageReqVO, categoryIds); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateSpuStock(Map stockIncrCounts) { - stockIncrCounts.forEach((id, incCount) -> productSpuMapper.updateStock(id, incCount)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateSpuStatus(ProductSpuUpdateStatusReqVO updateReqVO) { - // 校验存在 - validateSpuExists(updateReqVO.getId()); - // TODO 芋艿:【可选】参与活动中的商品,不允许下架??? - - // 更新状态 - ProductSpuDO productSpuDO = productSpuMapper.selectById(updateReqVO.getId()).setStatus(updateReqVO.getStatus()); - productSpuMapper.updateById(productSpuDO); - } - - @Override - public Map getTabsCount() { - Map counts = Maps.newLinkedHashMapWithExpectedSize(5); - // 查询销售中的商品数量 - counts.put(ProductSpuPageReqVO.FOR_SALE, - productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus())); - // 查询仓库中的商品数量 - counts.put(ProductSpuPageReqVO.IN_WAREHOUSE, - productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus())); - // 查询售空的商品数量 - counts.put(ProductSpuPageReqVO.SOLD_OUT, - productSpuMapper.selectCount(ProductSpuDO::getStock, 0)); - // 查询触发警戒库存的商品数量 - counts.put(ProductSpuPageReqVO.ALERT_STOCK, - productSpuMapper.selectCount()); - // 查询回收站中的商品数量 - counts.put(ProductSpuPageReqVO.RECYCLE_BIN, - productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus())); - return counts; - } - - @Override - public Long getSpuCountByCategoryId(Long categoryId) { - return productSpuMapper.selectCount(ProductSpuDO::getCategoryId, categoryId); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java deleted file mode 100644 index 2da8613..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package cn.iocoder.yudao.module.product.service.brand; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import jakarta.annotation.Resource; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -/** -* {@link ProductBrandServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(ProductBrandServiceImpl.class) -public class ProductBrandServiceImplTest extends BaseDbUnitTest { - - @Resource - private ProductBrandServiceImpl brandService; - - @Resource - private ProductBrandMapper brandMapper; - - @Test - public void testCreateBrand_success() { - // 准备参数 - ProductBrandCreateReqVO reqVO = randomPojo(ProductBrandCreateReqVO.class); - - // 调用 - Long brandId = brandService.createBrand(reqVO); - // 断言 - assertNotNull(brandId); - // 校验记录的属性是否正确 - ProductBrandDO brand = brandMapper.selectById(brandId); - assertPojoEquals(reqVO, brand); - } - - @Test - public void testUpdateBrand_success() { - // mock 数据 - ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class); - brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class, o -> { - o.setId(dbBrand.getId()); // 设置更新的 ID - }); - - // 调用 - brandService.updateBrand(reqVO); - // 校验是否更新正确 - ProductBrandDO brand = brandMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, brand); - } - - @Test - public void testUpdateBrand_notExists() { - // 准备参数 - ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> brandService.updateBrand(reqVO), BRAND_NOT_EXISTS); - } - - @Test - public void testDeleteBrand_success() { - // mock 数据 - ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class); - brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbBrand.getId(); - - // 调用 - brandService.deleteBrand(id); - // 校验数据不存在了 - assertNull(brandMapper.selectById(id)); - } - - @Test - public void testDeleteBrand_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> brandService.deleteBrand(id), BRAND_NOT_EXISTS); - } - - @Test - public void testGetBrandPage() { - // mock 数据 - ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class, o -> { // 等会查询到 - o.setName("芋道源码"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2022, 2, 1)); - }); - brandMapper.insert(dbBrand); - // 测试 name 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setName("源码"))); - // 测试 status 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 createTime 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(buildTime(2022, 3, 1)))); - // 准备参数 - ProductBrandPageReqVO reqVO = new ProductBrandPageReqVO(); - reqVO.setName("芋道"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 2, 25)})); - - // 调用 - PageResult pageResult = brandService.getBrandPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbBrand, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java deleted file mode 100644 index 6478576..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java +++ /dev/null @@ -1,163 +0,0 @@ -package cn.iocoder.yudao.module.product.service.category; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; -import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -/** - * {@link ProductCategoryServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(ProductCategoryServiceImpl.class) -public class ProductCategoryServiceImplTest extends BaseDbUnitTest { - - @Resource - private ProductCategoryServiceImpl productCategoryService; - - @Resource - private ProductCategoryMapper productCategoryMapper; - - @Test - public void testCreateCategory_success() { - // 准备参数 - //ProductCategoryCreateReqVO reqVO = randomPojo(ProductCategoryCreateReqVO.class); - - // mock 父类 - //ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> { - // reqVO.setParentId(o.getId()); - // o.setParentId(PARENT_ID_NULL); - //}); - //productCategoryMapper.insert(parentProductCategory); - // - //// 调用 - //Long categoryId = productCategoryService.createCategory(reqVO); - //// 断言 - //assertNotNull(categoryId); - //// 校验记录的属性是否正确 - //ProductCategoryDO category = productCategoryMapper.selectById(categoryId); - //assertPojoEquals(reqVO, category); - } - - @Test - public void testUpdateCategory_success() { - // mock 数据 - ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class); - productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ProductCategorySaveReqVO reqVO = randomPojo(ProductCategorySaveReqVO.class, o -> { - o.setId(dbCategory.getId()); // 设置更新的 ID - }); - // mock 父类 - ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> o.setId(reqVO.getParentId())); - productCategoryMapper.insert(parentProductCategory); - - // 调用 - productCategoryService.updateCategory(reqVO); - // 校验是否更新正确 - ProductCategoryDO category = productCategoryMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, category); - } - - @Test - public void testUpdateCategory_notExists() { - // 准备参数 - ProductCategorySaveReqVO reqVO = randomPojo(ProductCategorySaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> productCategoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS); - } - - @Test - public void testDeleteCategory_success() { - // mock 数据 - ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class); - productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbCategory.getId(); - - // 调用 - productCategoryService.deleteCategory(id); - // 校验数据不存在了 - assertNull(productCategoryMapper.selectById(id)); - } - - @Test - public void testDeleteCategory_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); - } - - @Test - public void testGetCategoryLevel() { - // mock 数据 - ProductCategoryDO category1 = randomPojo(ProductCategoryDO.class, - o -> o.setParentId(PARENT_ID_NULL)); - productCategoryMapper.insert(category1); - ProductCategoryDO category2 = randomPojo(ProductCategoryDO.class, - o -> o.setParentId(category1.getId())); - productCategoryMapper.insert(category2); - ProductCategoryDO category3 = randomPojo(ProductCategoryDO.class, - o -> o.setParentId(category2.getId())); - productCategoryMapper.insert(category3); - - // 调用,并断言 - assertEquals(productCategoryService.getCategoryLevel(category1.getId()), 1); - assertEquals(productCategoryService.getCategoryLevel(category2.getId()), 2); - assertEquals(productCategoryService.getCategoryLevel(category3.getId()), 3); - } - - @Test - public void testGetCategoryList() { - // mock 数据 - ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class, o -> { // 等会查询到 - o.setName("奥特曼"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setParentId(PARENT_ID_NULL); - }); - productCategoryMapper.insert(dbCategory); - // 测试 name 不匹配 - productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("奥特块"))); - // 测试 status 不匹配 - productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 parentId 不匹配 - productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setParentId(3333L))); - // 准备参数 - ProductCategoryListReqVO reqVO = new ProductCategoryListReqVO(); - reqVO.setName("特曼"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setParentId(PARENT_ID_NULL); - - // 调用 - List list = productCategoryService.getCategoryList(reqVO); - List all = productCategoryService.getCategoryList(new ProductCategoryListReqVO()); - // 断言 - assertEquals(1, list.size()); - assertEquals(4, all.size()); - assertPojoEquals(dbCategory, list.get(0)); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java deleted file mode 100644 index 1b92e21..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package cn.iocoder.yudao.module.product.service.comment; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; -import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; -import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Lazy; - -import java.time.LocalDateTime; -import java.util.Date; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; - -// TODO 芋艿:单测详细 review 下 -/** - * {@link ProductCommentServiceImpl} 的单元测试类 - * - * @author wangzhs - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(ProductCommentServiceImpl.class) -public class ProductCommentServiceImplTest extends BaseDbUnitTest { - - @Resource - private ProductCommentMapper productCommentMapper; - - @Resource - @Lazy - private ProductCommentServiceImpl productCommentService; - - @MockBean - private ProductSpuService productSpuService; - @MockBean - private ProductSkuService productSkuService; - - public String generateNo() { - return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); - } - - public Long generateId() { - return RandomUtil.randomLong(100000, 999999); - } - - @Test - public void testCreateCommentAndGet_success() { - // mock 测试 - ProductCommentDO productComment = randomPojo(ProductCommentDO.class); - productCommentMapper.insert(productComment); - - // 断言 - // 校验记录的属性是否正确 - ProductCommentDO comment = productCommentMapper.selectById(productComment.getId()); - assertPojoEquals(productComment, comment); - } - - @Test - public void testGetCommentPage_success() { - // 准备参数 - ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> { - o.setUserNickname("王二狗"); - o.setSpuName("感冒药"); - o.setScores(ProductCommentScoresEnum.FOUR.getScores()); - o.setReplyStatus(Boolean.TRUE); - o.setVisible(Boolean.TRUE); - o.setId(generateId()); - o.setUserId(generateId()); - o.setAnonymous(Boolean.TRUE); - o.setOrderId(generateId()); - o.setOrderItemId(generateId()); - o.setSpuId(generateId()); - o.setSkuId(generateId()); - o.setDescriptionScores(ProductCommentScoresEnum.FOUR.getScores()); - o.setBenefitScores(ProductCommentScoresEnum.FOUR.getScores()); - o.setContent("真好吃"); - o.setReplyUserId(generateId()); - o.setReplyContent("确实"); - o.setReplyTime(LocalDateTime.now()); - o.setCreateTime(LocalDateTime.now()); - o.setUpdateTime(LocalDateTime.now()); - }); - productCommentMapper.insert(productComment); - - Long orderId = productComment.getOrderId(); - Long spuId = productComment.getSpuId(); - - // 测试 userNickname 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setUserNickname("王三").setScores(ProductCommentScoresEnum.ONE.getScores()))); - // 测试 orderId 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setOrderId(generateId()))); - // 测试 spuId 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuId(generateId()))); - // 测试 spuName 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuName("感康"))); - // 测试 scores 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setScores(ProductCommentScoresEnum.ONE.getScores()))); - // 测试 replied 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setReplyStatus(Boolean.FALSE))); - // 测试 visible 不匹配 - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setVisible(Boolean.FALSE))); - - // 调用 - ProductCommentPageReqVO productCommentPageReqVO = new ProductCommentPageReqVO(); - productCommentPageReqVO.setUserNickname("王二"); - productCommentPageReqVO.setOrderId(orderId); - productCommentPageReqVO.setSpuId(spuId); - productCommentPageReqVO.setSpuName("感冒药"); - productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores()); - productCommentPageReqVO.setReplyStatus(Boolean.TRUE); - - PageResult commentPage = productCommentService.getCommentPage(productCommentPageReqVO); - PageResult result = BeanUtils.toBean(productCommentMapper.selectPage(productCommentPageReqVO), - ProductCommentRespVO.class); - assertEquals(result.getTotal(), commentPage.getTotal()); - - PageResult all = productCommentService.getCommentPage(new ProductCommentPageReqVO()); - assertEquals(8, all.getTotal()); - - // 测试获取所有商品分页评论数据 - PageResult result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE); - assertEquals(7, result1.getTotal()); - - // 测试获取所有商品分页中评数据 - PageResult result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); - assertEquals(2, result2.getTotal()); - - // 测试获取指定 spuId 商品分页中评数据 - PageResult result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); - assertEquals(2, result3.getTotal()); - - // 测试分页 tab count - //AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentStatistics(spuId, Boolean.TRUE); - //assertEquals(4, tabsCount.getGoodCount()); - //assertEquals(2, tabsCount.getMediocreCount()); - //assertEquals(0, tabsCount.getNegativeCount()); - - } - - @Test - public void testUpdateCommentVisible_success() { - // mock 测试 - ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> { - o.setVisible(Boolean.TRUE); - }); - productCommentMapper.insert(productComment); - - Long productCommentId = productComment.getId(); - - ProductCommentUpdateVisibleReqVO updateReqVO = new ProductCommentUpdateVisibleReqVO(); - updateReqVO.setId(productCommentId); - updateReqVO.setVisible(Boolean.FALSE); - productCommentService.updateCommentVisible(updateReqVO); - - ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId); - assertFalse(productCommentDO.getVisible()); - } - - - @Test - public void testCommentReply_success() { - // mock 测试 - ProductCommentDO productComment = randomPojo(ProductCommentDO.class); - productCommentMapper.insert(productComment); - - Long productCommentId = productComment.getId(); - - ProductCommentReplyReqVO replyVO = new ProductCommentReplyReqVO(); - replyVO.setId(productCommentId); - replyVO.setReplyContent("测试"); - productCommentService.replyComment(replyVO, 1L); - - ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId); - assertEquals("测试", productCommentDO.getReplyContent()); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java deleted file mode 100644 index 5bd79a2..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java +++ /dev/null @@ -1,207 +0,0 @@ -package cn.iocoder.yudao.module.product.service.sku; - -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.framework.test.core.util.AssertUtils; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; -import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import jakarta.annotation.Resource; -import java.util.Arrays; -import java.util.List; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.verify; - -/** - * {@link ProductSkuServiceImpl} 的单元测试 - * - * @author 芋道源码 - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(ProductSkuServiceImpl.class) -public class ProductSkuServiceTest extends BaseDbUnitTest { - - @Resource - private ProductSkuService productSkuService; - - @Resource - private ProductSkuMapper productSkuMapper; - - @MockBean - private ProductSpuService productSpuService; - @MockBean - private ProductPropertyService productPropertyService; - @MockBean - private ProductPropertyValueService productPropertyValueService; - - public Long generateId() { - return RandomUtil.randomLong(100000, 999999); - } - - @Test - public void testUpdateSkuList() { - // mock 数据 - ProductSkuDO sku01 = randomPojo(ProductSkuDO.class, o -> { // 测试更新 - o.setSpuId(1L); - o.setProperties(singletonList(new ProductSkuDO.Property( - 10L, "颜色", 20L, "红色"))); - }); - productSkuMapper.insert(sku01); - ProductSkuDO sku02 = randomPojo(ProductSkuDO.class, o -> { // 测试删除 - o.setSpuId(1L); - o.setProperties(singletonList(new ProductSkuDO.Property( - 10L, "颜色", 30L, "蓝色"))); - - }); - productSkuMapper.insert(sku02); - // 准备参数 - Long spuId = 1L; - String spuName = "测试商品"; - List skus = Arrays.asList( - randomPojo(ProductSkuSaveReqVO.class, o -> { // 测试更新 - o.setProperties(singletonList(new ProductSkuSaveReqVO.Property( - 10L, "颜色", 20L, "红色"))); - }), - randomPojo(ProductSkuSaveReqVO.class, o -> { // 测试新增 - o.setProperties(singletonList(new ProductSkuSaveReqVO.Property( - 10L, "颜色", 20L, "红色"))); - }) - ); - - // 调用 - productSkuService.updateSkuList(spuId, skus); - // 断言 - List dbSkus = productSkuMapper.selectListBySpuId(spuId); - assertEquals(dbSkus.size(), 2); - // 断言更新的 - assertEquals(dbSkus.get(0).getId(), sku01.getId()); - assertPojoEquals(dbSkus.get(0), skus.get(0), "properties"); - assertEquals(skus.get(0).getProperties().size(), 1); - assertPojoEquals(dbSkus.get(0).getProperties().get(0), skus.get(0).getProperties().get(0)); - // 断言新增的 - assertNotEquals(dbSkus.get(1).getId(), sku02.getId()); - assertPojoEquals(dbSkus.get(1), skus.get(1), "properties"); - assertEquals(skus.get(1).getProperties().size(), 1); - assertPojoEquals(dbSkus.get(1).getProperties().get(0), skus.get(1).getProperties().get(0)); - } - - @Test - public void testUpdateSkuStock_incrSuccess() { - // 准备参数 - ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() - .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(10))); - // mock 数据 - productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> { - o.setId(1L).setSpuId(10L).setStock(20); - o.getProperties().forEach(p -> { - // 指定 id 范围 解决 Value too long - p.setPropertyId(generateId()); - p.setValueId(generateId()); - }); - })); - - // 调用 - productSkuService.updateSkuStock(updateStockReqDTO); - // 断言 - ProductSkuDO sku = productSkuMapper.selectById(1L); - assertEquals(sku.getStock(), 30); - verify(productSpuService).updateSpuStock(argThat(spuStockIncrCounts -> { - assertEquals(spuStockIncrCounts.size(), 1); - assertEquals(spuStockIncrCounts.get(10L), 10); - return true; - })); - } - - @Test - public void testUpdateSkuStock_decrSuccess() { - // 准备参数 - ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() - .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-10))); - // mock 数据 - productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> { - o.setId(1L).setSpuId(10L).setStock(20); - o.getProperties().forEach(p -> { - // 指定 id 范围 解决 Value too long - p.setPropertyId(generateId()); - p.setValueId(generateId()); - }); - })); - - // 调用 - productSkuService.updateSkuStock(updateStockReqDTO); - // 断言 - ProductSkuDO sku = productSkuMapper.selectById(1L); - assertEquals(sku.getStock(), 10); - verify(productSpuService).updateSpuStock(argThat(spuStockIncrCounts -> { - assertEquals(spuStockIncrCounts.size(), 1); - assertEquals(spuStockIncrCounts.get(10L), -10); - return true; - })); - } - - @Test - public void testUpdateSkuStock_decrFail() { - // 准备参数 - ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() - .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-30))); - // mock 数据 - productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> { - o.setId(1L).setSpuId(10L).setStock(20); - o.getProperties().forEach(p -> { - // 指定 id 范围 解决 Value too long - p.setPropertyId(generateId()); - p.setValueId(generateId()); - }); - })); - // 调用并断言 - AssertUtils.assertServiceException(() -> productSkuService.updateSkuStock(updateStockReqDTO), - SKU_STOCK_NOT_ENOUGH); - } - - @Test - public void testDeleteSku_success() { - ProductSkuDO dbSku = randomPojo(ProductSkuDO.class, o -> { - o.setId(generateId()).setSpuId(generateId()); - o.getProperties().forEach(p -> { - // 指定 id 范围 解决 Value too long - p.setPropertyId(generateId()); - p.setValueId(generateId()); - }); - }); - // mock 数据 - productSkuMapper.insert(dbSku); - // 准备参数 - Long id = dbSku.getId(); - - // 调用 - productSkuService.deleteSku(id); - // 校验数据不存在了 - assertNull(productSkuMapper.selectById(id)); - } - - @Test - public void testDeleteSku_notExists() { - // 准备参数 - Long id = 1L; - - // 调用, 并断言异常 - assertServiceException(() -> productSkuService.deleteSku(id), SKU_NOT_EXISTS); - } -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java deleted file mode 100755 index 0273465..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ /dev/null @@ -1,470 +0,0 @@ -package cn.iocoder.yudao.module.product.service.spu; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import cn.iocoder.yudao.module.product.service.brand.ProductBrandServiceImpl; -import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceImpl; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; -import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl; -import com.google.common.collect.Lists; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.assertj.core.util.Lists.newArrayList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -// TODO @芋艿:review 下单元测试 - -/** - * {@link ProductSpuServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(ProductSpuServiceImpl.class) -public class ProductSpuServiceImplTest extends BaseDbUnitTest { - - @Resource - private ProductSpuServiceImpl productSpuService; - - @Resource - private ProductSpuMapper productSpuMapper; - - @MockBean - private ProductSkuServiceImpl productSkuService; - @MockBean - private ProductCategoryServiceImpl categoryService; - @MockBean - private ProductBrandServiceImpl brandService; - @MockBean - private ProductPropertyService productPropertyService; - @MockBean - private ProductPropertyValueService productPropertyValueService; - - public String generateNo() { - return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); - } - - public Long generateId() { - return RandomUtil.randomLong(100000, 999999); - } - - public int generaInt(){return RandomUtil.randomInt(1,9999999);} - - // TODO @芋艿:单测后续 review 哈 - - @Test - public void testCreateSpu_success() { - // 准备参数 - ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{ - // 限制范围为正整数 - o.setCostPrice(generaInt()); - o.setPrice(generaInt()); - o.setMarketPrice(generaInt()); - o.setStock(generaInt()); - o.setFirstBrokeragePrice(generaInt()); - o.setSecondBrokeragePrice(generaInt()); - // 限制分数为两位数 - o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); - o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); - }); - ProductSpuSaveReqVO createReqVO = randomPojo(ProductSpuSaveReqVO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO)); - }); - when(categoryService.getCategoryLevel(eq(createReqVO.getCategoryId()))).thenReturn(2); - Long spu = productSpuService.createSpu(createReqVO); - ProductSpuDO productSpuDO = productSpuMapper.selectById(spu); - assertPojoEquals(createReqVO, productSpuDO); - } - - @Test - public void testUpdateSpu_success() { - // 准备参数 - ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - }); - productSpuMapper.insert(createReqVO); - // 准备参数 - ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{ - // 限制范围为正整数 - o.setCostPrice(generaInt()); - o.setPrice(generaInt()); - o.setMarketPrice(generaInt()); - o.setStock(generaInt()); - o.setFirstBrokeragePrice(generaInt()); - o.setSecondBrokeragePrice(generaInt()); - // 限制分数为两位数 - o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); - o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); - }); - // 准备参数 - ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class, o -> { - o.setId(createReqVO.getId()); // 设置更新的 ID - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO)); - }); - when(categoryService.getCategoryLevel(eq(reqVO.getCategoryId()))).thenReturn(2); - // 调用 - productSpuService.updateSpu(reqVO); - // 校验是否更新正确 - ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, spu); - } - - @Test - public void testValidateSpuExists_exception() { - ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class); - // 调用 - Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO)); - } - - @Test - void deleteSpu() { - // 准备参数 - ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - o.setStatus(-1); // 加入回收站才可删除 - }); - productSpuMapper.insert(createReqVO); - - // 调用 - productSpuService.deleteSpu(createReqVO.getId()); - - Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId())); - } - - @Test - void getSpu() { - // 准备参数 - ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - }); - productSpuMapper.insert(createReqVO); - - ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId()); - assertPojoEquals(createReqVO, spu); - } - - @Test - void getSpuList() { - // 准备参数 - ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - }), randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - })); - productSpuMapper.insertBatch(createReqVOs); - - // 调用 - List spuList = productSpuService.getSpuList(createReqVOs.stream().map(ProductSpuDO::getId).collect(Collectors.toList())); - Assertions.assertIterableEquals(createReqVOs, spuList); - } - - @Test - void getSpuPage_alarmStock_empty() { - // 准备参数 - ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(11); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - }), randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(11); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - })); - productSpuMapper.insertBatch(createReqVOs); - // 调用 - ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); - productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK); - - PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); - - PageResult result = PageResult.empty(); - Assertions.assertIterableEquals(result.getList(), spuPage.getList()); - assertEquals(spuPage.getTotal(), result.getTotal()); - } - - @Test - void getSpuPage_alarmStock() { - // 准备参数 - ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(5); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - }), randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(9); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - })); - productSpuMapper.insertBatch(createReqVOs); - // 调用 - ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); - productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK); - PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); - assertEquals(createReqVOs.size(), spuPage.getTotal()); - } - - @Test - void testGetSpuPage() { - // 准备参数 - ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - }); - - // 准备参数 - productSpuMapper.insert(createReqVO); - // 测试 status 不匹配 - productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus()))); - productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setStatus(ProductSpuStatusEnum.RECYCLE.getStatus()))); - // 测试 SpecType 不匹配 - productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setSpecType(true))); - // 测试 BrandId 不匹配 - productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setBrandId(generateId()))); - // 测试 CategoryId 不匹配 - productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setCategoryId(generateId()))); - - // 调用 - ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); - // 查询条件 按需打开 - //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK); - //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.RECYCLE_BIN); - //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.FOR_SALE); - //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.IN_WAREHOUSE); - //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.SOLD_OUT); - //productSpuPageReqVO.setName(createReqVO.getName()); - //productSpuPageReqVO.setCategoryId(createReqVO.getCategoryId()); - - PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); - - assertEquals(1, spuPage.getTotal()); - } - - /** - * 生成笛卡尔积 - * - * @param data 数据 - * @return 笛卡尔积 - */ - public static List> cartesianProduct(List> data) { - List> res = null; // 结果集(当前为第N个List,则该处存放的就为前N-1个List的笛卡尔积集合) - for (List list : data) { // 遍历数据 - List> temp = new ArrayList<>(); // 临时结果集,存放本次循环后生成的笛卡尔积集合 - if (res == null) { // 结果集为null表示第一次循环既list为第一个List - for (T t : list) { // 便利第一个List - // 利用stream生成List,第一个List的笛卡尔积集合约等于自己本身(需要创建一个List并把对象添加到当中),存放到临时结果集 - temp.add(Stream.of(t).collect(Collectors.toList())); - } - res = temp; // 将临时结果集赋值给结果集 - continue; // 跳过本次循环 - } - // 不为第一个List,计算前面的集合(笛卡尔积)和当前List的笛卡尔积集合 - for (T t : list) { // 便利 - for (List rl : res) { // 便利前面的笛卡尔积集合 - // 利用stream生成List - temp.add(Stream.concat(rl.stream(), Stream.of(t)).collect(Collectors.toList())); - } - } - res = temp; // 将临时结果集赋值给结果集 - } - // 返回结果 - return res; - } - - @Test - public void testUpdateSpuStock() { - // 准备参数 - Map stockIncrCounts = MapUtil.builder(1L, 10).put(2L, -20).build(); - // mock 方法(数据) - productSpuMapper.insert(randomPojo(ProductSpuDO.class, o ->{ - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - o.setId(1L).setStock(20); - })); - productSpuMapper.insert(randomPojo(ProductSpuDO.class, o -> { - o.setCategoryId(generateId()); - o.setBrandId(generateId()); - o.setDeliveryTemplateId(generateId()); - o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 - o.setPrice(generaInt()); // 限制范围为正整数 - o.setMarketPrice(generaInt()); // 限制范围为正整数 - o.setCostPrice(generaInt()); // 限制范围为正整数 - o.setStock(generaInt()); // 限制范围为正整数 - o.setGiveIntegral(generaInt()); // 限制范围为正整数 - o.setSalesCount(generaInt()); // 限制范围为正整数 - o.setBrowseCount(generaInt()); // 限制范围为正整数 - o.setId(2L).setStock(30); - })); - - // 调用 - productSpuService.updateSpuStock(stockIncrCounts); - // 断言 - assertEquals(productSpuService.getSpu(1L).getStock(), 30); - assertEquals(productSpuService.getSpu(2L).getStock(), 10); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml b/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml deleted file mode 100644 index 36aec5c..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml +++ /dev/null @@ -1,49 +0,0 @@ -spring: - main: - lazy-initialization: true # 开启懒加载,加快速度 - banner-mode: off # 单元测试,禁用 Banner - ---- #################### 数据库相关配置 #################### - -spring: - # 数据源配置项 - datasource: - name: ruoyi-vue-pro - url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 - driver-class-name: org.h2.Driver - username: sa - password: - druid: - async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 - initial-size: 1 # 单元测试,配置为 1,提升启动速度 - sql: - init: - schema-locations: classpath:/sql/create_tables.sql - - # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 - data: - redis: - host: 127.0.0.1 # 地址 - port: 16379 # 端口(单元测试,使用 16379 端口) - database: 0 # 数据库索引 - -mybatis-plus: - lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject - ---- #################### 定时任务相关配置 #################### - ---- #################### 配置中心相关配置 #################### - ---- #################### 服务保障相关配置 #################### - -# Lock4j 配置项(单元测试,禁用 Lock4j) - ---- #################### 监控相关配置 #################### - ---- #################### 芋道相关配置 #################### - -# 芋道配置项,设置当前项目所有自定义的配置 -yudao: - info: - base-package: cn.iocoder.yudao diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml b/yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml deleted file mode 100644 index daf756b..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql deleted file mode 100644 index e9616cd..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql +++ /dev/null @@ -1,7 +0,0 @@ -DELETE FROM "product_sku"; -DELETE FROM "product_spu"; -DELETE FROM "product_category"; -DELETE FROM "product_brand"; -DELETE FROM "product_property"; -DELETE FROM "product_property_value"; -DELETE FROM "product_comment"; diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql deleted file mode 100644 index f0f0c70..0000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql +++ /dev/null @@ -1,157 +0,0 @@ -CREATE TABLE IF NOT EXISTS `product_sku` ( - `id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - `spu_id` bigint NOT NULL COMMENT 'spu编号', - `properties` varchar(512) DEFAULT NULL COMMENT '属性数组,JSON 格式', - `price` int NOT NULL DEFAULT '-1' COMMENT '商品价格,单位:分', - `market_price` int DEFAULT NULL COMMENT '市场价,单位:分', - `cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分', - `bar_code` varchar(64) DEFAULT NULL COMMENT 'SKU 的条形码', - `pic_url` varchar(256) NOT NULL COMMENT '图片地址', - `stock` int DEFAULT NULL COMMENT '库存', - `weight` double DEFAULT NULL COMMENT '商品重量,单位:kg 千克', - `volume` double DEFAULT NULL COMMENT '商品体积,单位:m^3 平米', - `sub_commission_first_price` int DEFAULT NULL COMMENT '一级分销的佣金,单位:分', - `sub_commission_second_price` int DEFAULT NULL COMMENT '二级分销的佣金,单位:分', - `sales_count` int DEFAULT NULL COMMENT '商品销量', - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY("id") -) COMMENT '商品sku'; - -CREATE TABLE IF NOT EXISTS `product_spu` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品 SPU 编号,自增', - `name` varchar(128) NOT NULL COMMENT '商品名称', - `keyword` varchar(256) NOT NULL COMMENT '关键字', - `introduction` varchar(256) NOT NULL COMMENT '商品简介', - `description` text NOT NULL COMMENT '商品详情', - `bar_code` varchar(64) NOT NULL COMMENT '条形码', - `category_id` bigint NOT NULL COMMENT '商品分类编号', - `brand_id` int DEFAULT NULL COMMENT '商品品牌编号', - `pic_url` varchar(256) NOT NULL COMMENT '商品封面图', - `slider_pic_urls` varchar(2000) DEFAULT '' COMMENT '商品轮播图地址\n 数组,以逗号分隔\n 最多上传15张', - `video_url` varchar(256) DEFAULT NULL COMMENT '商品视频', - `unit` tinyint NOT NULL COMMENT '单位', - `sort` int NOT NULL DEFAULT '0' COMMENT '排序字段', - `status` tinyint NOT NULL COMMENT '商品状态: 0 上架(开启) 1 下架(禁用)-1 回收', - `spec_type` bit(1) NOT NULL COMMENT '规格类型:0 单规格 1 多规格', - `price` int NOT NULL DEFAULT '-1' COMMENT '商品价格,单位使用:分', - `market_price` int NOT NULL COMMENT '市场价,单位使用:分', - `cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分', - `stock` int NOT NULL DEFAULT '0' COMMENT '库存', - `delivery_template_id` bigint NOT NULL COMMENT '物流配置模板编号', - `recommend_hot` bit(1) NOT NULL COMMENT '是否热卖推荐: 0 默认 1 热卖', - `recommend_benefit` bit(1) NOT NULL COMMENT '是否优惠推荐: 0 默认 1 优选', - `recommend_best` bit(1) NOT NULL COMMENT '是否精品推荐: 0 默认 1 精品', - `recommend_new` bit(1) NOT NULL COMMENT '是否新品推荐: 0 默认 1 新品', - `recommend_good` bit(1) NOT NULL COMMENT '是否优品推荐', - `give_integral` int NOT NULL COMMENT '赠送积分', - `give_coupon_template_ids` varchar(512) DEFAULT '' COMMENT '赠送的优惠劵编号的数组', - `sub_commission_type` bit(1) NOT NULL COMMENT '分销类型', - `activity_orders` varchar(16) NOT NULL DEFAULT '' COMMENT '活动显示排序0=默认, 1=秒杀,2=砍价,3=拼团', - `sales_count` int DEFAULT '0' COMMENT '商品销量', - `virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量', - `browse_count` int DEFAULT '0' COMMENT '商品点击量', - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY("id") -) COMMENT '商品spu'; - -CREATE TABLE IF NOT EXISTS `product_category` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号', - `parent_id` bigint NOT NULL COMMENT '父分类编号', - `name` varchar(255) NOT NULL COMMENT '分类名称', - `pic_url` varchar(255) NOT NULL COMMENT '移动端分类图', - `big_pic_url` varchar(255) DEFAULT NULL COMMENT 'PC 端分类图', - `sort` int DEFAULT '0' COMMENT '分类排序', - `status` tinyint NOT NULL COMMENT '开启状态', - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY("id") -) COMMENT '商品分类'; - -CREATE TABLE IF NOT EXISTS `product_brand` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号', - `name` varchar(255) NOT NULL COMMENT '品牌名称', - `pic_url` varchar(255) NOT NULL COMMENT '品牌图片', - `sort` int DEFAULT '0' COMMENT '品牌排序', - `description` varchar(1024) DEFAULT NULL COMMENT '品牌描述', - `status` tinyint NOT NULL COMMENT '状态', - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY("id") -) COMMENT '商品品牌'; - -CREATE TABLE IF NOT EXISTS `product_property` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', - `name` varchar(64) DEFAULT NULL COMMENT '规格名称', - `status` tinyint DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用', - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - `remark` varchar(255) DEFAULT NULL COMMENT '备注', - PRIMARY KEY("id") -) COMMENT '规格名称'; - -CREATE TABLE IF NOT EXISTS `product_property_value` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', - `property_id` bigint DEFAULT NULL COMMENT '规格键id', - `name` varchar(128) DEFAULT NULL COMMENT '规格值名字', - `status` tinyint DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用', - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - `remark` varchar(255) DEFAULT NULL COMMENT '备注', - PRIMARY KEY("id") -) COMMENT '规格值'; - -DROP TABLE IF EXISTS `product_comment` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论编号,主键自增', - `user_id` bigint DEFAULT NULL COMMENT '评价人的用户编号关联 MemberUserDO 的 id 编号', - `user_nickname` varchar(255) DEFAULT NULL COMMENT '评价人名称', - `user_avatar` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '评价人头像', - `anonymous` bit(1) DEFAULT NULL COMMENT '是否匿名', - `order_id` bigint DEFAULT NULL COMMENT '交易订单编号关联 TradeOrderDO 的 id 编号', - `order_item_id` bigint DEFAULT NULL COMMENT '交易订单项编号关联 TradeOrderItemDO 的 id 编号', - `spu_id` bigint DEFAULT NULL COMMENT '商品 SPU 编号关联 ProductSpuDO 的 id', - `spu_name` varchar(255) DEFAULT NULL COMMENT '商品 SPU 名称', - `sku_id` bigint DEFAULT NULL COMMENT '商品 SKU 编号关联 ProductSkuDO 的 id 编号', - `visible` bit(1) DEFAULT NULL COMMENT '是否可见true:显示false:隐藏', - `scores` tinyint DEFAULT NULL COMMENT '评分星级1-5分', - `description_scores` tinyint DEFAULT NULL COMMENT '描述星级1-5 星', - `benefit_scores` tinyint DEFAULT NULL COMMENT '服务星级1-5 星', - `content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '评论内容', - `pic_urls` varchar(4096) DEFAULT NULL COMMENT '评论图片地址数组', - `reply_status` bit(1) DEFAULT NULL COMMENT '商家是否回复', - `reply_user_id` bigint DEFAULT NULL COMMENT '回复管理员编号关联 AdminUserDO 的 id 编号', - `reply_content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '商家回复内容', - `reply_time` datetime DEFAULT NULL COMMENT '商家回复时间', - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '商品评论'; \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/pom.xml b/yudao-module-mall/yudao-module-product/pom.xml new file mode 100644 index 0000000..07bd9d0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/pom.xml @@ -0,0 +1,58 @@ + + + + cn.iocoder.boot + yudao-module-mall + ${revision} + + 4.0.0 + yudao-module-product + jar + + ${project.artifactId} + + product 模块,主要实现商品相关功能 + 例如:品牌、商品分类、spu、sku等功能。 + + + + + cn.iocoder.boot + yudao-module-member + ${revision} + + + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java new file mode 100644 index 0000000..38feb96 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.product.api.category; + +import java.util.Collection; + +/** + * 商品分类 API 接口 + * + * @author owen + */ +public interface ProductCategoryApi { + + /** + * 校验商品分类是否有效。如下情况,视为无效: + * 1. 商品分类编号不存在 + * 2. 商品分类被禁用 + * + * @param ids 商品分类编号数组 + */ + void validateCategoryList(Collection ids); +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java new file mode 100644 index 0000000..b339a47 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.product.api.category; + +import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; +import java.util.Collection; + +/** + * 商品分类 API 接口实现类 + * + * @author owen + */ +@Service +@Validated +public class ProductCategoryApiImpl implements ProductCategoryApi { + + @Resource + private ProductCategoryService productCategoryService; + + @Override + public void validateCategoryList(Collection ids) { + productCategoryService.validateCategoryList(ids); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java new file mode 100644 index 0000000..b0ba1f7 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.product.api.comment; + +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; + +/** + * 产品评论 API 接口 + * + * @author HUIHUI + */ +public interface ProductCommentApi { + + /** + * 创建评论 + * + * @param createReqDTO 评论参数 + * @return 返回评论创建后的 id + */ + Long createComment(ProductCommentCreateReqDTO createReqDTO); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java new file mode 100644 index 0000000..7bda131 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.product.api.comment; + +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; + +/** + * 商品评论 API 实现类 + * + * @author HUIHUI + */ +@Service +@Validated +public class ProductCommentApiImpl implements ProductCommentApi { + + @Resource + private ProductCommentService productCommentService; + + @Override + public Long createComment(ProductCommentCreateReqDTO createReqDTO) { + return productCommentService.createComment(createReqDTO); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java new file mode 100644 index 0000000..66caeed --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.product.api.comment.dto; + +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import java.util.List; + +/** + * 评论创建请求 DTO + * + * @author HUIHUI + */ +@Data +public class ProductCommentCreateReqDTO { + + /** + * 商品 SKU 编号 + */ + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + /** + * 订单编号 + */ + private Long orderId; + /** + * 交易订单项编号 + */ + private Long orderItemId; + + /** + * 描述星级 1-5 分 + */ + @NotNull(message = "描述星级不能为空") + private Integer descriptionScores; + /** + * 服务星级 1-5 分 + */ + @NotNull(message = "服务星级不能为空") + private Integer benefitScores; + /** + * 评论内容 + */ + @NotNull(message = "评论内容不能为空") + private String content; + /** + * 评论图片地址数组,以逗号分隔最多上传 9 张 + */ + private List picUrls; + + /** + * 是否匿名 + */ + @NotNull(message = "是否匿名不能为空") + private Boolean anonymous; + /** + * 评价人 + */ + @NotNull(message = "评价人不能为空") + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java new file mode 100644 index 0000000..e3e7412 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/package-info.java @@ -0,0 +1,4 @@ +/** + * product API 包,定义并实现提供给其它模块的 API + */ +package cn.iocoder.yudao.module.product.api; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java new file mode 100644 index 0000000..2a1ab71 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.product.api.property.dto; + +import lombok.Data; + +/** + * 商品属性项的明细 Response DTO + * + * @author 芋道源码 + */ +@Data +public class ProductPropertyValueDetailRespDTO { + + /** + * 属性的编号 + */ + private Long propertyId; + + /** + * 属性的名称 + */ + private String propertyName; + + /** + * 属性值的编号 + */ + private Long valueId; + + /** + * 属性值的名称 + */ + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java new file mode 100644 index 0000000..f6e6034 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.product.api.sku; + +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * 商品 SKU API 接口 + * + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface ProductSkuApi { + + /** + * 查询 SKU 信息 + * + * @param id SKU 编号 + * @return SKU 信息 + */ + ProductSkuRespDTO getSku(Long id); + + /** + * 批量查询 SKU 数组 + * + * @param ids SKU 编号列表 + * @return SKU 数组 + */ + List getSkuList(Collection ids); + + /** + * 批量查询 SKU MAP + * + * @param ids SKU 编号列表 + * @return SKU MAP + */ + default Map getSkuMap(Collection ids) { + return convertMap(getSkuList(ids), ProductSkuRespDTO::getId); + } + + /** + * 批量查询 SKU 数组 + * + * @param spuIds SPU 编号列表 + * @return SKU 数组 + */ + List getSkuListBySpuId(Collection spuIds); + + /** + * 更新 SKU 库存(增加 or 减少) + * + * @param updateStockReqDTO 更新请求 + */ + void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java new file mode 100644 index 0000000..dbdc37e --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.product.api.sku; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +/** + * 商品 SKU API 实现类 + * + * @author LeeYan9 + * @since 2022-09-06 + */ +@Service +@Validated +public class ProductSkuApiImpl implements ProductSkuApi { + + @Resource + private ProductSkuService productSkuService; + + @Override + public ProductSkuRespDTO getSku(Long id) { + ProductSkuDO sku = productSkuService.getSku(id); + return BeanUtils.toBean(sku, ProductSkuRespDTO.class); + } + + @Override + public List getSkuList(Collection ids) { + List skus = productSkuService.getSkuList(ids); + return BeanUtils.toBean(skus, ProductSkuRespDTO.class); + } + + @Override + public List getSkuListBySpuId(Collection spuIds) { + List skus = productSkuService.getSkuListBySpuId(spuIds); + return BeanUtils.toBean(skus, ProductSkuRespDTO.class); + } + + @Override + public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) { + productSkuService.updateSkuStock(updateStockReqDTO); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java new file mode 100644 index 0000000..338c4dd --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.product.api.sku.dto; + +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import lombok.Data; + +import java.util.List; + +/** + * 商品 SKU 信息 Response DTO + * + * @author LeeYan9 + * @since 2022-08-26 + */ +@Data +public class ProductSkuRespDTO { + + /** + * 商品 SKU 编号,自增 + */ + private Long id; + /** + * SPU 编号 + */ + private Long spuId; + + /** + * 属性数组 + */ + private List properties; + /** + * 销售价格,单位:分 + */ + private Integer price; + /** + * 市场价,单位:分 + */ + private Integer marketPrice; + /** + * 成本价,单位:分 + */ + private Integer costPrice; + /** + * SKU 的条形码 + */ + private String barCode; + /** + * 图片地址 + */ + private String picUrl; + /** + * 库存 + */ + private Integer stock; + /** + * 商品重量,单位:kg 千克 + */ + private Double weight; + /** + * 商品体积,单位:m^3 平米 + */ + private Double volume; + /** + * 一级分销的佣金,单位:分 + */ + private Integer firstBrokeragePrice; + /** + * 二级分销的佣金,单位:分 + */ + private Integer secondBrokeragePrice; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java new file mode 100644 index 0000000..98c63c7 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuUpdateStockReqDTO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.product.api.sku.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import jakarta.validation.constraints.NotNull; +import java.util.List; + +/** + * 商品 SKU 更新库存 Request DTO + * + * @author LeeYan9 + * @since 2022-08-26 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ProductSkuUpdateStockReqDTO { + + /** + * 商品 SKU + */ + @NotNull(message = "商品 SKU 不能为空") + private List items; + + @Data + public static class Item { + + /** + * 商品 SKU 编号 + */ + @NotNull(message = "商品 SKU 编号不能为空") + private Long id; + + /** + * 库存变化数量 + * + * 正数:增加库存 + * 负数:扣减库存 + */ + @NotNull(message = "库存变化数量不能为空") + private Integer incrCount; + + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java new file mode 100644 index 0000000..499a0ca --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.product.api.spu; + +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * 商品 SPU API 接口 + * + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface ProductSpuApi { + + /** + * 批量查询 SPU 数组 + * + * @param ids SPU 编号列表 + * @return SPU 数组 + */ + List getSpuList(Collection ids); + + /** + * 批量查询 SPU MAP + * + * @param ids SPU 编号列表 + * @return SPU MAP + */ + default Map getSpuMap(Collection ids) { + return convertMap(getSpuList(ids), ProductSpuRespDTO::getId); + } + + /** + * 批量查询 SPU 数组,并且校验是否 SPU 是否有效。 + * + * 如下情况,视为无效: + * 1. 商品编号不存在 + * 2. 商品被禁用 + * + * @param ids SPU 编号列表 + * @return SPU 数组 + */ + List validateSpuList(Collection ids); + + /** + * 获得 SPU + * + * @return SPU + */ + ProductSpuRespDTO getSpu(Long id); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java new file mode 100644 index 0000000..050f9f5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.product.api.spu; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +/** + * 商品 SPU API 接口实现类 + * + * @author LeeYan9 + * @since 2022-09-06 + */ +@Service +@Validated +public class ProductSpuApiImpl implements ProductSpuApi { + + @Resource + private ProductSpuService spuService; + + @Override + public List getSpuList(Collection ids) { + List spus = spuService.getSpuList(ids); + return BeanUtils.toBean(spus, ProductSpuRespDTO.class); + } + + @Override + public List validateSpuList(Collection ids) { + List spus = spuService.validateSpuList(ids); + return BeanUtils.toBean(spus, ProductSpuRespDTO.class); + } + + @Override + public ProductSpuRespDTO getSpu(Long id) { + ProductSpuDO spu = spuService.getSpu(id); + return BeanUtils.toBean(spu, ProductSpuRespDTO.class); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java new file mode 100644 index 0000000..60fb0bc --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.product.api.spu.dto; + +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import lombok.Data; + +import java.util.List; + +/** + * 商品 SPU 信息 Response DTO + * + * @author LeeYan9 + * @since 2022-08-26 + */ +@Data +public class ProductSpuRespDTO { + + /** + * 商品 SPU 编号,自增 + */ + private Long id; + + // ========== 基本信息 ========= + + /** + * 商品名称 + */ + private String name; + + /** + * 商品分类编号 + */ + private Long categoryId; + /** + * 商品封面图 + */ + private String picUrl; + + /** + * 商品状态 + *

+ * 枚举 {@link ProductSpuStatusEnum} + */ + private Integer status; + + // ========== SKU 相关字段 ========= + + /** + * 规格类型 + * + * false - 单规格 + * true - 多规格 + */ + private Boolean specType; + /** + * 商品价格,单位使用:分 + */ + private Integer price; + /** + * 市场价,单位使用:分 + */ + private Integer marketPrice; + /** + * 成本价,单位使用:分 + */ + private Integer costPrice; + /** + * 库存 + */ + private Integer stock; + + // ========== 物流相关字段 ========= + + /** + * 配送方式数组 + * + * 对应 DeliveryTypeEnum 枚举 + */ + private List deliveryTypes; + + /** + * 物流配置模板编号 + * + * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 + */ + private Long deliveryTemplateId; + + // ========== 营销相关字段 ========= + + /** + * 赠送积分 + */ + private Integer giveIntegral; + + // ========== 分销相关字段 ========= + + /** + * 分销类型 + * + * false - 默认 + * true - 自行设置 + */ + private Boolean subCommissionType; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java new file mode 100644 index 0000000..aff47c7 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; +import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import java.util.Comparator; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 商品品牌") +@RestController +@RequestMapping("/product/brand") +@Validated +public class ProductBrandController { + + @Resource + private ProductBrandService brandService; + + @PostMapping("/create") + @Operation(summary = "创建品牌") + @PreAuthorize("@ss.hasPermission('product:brand:create')") + public CommonResult createBrand(@Valid @RequestBody ProductBrandCreateReqVO createReqVO) { + return success(brandService.createBrand(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新品牌") + @PreAuthorize("@ss.hasPermission('product:brand:update')") + public CommonResult updateBrand(@Valid @RequestBody ProductBrandUpdateReqVO updateReqVO) { + brandService.updateBrand(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除品牌") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:brand:delete')") + public CommonResult deleteBrand(@RequestParam("id") Long id) { + brandService.deleteBrand(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得品牌") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:brand:query')") + public CommonResult getBrand(@RequestParam("id") Long id) { + ProductBrandDO brand = brandService.getBrand(id); + return success(ProductBrandConvert.INSTANCE.convert(brand)); + } + + @GetMapping("/list-all-simple") + @Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项") + public CommonResult> getSimpleBrandList() { + // 获取品牌列表,只要开启状态的 + List list = brandService.getBrandListByStatus(CommonStatusEnum.ENABLE.getStatus()); + // 排序后,返回给前端 + return success(ProductBrandConvert.INSTANCE.convertList1(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得品牌分页") + @PreAuthorize("@ss.hasPermission('product:brand:query')") + public CommonResult> getBrandPage(@Valid ProductBrandPageReqVO pageVO) { + PageResult pageResult = brandService.getBrandPage(pageVO); + return success(ProductBrandConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/list") + @Operation(summary = "获得品牌列表") + @PreAuthorize("@ss.hasPermission('product:brand:query')") + public CommonResult> getBrandList(@Valid ProductBrandListReqVO listVO) { + List list = brandService.getBrandList(listVO); + list.sort(Comparator.comparing(ProductBrandDO::getSort)); + return success(ProductBrandConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java new file mode 100644 index 0000000..152de72 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandBaseVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +/** +* 商品品牌 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class ProductBrandBaseVO { + + @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") + @NotNull(message = "品牌名称不能为空") + private String name; + + @Schema(description = "品牌图片", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "品牌图片不能为空") + private String picUrl; + + @Schema(description = "品牌排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "品牌排序不能为空") + private Integer sort; + + @Schema(description = "品牌描述", example = "描述") + private String description; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java new file mode 100644 index 0000000..dc85a47 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 商品品牌创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductBrandCreateReqVO extends ProductBrandBaseVO { + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java new file mode 100644 index 0000000..ed93ff0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandListReqVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 商品品牌分页 Request VO") +@Data +public class ProductBrandListReqVO { + + @Schema(description = "品牌名称", example = "苹果") + private String name; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java new file mode 100644 index 0000000..3a6efc9 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 商品品牌分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductBrandPageReqVO extends PageParam { + + @Schema(description = "品牌名称", example = "苹果") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Schema(description = "创建时间") + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java new file mode 100644 index 0000000..486fe76 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 品牌 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductBrandRespVO extends ProductBrandBaseVO { + + @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java new file mode 100644 index 0000000..6379a5f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "管理后台 - 品牌精简信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ProductBrandSimpleRespVO { + + @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") + private String name; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java new file mode 100644 index 0000000..b9585b6 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.product.controller.admin.brand.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商品品牌更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductBrandUpdateReqVO extends ProductBrandBaseVO { + + @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "品牌编号不能为空") + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java new file mode 100644 index 0000000..f3f5980 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.product.controller.admin.category; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Comparator; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 商品分类") +@RestController +@RequestMapping("/product/category") +@Validated +public class ProductCategoryController { + + @Resource + private ProductCategoryService categoryService; + + @PostMapping("/create") + @Operation(summary = "创建商品分类") + @PreAuthorize("@ss.hasPermission('product:category:create')") + public CommonResult createCategory(@Valid @RequestBody ProductCategorySaveReqVO createReqVO) { + return success(categoryService.createCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新商品分类") + @PreAuthorize("@ss.hasPermission('product:category:update')") + public CommonResult updateCategory(@Valid @RequestBody ProductCategorySaveReqVO updateReqVO) { + categoryService.updateCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除商品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('product:category:delete')") + public CommonResult deleteCategory(@RequestParam("id") Long id) { + categoryService.deleteCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得商品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:category:query')") + public CommonResult getCategory(@RequestParam("id") Long id) { + ProductCategoryDO category = categoryService.getCategory(id); + return success(BeanUtils.toBean(category, ProductCategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得商品分类列表") + @PreAuthorize("@ss.hasPermission('product:category:query')") + public CommonResult> getCategoryList(@Valid ProductCategoryListReqVO listReqVO) { + List list = categoryService.getCategoryList(listReqVO); + list.sort(Comparator.comparing(ProductCategoryDO::getSort)); + return success(BeanUtils.toBean(list, ProductCategoryRespVO.class)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java new file mode 100644 index 0000000..9e5364c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Collection; + +@Schema(description = "管理后台 - 商品分类列表查询 Request VO") +@Data +public class ProductCategoryListReqVO { + + @Schema(description = "分类名称", example = "办公文具") + private String name; + + @Schema(description = "开启状态", example = "0") + private Integer status; + + @Schema(description = "父分类编号", example = "1") + private Long parentId; + + @Schema(description = "父分类编号数组", example = "1,2,3") + private Collection parentIds; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java new file mode 100644 index 0000000..c8ef92e --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 商品分类 Response VO") +@Data +public class ProductCategoryRespVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具") + private String name; + + @Schema(description = "移动端分类图", requiredMode = Schema.RequiredMode.REQUIRED) + private String picUrl; + + @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "分类描述", example = "描述") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java new file mode 100644 index 0000000..5f03df1 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategorySaveReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 商品分类新增/更新 Request VO") +@Data +public class ProductCategorySaveReqVO { + + @Schema(description = "分类编号", example = "2") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "父分类编号不能为空") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具") + @NotBlank(message = "分类名称不能为空") + private String name; + + @Schema(description = "移动端分类图", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "移动端分类图不能为空") + private String picUrl; + + @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "开启状态不能为空") + private Integer status; + + @Schema(description = "分类描述", example = "描述") + private String description; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.http diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java new file mode 100644 index 0000000..3cac6d0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.product.controller.admin.comment; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.*; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 商品评价") +@RestController +@RequestMapping("/product/comment") +@Validated +public class ProductCommentController { + + @Resource + private ProductCommentService productCommentService; + + @GetMapping("/page") + @Operation(summary = "获得商品评价分页") + @PreAuthorize("@ss.hasPermission('product:comment:query')") + public CommonResult> getCommentPage(@Valid ProductCommentPageReqVO pageVO) { + PageResult pageResult = productCommentService.getCommentPage(pageVO); + return success(BeanUtils.toBean(pageResult, ProductCommentRespVO.class)); + } + + @PutMapping("/update-visible") + @Operation(summary = "显示 / 隐藏评论") + @PreAuthorize("@ss.hasPermission('product:comment:update')") + public CommonResult updateCommentVisible(@Valid @RequestBody ProductCommentUpdateVisibleReqVO updateReqVO) { + productCommentService.updateCommentVisible(updateReqVO); + return success(true); + } + + @PutMapping("/reply") + @Operation(summary = "商家回复") + @PreAuthorize("@ss.hasPermission('product:comment:update')") + public CommonResult commentReply(@Valid @RequestBody ProductCommentReplyReqVO replyVO) { + productCommentService.replyComment(replyVO, getLoginUserId()); + return success(true); + } + + @PostMapping("/create") + @Operation(summary = "添加自评") + @PreAuthorize("@ss.hasPermission('product:comment:update')") + public CommonResult createComment(@Valid @RequestBody ProductCommentCreateReqVO createReqVO) { + productCommentService.createComment(createReqVO); + return success(true); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java new file mode 100644 index 0000000..b411db0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.product.controller.admin.comment.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - 商品评价创建 Request VO") +@Data +public class ProductCommentCreateReqVO { + + @Schema(description = "评价人", requiredMode = Schema.RequiredMode.REQUIRED, example = "16868") + private Long userId; + + @Schema(description = "评价订单项", requiredMode = Schema.RequiredMode.REQUIRED, example = "19292") + private Long orderItemId; + + @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小姑凉") + @NotNull(message = "评价人名称不能为空") + private String userNickname; + + @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + @NotNull(message = "评价人头像不能为空") + private String userAvatar; + + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "描述星级不能为空") + private Integer descriptionScores; + + @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "服务星级分不能为空") + private Integer benefitScores; + + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿起来非常丝滑凉快") + @NotNull(message = "评论内容不能为空") + private String content; + + @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, + example = "[https://www.iocoder.cn/xx.png]") + @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") + private List picUrls; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java new file mode 100644 index 0000000..3791f57 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.product.controller.admin.comment.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 商品评价分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductCommentPageReqVO extends PageParam { + + @Schema(description = "评价人名称", example = "王二狗") + private String userNickname; + + @Schema(description = "交易订单编号", example = "24428") + private Long orderId; + + @Schema(description = "商品SPU编号", example = "29502") + private Long spuId; + + @Schema(description = "商品SPU名称", example = "感冒药") + private String spuName; + + @Schema(description = "评分星级 1-5 分", example = "5") + @InEnum(ProductCommentScoresEnum.class) + private Integer scores; + + @Schema(description = "商家是否回复", example = "true") + private Boolean replyStatus; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java new file mode 100644 index 0000000..9d2aa42 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.product.controller.admin.comment.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商品评价的商家回复 Request VO") +@Data +@ToString(callSuper = true) +public class ProductCommentReplyReqVO { + + @Schema(description = "评价编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721") + @NotNull(message = "评价编号不能为空") + private Long id; + + @Schema(description = "商家回复内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "谢谢亲") + @NotEmpty(message = "商家回复内容不能为空") + private String replyContent; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java new file mode 100644 index 0000000..605019a --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.product.controller.admin.comment.vo; + +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 商品评价 Response VO") +@Data +public class ProductCommentRespVO { + + @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24965") + private Long id; + + @Schema(description = "评价人", requiredMode = Schema.RequiredMode.REQUIRED, example = "16868") + private Long userId; + + @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小姑凉") + private String userNickname; + + @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + private String userAvatar; + @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean anonymous; + + @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24428") + private Long orderId; + + @Schema(description = "评价订单项", requiredMode = Schema.RequiredMode.REQUIRED, example = "19292") + private Long orderItemId; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖") + private Long spuId; + + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long skuId; + + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + private String spuName; + + @Schema(description = "商品 SKU 图片地址", example = "https://www.iocoder.cn/yudao.jpg") + private String skuPicUrl; + + @Schema(description = "商品 SKU 规格值数组") + private List skuProperties; + + @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED) + private Boolean visible; + + @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + private Integer scores; + + @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + private Integer descriptionScores; + + @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + private Integer benefitScores; + + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿起来非常丝滑凉快") + private String content; + + @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]") + private List picUrls; + + @Schema(description = "商家是否回复", requiredMode = Schema.RequiredMode.REQUIRED) + private Boolean replyStatus; + + @Schema(description = "回复管理员编号", example = "9527") + private Long replyUserId; + + @Schema(description = "商家回复内容", example = "感谢好评哦亲(づ ̄3 ̄)づ╭❤~") + private String replyContent; + + @Schema(description = "商家回复时间", example = "2023-08-08 12:20:55") + private LocalDateTime replyTime; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java new file mode 100644 index 0000000..d970c3f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.product.controller.admin.comment.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商品评价可见修改 Request VO") +@Data +@ToString(callSuper = true) +public class ProductCommentUpdateVisibleReqVO { + + @Schema(description = "评价编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721") + @NotNull(message = "评价编号不能为空") + private Long id; + + @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否可见不能为空") + private Boolean visible; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java new file mode 100644 index 0000000..b0ff22c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/ProductFavoriteController.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.product.controller.admin.favorite; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoriteRespVO; +import cn.iocoder.yudao.module.product.convert.favorite.ProductFavoriteConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.favorite.ProductFavoriteService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +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 jakarta.annotation.Resource; +import jakarta.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - 商品收藏") +@RestController +@RequestMapping("/product/favorite") +@Validated +public class ProductFavoriteController { + + @Resource + private ProductFavoriteService productFavoriteService; + + @Resource + private ProductSpuService productSpuService; + + @GetMapping("/page") + @Operation(summary = "获得商品收藏分页") + @PreAuthorize("@ss.hasPermission('product:favorite:query')") + public CommonResult> getFavoritePage(@Valid ProductFavoritePageReqVO pageVO) { + PageResult pageResult = productFavoriteService.getFavoritePage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + // 拼接数据 + List spuList = productSpuService.getSpuList(convertSet(pageResult.getList(), ProductFavoriteDO::getSpuId)); + return success(ProductFavoriteConvert.INSTANCE.convertPage(pageResult, spuList)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java new file mode 100644 index 0000000..9ecf2fc --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteBaseVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +/** + * 商品收藏 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class ProductFavoriteBaseVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5036") + @NotNull(message = "用户编号不能为空") + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java new file mode 100644 index 0000000..3d78883 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoritePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 商品收藏分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductFavoritePageReqVO extends PageParam { + + @Schema(description = "用户编号", example = "5036") + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java new file mode 100644 index 0000000..8233100 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商品收藏的单个 Response VO") +@Data +@ToString(callSuper = true) +public class ProductFavoriteReqVO extends ProductFavoriteBaseVO { + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32734") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java new file mode 100644 index 0000000..3c09aa8 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/favorite/vo/ProductFavoriteRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.product.controller.admin.favorite.vo; + +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Schema(description = "管理后台 - 商品收藏 Response VO") +@Data +@ToString(callSuper = true) +public class ProductFavoriteRespVO extends ProductSpuRespVO { + + @Schema(description = "userId", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + private Long userId; + + @Schema(description = "spuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + private Long spuId; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java new file mode 100644 index 0000000..38c888b --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/ProductBrowseHistoryController.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.product.controller.admin.history; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.history.ProductBrowseHistoryService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +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 java.util.Map; +import java.util.Optional; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - 商品浏览记录") +@RestController +@RequestMapping("/product/browse-history") +@Validated +public class ProductBrowseHistoryController { + + @Resource + private ProductBrowseHistoryService browseHistoryService; + @Resource + private ProductSpuService productSpuService; + + @GetMapping("/page") + @Operation(summary = "获得商品浏览记录分页") + @PreAuthorize("@ss.hasPermission('product:browse-history:query')") + public CommonResult> getBrowseHistoryPage(@Valid ProductBrowseHistoryPageReqVO pageReqVO) { + PageResult pageResult = browseHistoryService.getBrowseHistoryPage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + + // 得到商品 spu 信息 + Map spuMap = productSpuService.getSpuMap( + convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId)); + return success(BeanUtils.toBean(pageResult, ProductBrowseHistoryRespVO.class, + vo -> Optional.ofNullable(spuMap.get(vo.getSpuId())) + .ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice()) + .setSalesCount(spu.getSalesCount()).setStock(spu.getStock())))); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java new file mode 100644 index 0000000..aa30102 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.product.controller.admin.history.vo; + +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 商品浏览记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductBrowseHistoryPageReqVO extends SortablePageParam { + + @Schema(description = "用户编号", example = "4314") + private Long userId; + + @Schema(description = "用户是否删除", example = "false") + private Boolean userDeleted; + + @Schema(description = "商品 SPU 编号", example = "42") + private Long spuId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java new file mode 100644 index 0000000..df8ae8c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.product.controller.admin.history.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 商品浏览记录 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProductBrowseHistoryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") + private Long spuId; + + // ========== 商品相关字段 ========== + + @Schema(description = "商品 SPU 名称", example = "赵六") + private String spuName; + + @Schema(description = "商品封面图", example = "https://domain/pic.png") + private String picUrl; + + @Schema(description = "商品单价", example = "100") + private Integer price; + + @Schema(description = "商品销量", example = "100") + private Integer salesCount; + + @Schema(description = "库存", example = "100") + private Integer stock; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java new file mode 100644 index 0000000..1ff2d9c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.product.controller.admin.property; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertySaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - 商品属性项") +@RestController +@RequestMapping("/product/property") +@Validated +public class ProductPropertyController { + + @Resource + private ProductPropertyService productPropertyService; + + @PostMapping("/create") + @Operation(summary = "创建属性项") + @PreAuthorize("@ss.hasPermission('product:property:create')") + public CommonResult createProperty(@Valid @RequestBody ProductPropertySaveReqVO createReqVO) { + return success(productPropertyService.createProperty(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新属性项") + @PreAuthorize("@ss.hasPermission('product:property:update')") + public CommonResult updateProperty(@Valid @RequestBody ProductPropertySaveReqVO updateReqVO) { + productPropertyService.updateProperty(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除属性项") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('product:property:delete')") + public CommonResult deleteProperty(@RequestParam("id") Long id) { + productPropertyService.deleteProperty(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得属性项") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:property:query')") + public CommonResult getProperty(@RequestParam("id") Long id) { + ProductPropertyDO property = productPropertyService.getProperty(id); + return success(BeanUtils.toBean(property, ProductPropertyRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得属性项分页") + @PreAuthorize("@ss.hasPermission('product:property:query')") + public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { + PageResult pageResult = productPropertyService.getPropertyPage(pageVO); + return success(BeanUtils.toBean(pageResult, ProductPropertyRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得属性项精简列表") + public CommonResult> getPropertySimpleList() { + List list = productPropertyService.getPropertyList(); + return success(convertList(list, property -> new ProductPropertyRespVO() // 只返回 id、name 属性 + .setId(property.getId()).setName(property.getName()))); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java new file mode 100644 index 0000000..647df87 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.product.controller.admin.property; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueSaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.singleton; + +@Tag(name = "管理后台 - 商品属性值") +@RestController +@RequestMapping("/product/property/value") +@Validated +public class ProductPropertyValueController { + + @Resource + private ProductPropertyValueService productPropertyValueService; + + @PostMapping("/create") + @Operation(summary = "创建属性值") + @PreAuthorize("@ss.hasPermission('product:property:create')") + public CommonResult createPropertyValue(@Valid @RequestBody ProductPropertyValueSaveReqVO createReqVO) { + return success(productPropertyValueService.createPropertyValue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新属性值") + @PreAuthorize("@ss.hasPermission('product:property:update')") + public CommonResult updatePropertyValue(@Valid @RequestBody ProductPropertyValueSaveReqVO updateReqVO) { + productPropertyValueService.updatePropertyValue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除属性值") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:property:delete')") + public CommonResult deletePropertyValue(@RequestParam("id") Long id) { + productPropertyValueService.deletePropertyValue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得属性值") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:property:query')") + public CommonResult getPropertyValue(@RequestParam("id") Long id) { + ProductPropertyValueDO value = productPropertyValueService.getPropertyValue(id); + return success(BeanUtils.toBean(value, ProductPropertyValueRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得属性值分页") + @PreAuthorize("@ss.hasPermission('product:property:query')") + public CommonResult> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) { + PageResult pageResult = productPropertyValueService.getPropertyValuePage(pageVO); + return success(BeanUtils.toBean(pageResult, ProductPropertyValueRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得属性值精简列表") + @Parameter(name = "propertyId", description = "属性项编号", required = true, example = "1024") + public CommonResult> getPropertyValueSimpleList(@RequestParam("propertyId") Long propertyId) { + List list = productPropertyValueService.getPropertyValueListByPropertyId(singleton(propertyId)); + return success(convertList(list, value -> new ProductPropertyValueRespVO() // 只返回 id、name 属性 + .setId(value.getId()).setName(value.getName()))); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java new file mode 100644 index 0000000..97b959d --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 属性项 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductPropertyPageReqVO extends PageParam { + + @Schema(description = "名称", example = "颜色") + private String name; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Schema(description = "创建时间") + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java new file mode 100644 index 0000000..82a3a0c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 属性项 Response VO") +@Data +public class ProductPropertyRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色") + private String name; + + @Schema(description = "备注", example = "颜色") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java new file mode 100644 index 0000000..69ebf9f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertySaveReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Schema(description = "管理后台 - 属性项新增/更新 Request VO") +@Data +public class ProductPropertySaveReqVO { + + @Schema(description = "主键", example = "1") + private Long id; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色") + @NotBlank(message = "名称不能为空") + private String name; + + @Schema(description = "备注", example = "颜色") + private String remark; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java new file mode 100644 index 0000000..ff0c326 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 商品属性值分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductPropertyValuePageReqVO extends PageParam { + + @Schema(description = "属性项的编号", example = "1024") + private String propertyId; + + @Schema(description = "名称", example = "红色") + private String name; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java new file mode 100644 index 0000000..1eedf9f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 商品属性值 Response VO") +@Data +public class ProductPropertyValueRespVO { + + @Schema(description = "主键", example = "1024") + private Long id; + + @Schema(description = "属性项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "属性项的编号不能为空") + private Long propertyId; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色") + @NotEmpty(message = "名称名字不能为空") + private String name; + + @Schema(description = "备注", example = "颜色") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java new file mode 100644 index 0000000..1a57c6a --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueSaveReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 商品属性值新增/更新 Request VO") +@Data +public class ProductPropertyValueSaveReqVO { + + @Schema(description = "主键", example = "1024") + private Long id; + + @Schema(description = "属性项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "属性项的编号不能为空") + private Long propertyId; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色") + @NotEmpty(message = "名称名字不能为空") + private String name; + + @Schema(description = "备注", example = "颜色") + private String remark; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http new file mode 100644 index 0000000..8b20673 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http @@ -0,0 +1,4 @@ +### 获得商品 SPU 明细 +GET {{baseUrl}}/product/spu/get-detail?id=4 +Authorization: Bearer {{token}} +tenant-id: {{adminTenantId}} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java new file mode 100755 index 0000000..0761701 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; +import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; + +@Tag(name = "管理后台 - 商品 SPU") +@RestController +@RequestMapping("/product/spu") +@Validated +public class ProductSpuController { + + @Resource + private ProductSpuService productSpuService; + @Resource + private ProductSkuService productSkuService; + + @PostMapping("/create") + @Operation(summary = "创建商品 SPU") + @PreAuthorize("@ss.hasPermission('product:spu:create')") + public CommonResult createProductSpu(@Valid @RequestBody ProductSpuSaveReqVO createReqVO) { + return success(productSpuService.createSpu(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新商品 SPU") + @PreAuthorize("@ss.hasPermission('product:spu:update')") + public CommonResult updateSpu(@Valid @RequestBody ProductSpuSaveReqVO updateReqVO) { + productSpuService.updateSpu(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新商品 SPU Status") + @PreAuthorize("@ss.hasPermission('product:spu:update')") + public CommonResult updateStatus(@Valid @RequestBody ProductSpuUpdateStatusReqVO updateReqVO) { + productSpuService.updateSpuStatus(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除商品 SPU") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:spu:delete')") + public CommonResult deleteSpu(@RequestParam("id") Long id) { + productSpuService.deleteSpu(id); + return success(true); + } + + @GetMapping("/get-detail") + @Operation(summary = "获得商品 SPU 明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('product:spu:query')") + public CommonResult getSpuDetail(@RequestParam("id") Long id) { + // 获得商品 SPU + ProductSpuDO spu = productSpuService.getSpu(id); + if (spu == null) { + return success(null); + } + // 查询商品 SKU + List skus = productSkuService.getSkuListBySpuId(spu.getId()); + return success(ProductSpuConvert.INSTANCE.convert(spu, skus)); + } + + @GetMapping("/list-all-simple") + @Operation(summary = "获得商品 SPU 精简列表") + @PreAuthorize("@ss.hasPermission('product:spu:query')") + public CommonResult> getSpuSimpleList() { + List list = productSpuService.getSpuListByStatus(ProductSpuStatusEnum.ENABLE.getStatus()); + // 降序排序后,返回给前端 + list.sort(Comparator.comparing(ProductSpuDO::getSort).reversed()); + return success(BeanUtils.toBean(list, ProductSpuSimpleRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得商品 SPU 详情列表") + @Parameter(name = "spuIds", description = "spu 编号列表", required = true, example = "[1,2,3]") + @PreAuthorize("@ss.hasPermission('product:spu:query')") + public CommonResult> getSpuList(@RequestParam("spuIds") Collection spuIds) { + return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO( + productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds))); + } + + @GetMapping("/page") + @Operation(summary = "获得商品 SPU 分页") + @PreAuthorize("@ss.hasPermission('product:spu:query')") + public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) { + PageResult pageResult = productSpuService.getSpuPage(pageVO); + return success(BeanUtils.toBean(pageResult, ProductSpuRespVO.class)); + } + + @GetMapping("/get-count") + @Operation(summary = "获得商品 SPU 分页 tab count") + @PreAuthorize("@ss.hasPermission('product:spu:query')") + public CommonResult> getSpuCount() { + return success(productSpuService.getTabsCount()); + } + + @GetMapping("/export") + @Operation(summary = "导出商品") + @PreAuthorize("@ss.hasPermission('product:spu:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportSpuList(@Validated ProductSpuPageReqVO reqVO, + HttpServletResponse response) throws IOException { + reqVO.setPageSize(PAGE_SIZE_NONE); + List list = productSpuService.getSpuPage(reqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "商品列表.xls", "数据", ProductSpuRespVO.class, + BeanUtils.toBean(list, ProductSpuRespVO.class)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java new file mode 100755 index 0000000..f977d33 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - 商品 SKU Response VO") +@Data +public class ProductSkuRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") + private String name; + + @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") + private Integer price; + + @Schema(description = "市场价", example = "2999") + private Integer marketPrice; + + @Schema(description = "成本价", example = "19") + private Integer costPrice; + + @Schema(description = "条形码", example = "15156165456") + private String barCode; + + @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + private String picUrl; + + @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + private Integer stock; + + @Schema(description = "商品重量,单位:kg 千克", example = "1.2") + private Double weight; + + @Schema(description = "商品体积,单位:m^3 平米", example = "2.5") + private Double volume; + + @Schema(description = "一级分销的佣金,单位:分", example = "199") + private Integer firstBrokeragePrice; + + @Schema(description = "二级分销的佣金,单位:分", example = "19") + private Integer secondBrokeragePrice; + + @Schema(description = "属性数组") + private List properties; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java new file mode 100755 index 0000000..43b1a59 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.*; + +import java.util.List; + +@Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO") +@Data +public class ProductSkuSaveReqVO { + + @Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") + @NotEmpty(message = "商品 SKU 名字不能为空") + private String name; + + @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") + @NotNull(message = "销售价格,单位:分不能为空") + private Integer price; + + @Schema(description = "市场价", example = "2999") + private Integer marketPrice; + + @Schema(description = "成本价", example = "19") + private Integer costPrice; + + @Schema(description = "条形码", example = "15156165456") + private String barCode; + + @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + @NotNull(message = "图片地址不能为空") + private String picUrl; + + @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + @NotNull(message = "库存不能为空") + private Integer stock; + + @Schema(description = "商品重量,单位:kg 千克", example = "1.2") + private Double weight; + + @Schema(description = "商品体积,单位:m^3 平米", example = "2.5") + private Double volume; + + @Schema(description = "一级分销的佣金,单位:分", example = "199") + private Integer firstBrokeragePrice; + + @Schema(description = "二级分销的佣金,单位:分", example = "19") + private Integer secondBrokeragePrice; + + @Schema(description = "属性数组") + private List properties; + + @Schema(description = "商品属性") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Property { + + @Schema(description = "属性编号", example = "10") + private Long propertyId; + + @Schema(description = "属性名字", example = "颜色") + private String propertyName; + + @Schema(description = "属性值编号", example = "10") + private Long valueId; + + @Schema(description = "属性值名字", example = "红色") + private String valueName; + + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java new file mode 100755 index 0000000..81cff42 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 商品 SPU 分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductSpuPageReqVO extends PageParam { + + /** + * 出售中商品 + */ + public static final Integer FOR_SALE = 0; + + /** + * 仓库中商品 + */ + public static final Integer IN_WAREHOUSE = 1; + + /** + * 已售空商品 + */ + public static final Integer SOLD_OUT = 2; + + /** + * 警戒库存 + */ + public static final Integer ALERT_STOCK = 3; + + /** + * 商品回收站 + */ + public static final Integer RECYCLE_BIN = 4; + + @Schema(description = "商品名称", example = "清凉小短袖") + private String name; + + @Schema(description = "前端请求的tab类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer tabType; + + @Schema(description = "商品分类编号", example = "1") + private Long categoryId; + + @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java new file mode 100755 index 0000000..fbc7552 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; +import cn.iocoder.yudao.module.product.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 商品 SPU Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProductSpuRespVO { + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + @ExcelProperty("商品编号") + private Long id; + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") + @ExcelProperty("商品名称") + private String name; + + @Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗") + @ExcelProperty("关键字") + private String keyword; + + @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介") + @ExcelProperty("商品简介") + private String introduction; + + @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情") + @ExcelProperty("商品详情") + private String description; + + @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("商品分类编号") + private Long categoryId; + + @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("商品品牌编号") + private Long brandId; + + @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + @ExcelProperty("商品封面图") + private String picUrl; + + @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") + private List sliderPicUrls; + + @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("排序字段") + private Integer sort; + + @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "商品状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.PRODUCT_SPU_STATUS) + private Integer status; + + @Schema(description = "商品创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-05-24 00:00:00") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + // ========== SKU 相关字段 ========= + + @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("规格类型") + private Boolean specType; + + @Schema(description = "商品价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") + @ExcelProperty(value = "商品价格", converter = MoneyConvert.class) + private Integer price; + + @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199") + @ExcelProperty(value = "市场价", converter = MoneyConvert.class) + private Integer marketPrice; + + @Schema(description = "成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19") + @ExcelProperty(value = "成本价", converter = MoneyConvert.class) + private Integer costPrice; + + @Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @ExcelProperty("库存") + private Integer stock; + + @Schema(description = "SKU 数组") + private List skus; + + // ========== 物流相关字段 ========= + + @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private List deliveryTypes; + + @Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + @ExcelProperty("物流配置模板编号") + private Long deliveryTemplateId; + + // ========== 营销相关字段 ========= + + @Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + @ExcelProperty("赠送积分") + private Integer giveIntegral; + + @Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("分销类型") + private Boolean subCommissionType; + + // ========== 统计相关字段 ========= + + @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") + @ExcelProperty("商品销量") + private Integer salesCount; + + @Schema(description = "虚拟销量", example = "66") + @ExcelProperty("虚拟销量") + private Integer virtualSalesCount; + + @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + @ExcelProperty("商品点击量") + private Integer browseCount; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java new file mode 100755 index 0000000..b842df0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - 商品 SPU 新增/更新 Request VO") +@Data +public class ProductSpuSaveReqVO { + + @Schema(description = "商品编号", example = "1") + private Long id; + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") + @NotEmpty(message = "商品名称不能为空") + private String name; + + @Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗") + @NotEmpty(message = "商品关键字不能为空") + private String keyword; + + @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介") + @NotEmpty(message = "商品简介不能为空") + private String introduction; + + @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情") + @NotEmpty(message = "商品详情不能为空") + private String description; + + @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "商品分类不能为空") + private Long categoryId; + + @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "商品品牌不能为空") + private Long brandId; + + @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + @NotEmpty(message = "商品封面图不能为空") + private String picUrl; + + @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, + example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") + private List sliderPicUrls; + + @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "商品排序字段不能为空") + private Integer sort; + + // ========== SKU 相关字段 ========= + + @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "商品规格类型不能为空") + private Boolean specType; + + // ========== 物流相关字段 ========= + + @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotEmpty(message = "配送方式不能为空") + private List deliveryTypes; + + @Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + private Long deliveryTemplateId; + + // ========== 营销相关字段 ========= + + @Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111") + @NotNull(message = "商品赠送积分不能为空") + private Integer giveIntegral; + + @Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "商品分销类型不能为空") + private Boolean subCommissionType; + + // ========== 统计相关字段 ========= + + @Schema(description = "虚拟销量", example = "66") + private Integer virtualSalesCount; + + @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") + private Integer salesCount; + + @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") + private Integer browseCount; + + // ========== SKU 相关字段 ========= + + @Schema(description = "SKU 数组") + @Valid + private List skus; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java new file mode 100755 index 0000000..7d9d0d0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Schema(description = "管理后台 - 商品 SPU 精简 Response VO") +@Data +@ToString(callSuper = true) +public class ProductSpuSimpleRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "213") + private Long id; + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖") + private String name; + + @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999") + private Integer price; + + @Schema(description = "商品市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199") + private Integer marketPrice; + + @Schema(description = "商品成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19") + private Integer costPrice; + + @Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") + private Integer stock; + + // ========== 统计相关字段 ========= + + @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + private Integer salesCount; + + @Schema(description = "商品虚拟销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20000") + private Integer virtualSalesCount; + + @Schema(description = "商品浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") + private Integer browseCount; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java new file mode 100644 index 0000000..0bc0158 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO") +@Data +public class ProductSpuUpdateStatusReqVO{ + + @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "商品编号不能为空") + private Long id; + + @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "商品状态不能为空") + @InEnum(ProductSpuStatusEnum.class) + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java new file mode 100644 index 0000000..b8a3605 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.product.controller.app.category; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 APP - 商品分类") +@RestController +@RequestMapping("/product/category") +@Validated +public class AppCategoryController { + + @Resource + private ProductCategoryService categoryService; + + @GetMapping("/list") + @Operation(summary = "获得商品分类列表") + @PermitAll + public CommonResult> getProductCategoryList() { + List list = categoryService.getEnableCategoryList(); + list.sort(Comparator.comparing(ProductCategoryDO::getSort)); + return success(BeanUtils.toBean(list, AppCategoryRespVO.class)); + } + + @GetMapping("/list-by-ids") + @Operation(summary = "获得商品分类列表,指定编号") + @Parameter(name = "ids", description = "商品分类编号数组", required = true) + @PermitAll + public CommonResult> getProductCategoryList(@RequestParam("ids") List ids) { + if (CollUtil.isEmpty(ids)) { + return success(Collections.emptyList()); + } + List list = categoryService.getEnableCategoryList(ids); + list.sort(Comparator.comparing(ProductCategoryDO::getSort)); + return success(BeanUtils.toBean(list, AppCategoryRespVO.class)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java new file mode 100644 index 0000000..1ddec5f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.product.controller.app.category.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +@Data +@Schema(description = "用户 APP - 商品分类 Response VO") +public class AppCategoryRespVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "父分类编号不能为空") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具") + @NotBlank(message = "分类名称不能为空") + private String name; + + @Schema(description = "分类图片", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "分类图片不能为空") + private String picUrl; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.http diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java new file mode 100644 index 0000000..b57d58f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.product.controller.app.comment; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; +import jakarta.validation.Valid; +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 static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 APP - 商品评价") +@RestController +@RequestMapping("/product/comment") +@Validated +public class AppProductCommentController { + + @Resource + private ProductCommentService productCommentService; + + @GetMapping("/page") + @Operation(summary = "获得商品评价分页") + @PermitAll + public CommonResult> getCommentPage(@Valid AppCommentPageReqVO pageVO) { + // 查询评论分页 + PageResult pageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 拼接返回 + pageResult.getList().forEach(item -> { + if (Boolean.TRUE.equals(item.getAnonymous())) { + item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS); + } + }); + return success(BeanUtils.toBean(pageResult, AppProductCommentRespVO.class)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java new file mode 100644 index 0000000..854a1c7 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.product.controller.app.comment.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "用户 App - 商品评价分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppCommentPageReqVO extends PageParam { + + /** + * 好评 + */ + public static final Integer GOOD_COMMENT = 1; + /** + * 中评 + */ + public static final Integer MEDIOCRE_COMMENT = 2; + /** + * 差评 + */ + public static final Integer NEGATIVE_COMMENT = 3; + + @Schema(description = "商品 SPU 编号", example = "29502") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; + + @Schema(description = "app 评论页 tab 类型 (0 全部、1 好评、2 中评、3 差评)", example = "0") + @NotNull(message = "商品 SPU 编号不能为空") + private Integer type; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java new file mode 100644 index 0000000..31e50c0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.product.controller.app.comment.vo; + +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "用户 App - 商品评价详情 Response VO") +@Data +@ToString(callSuper = true) +public class AppProductCommentRespVO { + + @Schema(description = "评价人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721") + private Long userId; + + @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String userNickname; + + @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + private String userAvatar; + + @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24965") + private Long id; + + @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean anonymous; + + @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24428") + private Long orderId; + + @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8233") + private Long orderItemId; + + @Schema(description = "商家是否回复", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean replyStatus; + + @Schema(description = "回复管理员编号", example = "22212") + private Long replyUserId; + + @Schema(description = "商家回复内容", example = "亲,你的好评就是我的动力(*^▽^*)") + private String replyContent; + + @Schema(description = "商家回复时间") + private LocalDateTime replyTime; + + @Schema(description = "追加评价内容", example = "穿了很久都很丝滑诶") + private String additionalContent; + + @Schema(description = "追评评价图片地址数组,以逗号分隔最多上传 9 张", example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") + private List additionalPicUrls; + + @Schema(description = "追加评价时间") + private LocalDateTime additionalTime; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; + + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖") + @NotNull(message = "商品 SPU 名称不能为空") + private String spuName; + + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @Schema(description = "商品 SKU 属性", requiredMode = Schema.RequiredMode.REQUIRED) + private List skuProperties; + + @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "评分星级 1-5 分不能为空") + private Integer scores; + + @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "描述星级 1-5 分不能为空") + private Integer descriptionScores; + + @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "服务星级 1-5 分不能为空") + private Integer benefitScores; + + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "哇,真的很丝滑凉快诶,好评") + @NotNull(message = "评论内容不能为空") + private String content; + + @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, + example = "[https://www.iocoder.cn/xx.png]") + @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") + private List picUrls; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java new file mode 100644 index 0000000..fa0903c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.product.controller.app.favorite; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoriteReqVO; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoriteRespVO; +import cn.iocoder.yudao.module.product.convert.favorite.ProductFavoriteConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.favorite.ProductFavoriteService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 商品收藏") +@RestController +@RequestMapping("/product/favorite") +public class AppFavoriteController { + + @Resource + private ProductFavoriteService productFavoriteService; + @Resource + private ProductSpuService productSpuService; + + @PostMapping(value = "/create") + @Operation(summary = "添加商品收藏") + public CommonResult createFavorite(@RequestBody @Valid AppFavoriteReqVO reqVO) { + return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId())); + } + + @DeleteMapping(value = "/delete") + @Operation(summary = "取消单个商品收藏") + public CommonResult deleteFavorite(@RequestBody @Valid AppFavoriteReqVO reqVO) { + productFavoriteService.deleteFavorite(getLoginUserId(), reqVO.getSpuId()); + return success(Boolean.TRUE); + } + + @GetMapping(value = "/page") + @Operation(summary = "获得商品收藏分页") + public CommonResult> getFavoritePage(AppFavoritePageReqVO reqVO) { + PageResult favoritePage = productFavoriteService.getFavoritePage(getLoginUserId(), reqVO); + if (CollUtil.isEmpty(favoritePage.getList())) { + return success(PageResult.empty()); + } + + // 得到商品 spu 信息 + List favorites = favoritePage.getList(); + List spuIds = convertList(favorites, ProductFavoriteDO::getSpuId); + List spus = productSpuService.getSpuList(spuIds); + + // 转换 VO 结果 + PageResult pageResult = new PageResult<>(favoritePage.getTotal()); + pageResult.setList(ProductFavoriteConvert.INSTANCE.convertList(favorites, spus)); + return success(pageResult); + } + + @GetMapping(value = "/exits") + @Operation(summary = "检查是否收藏过商品") + public CommonResult isFavoriteExists(AppFavoriteReqVO reqVO) { + ProductFavoriteDO favorite = productFavoriteService.getFavorite(getLoginUserId(), reqVO.getSpuId()); + return success(favorite != null); + } + + @GetMapping(value = "/get-count") + @Operation(summary = "获得商品收藏数量") + public CommonResult getFavoriteCount() { + return success(productFavoriteService.getFavoriteCount(getLoginUserId())); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java new file mode 100644 index 0000000..2bf2e9d --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.product.controller.app.favorite.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotEmpty; +import java.util.List; + +@Schema(description = "用户 APP - 商品收藏的批量 Request VO") // 用于收藏、取消收藏、获取收藏 +@Data +public class AppFavoriteBatchReqVO { + + @Schema(description = "商品 SPU 编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") + @NotEmpty(message = "商品 SPU 编号数组不能为空") + private List spuIds; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java new file mode 100644 index 0000000..2aacc3e --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.module.product.controller.app.favorite.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 商品收藏分页查询 Request VO") +@Data +public class AppFavoritePageReqVO extends PageParam { +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java new file mode 100644 index 0000000..4d7ba0e --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.product.controller.app.favorite.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "用户 APP - 商品收藏的单个 Request VO") // 用于收藏、取消收藏、获取收藏 +@Data +public class AppFavoriteReqVO { + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java new file mode 100644 index 0000000..653ab91 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.product.controller.app.favorite.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 商品收藏 Response VO") +@Data +public class AppFavoriteRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") + private Long spuId; + + // ========== 商品相关字段 ========== + + @Schema(description = "商品 SPU 名称", example = "赵六") + private String spuName; + + @Schema(description = "商品封面图", example = "https://domain/pic.png") + private String picUrl; + + @Schema(description = "商品单价", example = "100") + private Integer price; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java new file mode 100644 index 0000000..89c435c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.product.controller.app.history; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.history.vo.AppProductBrowseHistoryDeleteReqVO; +import cn.iocoder.yudao.module.product.controller.app.history.vo.AppProductBrowseHistoryPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.history.vo.AppProductBrowseHistoryRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.history.ProductBrowseHistoryService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 商品浏览记录") +@RestController +@RequestMapping("/product/browse-history") +public class AppProductBrowseHistoryController { + + @Resource + private ProductBrowseHistoryService productBrowseHistoryService; + @Resource + private ProductSpuService productSpuService; + + @DeleteMapping(value = "/delete") + @Operation(summary = "删除商品浏览记录") + public CommonResult deleteBrowseHistory(@RequestBody @Valid AppProductBrowseHistoryDeleteReqVO reqVO) { + productBrowseHistoryService.hideUserBrowseHistory(getLoginUserId(), reqVO.getSpuIds()); + return success(Boolean.TRUE); + } + + @DeleteMapping(value = "/clean") + @Operation(summary = "清空商品浏览记录") + public CommonResult deleteBrowseHistory() { + productBrowseHistoryService.hideUserBrowseHistory(getLoginUserId(), null); + return success(Boolean.TRUE); + } + + @GetMapping(value = "/page") + @Operation(summary = "获得商品浏览记录分页") + public CommonResult> getBrowseHistoryPage(AppProductBrowseHistoryPageReqVO reqVO) { + ProductBrowseHistoryPageReqVO pageReqVO = BeanUtils.toBean(reqVO, ProductBrowseHistoryPageReqVO.class) + .setUserId(getLoginUserId()) + .setUserDeleted(false); // 排除用户已删除的(隐藏的) + PageResult pageResult = productBrowseHistoryService.getBrowseHistoryPage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + + // 得到商品 spu 信息 + Set spuIds = convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId); + Map spuMap = convertMap(productSpuService.getSpuList(spuIds), ProductSpuDO::getId); + return success(BeanUtils.toBean(pageResult, AppProductBrowseHistoryRespVO.class, + vo -> Optional.ofNullable(spuMap.get(vo.getSpuId())) + .ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice()) + .setSalesCount(spu.getSalesCount()).setStock(spu.getStock())))); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java new file mode 100644 index 0000000..aada3fa --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.product.controller.app.history.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.List; + +@Schema(description = "用户 APP - 删除商品浏览记录的 Request VO") +@Data +public class AppProductBrowseHistoryDeleteReqVO { + + @Schema(description = "商品 SPU 编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") + @NotEmpty(message = "商品 SPU 编号数组不能为空") + private List spuIds; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java new file mode 100644 index 0000000..f959fd0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.product.controller.app.history.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "用户 APP - 商品浏览记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppProductBrowseHistoryPageReqVO extends PageParam { + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java new file mode 100644 index 0000000..d5f8e9d --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.product.controller.app.history.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 商品浏览记录 Response VO") +@Data +public class AppProductBrowseHistoryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29502") + private Long spuId; + + // ========== 商品相关字段 ========== + + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + private String spuName; + + @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/pic.png") + private String picUrl; + + @Schema(description = "商品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + private Integer price; + + @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "60") + private Integer salesCount; + + @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") + private Integer stock; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java new file mode 100644 index 0000000..379e851 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位符,无时间作用,避免 package 缩进 + */ +package cn.iocoder.yudao.module.product.controller.app.property; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java new file mode 100644 index 0000000..6538bea --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位符,无时间作用,避免 package 缩进 + */ +package cn.iocoder.yudao.module.product.controller.app.property.vo.property; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java new file mode 100644 index 0000000..5cac091 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.product.controller.app.property.vo.value; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 商品属性值的明细 Response VO") +@Data +public class AppProductPropertyValueDetailRespVO { + + @Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long propertyId; + + @Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色") + private String propertyName; + + @Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long valueId; + + @Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色") + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http new file mode 100644 index 0000000..784c464 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http @@ -0,0 +1,18 @@ +### 获得订单交易的分页(默认) +GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10 +Authorization: Bearer {{appToken}} +tenant-id: {{appTenantId}} + +### 获得订单交易的分页(价格) +GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10&sortField=price&sortAsc=true +Authorization: Bearer {{appToken}} +tenant-id: {{appTenantId}} + +### 获得订单交易的分页(销售) +GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10&sortField=salesCount&sortAsc=true +Authorization: Bearer {{appToken}} +tenant-id: {{appTenantId}} + +### 获得商品 SPU 明细 +GET {{appApi}}/product/spu/get-detail?id=102 +tenant-id: {{appTenantId}} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java new file mode 100644 index 0000000..87b0f29 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.product.controller.app.spu; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.product.service.history.ProductBrowseHistoryService; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; +import jakarta.validation.Valid; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; + +@Tag(name = "用户 APP - 商品 SPU") +@RestController +@RequestMapping("/product/spu") +@Validated +public class AppProductSpuController { + + @Resource + private ProductSpuService productSpuService; + @Resource + private ProductSkuService productSkuService; + @Resource + private ProductBrowseHistoryService productBrowseHistoryService; + + @GetMapping("/list-by-ids") + @Operation(summary = "获得商品 SPU 列表") + @Parameter(name = "ids", description = "编号列表", required = true) + @PermitAll + public CommonResult> getSpuList(@RequestParam("ids") Set ids) { + List list = productSpuService.getSpuList(ids); + if (CollUtil.isEmpty(list)) { + return success(Collections.emptyList()); + } + + // 拼接返回 + list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount())); + List voList = BeanUtils.toBean(list, AppProductSpuRespVO.class); + return success(voList); + } + + @GetMapping("/page") + @Operation(summary = "获得商品 SPU 分页") + @PermitAll + public CommonResult> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) { + PageResult pageResult = productSpuService.getSpuPage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 拼接返回 + pageResult.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount())); + PageResult voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class); + return success(voPageResult); + } + + @GetMapping("/get-detail") + @Operation(summary = "获得商品 SPU 明细") + @Parameter(name = "id", description = "编号", required = true) + @PermitAll + public CommonResult getSpuDetail(@RequestParam("id") Long id) { + // 获得商品 SPU + ProductSpuDO spu = productSpuService.getSpu(id); + if (spu == null) { + throw exception(SPU_NOT_EXISTS); + } + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { + throw exception(SPU_NOT_ENABLE, spu.getName()); + } + // 获得商品 SKU + List skus = productSkuService.getSkuListBySpuId(spu.getId()); + + // 增加浏览量 + productSpuService.updateBrowseCount(id, 1); + // 保存浏览记录 + productBrowseHistoryService.createBrowseHistory(getLoginUserId(), id); + + // 拼接返回 + spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()); + AppProductSpuDetailRespVO spuVO = BeanUtils.toBean(spu, AppProductSpuDetailRespVO.class) + .setSkus(BeanUtils.toBean(skus, AppProductSpuDetailRespVO.Sku.class)); + return success(spuVO); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java new file mode 100644 index 0000000..525f224 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.product.controller.app.spu.vo; + +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "用户 App - 商品 SPU 明细 Response VO") +@Data +public class AppProductSpuDetailRespVO { + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + // ========== 基本信息 ========= + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + private String name; + + @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个快乐简介") + private String introduction; + + @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是商品描述") + private String description; + + @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long categoryId; + + @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED) + private String picUrl; + + @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED) + private List sliderPicUrls; + + // ========== 营销相关字段 ========= + + // ========== SKU 相关字段 ========= + + @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean specType; + + @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer price; + + @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer marketPrice; + + @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private Integer stock; + + /** + * SKU 数组 + */ + private List skus; + + // ========== 统计相关字段 ========= + + @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer salesCount; + + @Schema(description = "用户 App - 商品 SPU 明细的 SKU 信息") + @Data + public static class Sku { + + @Schema(description = "商品 SKU 编号", example = "1") + private Long id; + + /** + * 商品属性数组 + */ + private List properties; + + @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer price; + + @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer marketPrice; + + @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格 + private Integer vipPrice; + + @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + private String picUrl; + + @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer stock; + + @Schema(description = "商品重量", example = "1") // 单位:kg 千克 + private Double weight; + + @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米 + private Double volume; + + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java new file mode 100644 index 0000000..9e7930e --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.product.controller.app.spu.vo; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@Schema(description = "用户 App - 商品 SPU 分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppProductSpuPageReqVO extends PageParam { + + public static final String SORT_FIELD_PRICE = "price"; + public static final String SORT_FIELD_SALES_COUNT = "salesCount"; + public static final String SORT_FIELD_CREATE_TIME = "createTime"; + + @Schema(description = "商品 SPU 编号数组", example = "1,3,5") + private List ids; + + @Schema(description = "分类编号", example = "1") + private Long categoryId; + + @Schema(description = "分类编号数组", example = "1,2,3") + private List categoryIds; + + @Schema(description = "关键字", example = "好看") + private String keyword; + + @Schema(description = "排序字段", example = "price") // 参见 AppProductSpuPageReqVO.SORT_FIELD_XXX 常量 + private String sortField; + + @Schema(description = "排序方式", example = "true") + private Boolean sortAsc; + + @AssertTrue(message = "排序字段不合法") + @JsonIgnore + public boolean isSortFieldValid() { + if (StrUtil.isEmpty(sortField)) { + return true; + } + return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java new file mode 100644 index 0000000..db606cc --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.product.controller.app.spu.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "用户 App - 商品 SPU Response VO") +@Data +public class AppProductSpuRespVO { + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + private String name; + + @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介") + private String introduction; + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED) + private Long categoryId; + + @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED) + private String picUrl; + + @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED) + private List sliderPicUrls; + + // ========== SKU 相关字段 ========= + + @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean specType; + + @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer price; + + @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer marketPrice; + + @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private Integer stock; + + // ========== 营销相关字段 ========= + + // ========== 统计相关字段 ========= + + @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer salesCount; + + // ========== 物流相关字段 ========= + + @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private List deliveryTypes; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java new file mode 100644 index 0000000..e6c72fb --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.product.convert.brand; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandRespVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandSimpleRespVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 品牌 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ProductBrandConvert { + + ProductBrandConvert INSTANCE = Mappers.getMapper(ProductBrandConvert.class); + + ProductBrandDO convert(ProductBrandCreateReqVO bean); + + ProductBrandDO convert(ProductBrandUpdateReqVO bean); + + ProductBrandRespVO convert(ProductBrandDO bean); + + List convertList1(List list); + + List convertList(List list); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java new file mode 100644 index 0000000..7a3a3c0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.product.convert.comment; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 商品评价 Convert + * + * @author wangzhs + */ +@Mapper +public interface ProductCommentConvert { + + ProductCommentConvert INSTANCE = Mappers.getMapper(ProductCommentConvert.class); + + default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, + ProductSpuDO spu, ProductSkuDO sku, MemberUserRespDTO user) { + ProductCommentDO comment = BeanUtils.toBean(createReqDTO, ProductCommentDO.class) + .setScores(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores())); + if (user != null) { + comment.setUserId(user.getId()).setUserNickname(user.getNickname()).setUserAvatar(user.getAvatar()); + } + if (spu != null) { + comment.setSpuId(spu.getId()).setSpuName(spu.getName()); + } + if (sku != null) { + comment.setSkuPicUrl(sku.getPicUrl()).setSkuProperties(sku.getProperties()); + } + return comment; + } + + default ProductCommentDO convert(ProductCommentCreateReqVO createReq, ProductSpuDO spu, ProductSkuDO sku) { + ProductCommentDO comment = BeanUtils.toBean(createReq, ProductCommentDO.class) + .setVisible(true).setUserId(0L).setAnonymous(false) + .setScores(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores())); + if (spu != null) { + comment.setSpuId(spu.getId()).setSpuName(spu.getName()); + } + if (sku != null) { + comment.setSkuPicUrl(sku.getPicUrl()).setSkuProperties(sku.getProperties()); + } + return comment; + } + + default Integer convertScores(Integer descriptionScores, Integer benefitScores) { + // 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2 + BigDecimal sumScore = new BigDecimal(descriptionScores + benefitScores); + BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN); + return divide.intValue(); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java new file mode 100644 index 0000000..7b419b6 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.product.convert.favorite; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoriteRespVO; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoriteRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +@Mapper +public interface ProductFavoriteConvert { + + ProductFavoriteConvert INSTANCE = Mappers.getMapper(ProductFavoriteConvert.class); + + ProductFavoriteDO convert(Long userId, Long spuId); + + @Mapping(target = "id", source = "favorite.id") + @Mapping(target = "spuName", source = "spu.name") + AppFavoriteRespVO convert(ProductSpuDO spu, ProductFavoriteDO favorite); + + default List convertList(List favorites, List spus) { + List resultList = new ArrayList<>(favorites.size()); + Map spuMap = convertMap(spus, ProductSpuDO::getId); + for (ProductFavoriteDO favorite : favorites) { + ProductSpuDO spuDO = spuMap.get(favorite.getSpuId()); + resultList.add(convert(spuDO, favorite)); + } + return resultList; + } + + default PageResult convertPage(PageResult pageResult, List spuList) { + Map spuMap = convertMap(spuList, ProductSpuDO::getId); + List voList = CollectionUtils.convertList(pageResult.getList(), favorite -> { + ProductSpuDO spu = spuMap.get(favorite.getSpuId()); + return convert02(spu, favorite); + }); + return new PageResult<>(voList, pageResult.getTotal()); + } + @Mapping(target = "id", source = "favorite.id") + @Mapping(target = "userId", source = "favorite.userId") + @Mapping(target = "spuId", source = "favorite.spuId") + @Mapping(target = "createTime", source = "favorite.createTime") + ProductFavoriteRespVO convert02(ProductSpuDO spu, ProductFavoriteDO favorite); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java new file mode 100755 index 0000000..492f483 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.product.convert.sku; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.*; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * 商品 SKU Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ProductSkuConvert { + + ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class); + + /** + * 获得 SPU 的库存变化 Map + * + * @param items SKU 库存变化 + * @param skus SKU 列表 + * @return SPU 的库存变化 Map + */ + default Map convertSpuStockMap(List items, + List skus) { + Map skuIdAndSpuIdMap = convertMap(skus, ProductSkuDO::getId, ProductSkuDO::getSpuId); // SKU 与 SKU 编号的 Map 关系 + Map spuIdAndStockMap = new HashMap<>(); // SPU 的库存变化 Map 关系 + items.forEach(item -> { + Long spuId = skuIdAndSpuIdMap.get(item.getId()); + if (spuId == null) { + return; + } + Integer stock = spuIdAndStockMap.getOrDefault(spuId, 0) + item.getIncrCount(); + spuIdAndStockMap.put(spuId, stock); + }); + return spuIdAndStockMap; + } + + default String buildPropertyKey(ProductSkuDO bean) { + if (CollUtil.isEmpty(bean.getProperties())) { + return StrUtil.EMPTY; + } + List properties = new ArrayList<>(bean.getProperties()); + properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId)); + return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining()); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java new file mode 100755 index 0000000..3644342 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.product.convert.spu; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuRespVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; + +/** + * 商品 SPU Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ProductSpuConvert { + + ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class); + + ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean); + + default ProductSpuRespVO convert(ProductSpuDO spu, List skus) { + ProductSpuRespVO spuVO = BeanUtils.toBean(spu, ProductSpuRespVO.class); + spuVO.setSkus(BeanUtils.toBean(skus, ProductSkuRespVO.class)); + return spuVO; + } + + default List convertForSpuDetailRespListVO(List spus, List skus) { + Map> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId); + return CollectionUtils.convertList(spus, spu -> convert(spu, skuMultiMap.get(spu.getId()))); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java new file mode 100644 index 0000000..7265440 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/brand/ProductBrandDO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.brand; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品品牌 DO + * + * @author 芋道源码 + */ +@TableName("product_brand") +@KeySequence("product_brand_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductBrandDO extends BaseDO { + + /** + * 品牌编号 + */ + @TableId + private Long id; + /** + * 品牌名称 + */ + private String name; + /** + * 品牌图片 + */ + private String picUrl; + /** + * 品牌排序 + */ + private Integer sort; + /** + * 品牌描述 + */ + private String description; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java new file mode 100644 index 0000000..44c6c09 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.category; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品分类 DO + * + * @author 芋道源码 + */ +@TableName("product_category") +@KeySequence("product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductCategoryDO extends BaseDO { + + /** + * 父分类编号 - 根分类 + */ + public static final Long PARENT_ID_NULL = 0L; + /** + * 限定分类层级 + */ + public static final int CATEGORY_LEVEL = 2; + + /** + * 分类编号 + */ + @TableId + private Long id; + /** + * 父分类编号 + */ + private Long parentId; + /** + * 分类名称 + */ + private String name; + /** + * 移动端分类图 + * + * 建议 180*180 分辨率 + */ + private String picUrl; + /** + * 分类排序 + */ + private Integer sort; + /** + * 开启状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java new file mode 100644 index 0000000..86d70f0 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/comment/ProductCommentDO.java @@ -0,0 +1,159 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.comment; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 商品评论 DO + * + * @author 芋道源码 + */ +@TableName(value = "product_comment", autoResultMap = true) +@KeySequence("product_comment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductCommentDO extends BaseDO { + + /** + * 默认匿名昵称 + */ + public static final String NICKNAME_ANONYMOUS = "匿名用户"; + + /** + * 评论编号,主键自增 + */ + @TableId + private Long id; + + /** + * 评价人的用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 评价人名称 + */ + private String userNickname; + /** + * 评价人头像 + */ + private String userAvatar; + /** + * 是否匿名 + */ + private Boolean anonymous; + + /** + * 交易订单编号 + * + * 关联 TradeOrderDO 的 id 编号 + */ + private Long orderId; + /** + * 交易订单项编号 + * + * 关联 TradeOrderItemDO 的 id 编号 + */ + private Long orderItemId; + + /** + * 商品 SPU 编号 + * + * 关联 {@link ProductSpuDO#getId()} + */ + private Long spuId; + /** + * 商品 SPU 名称 + * + * 关联 {@link ProductSpuDO#getName()} + */ + private String spuName; + /** + * 商品 SKU 编号 + * + * 关联 {@link ProductSkuDO#getId()} + */ + private Long skuId; + /** + * 商品 SKU 图片地址 + * + * 关联 {@link ProductSkuDO#getPicUrl()} + */ + private String skuPicUrl; + /** + * 属性数组,JSON 格式 + * + * 关联 {@link ProductSkuDO#getProperties()} + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List skuProperties; + + /** + * 是否可见 + * + * true:显示 + * false:隐藏 + */ + private Boolean visible; + /** + * 评分星级 + * + * 1-5 分 + */ + private Integer scores; + /** + * 描述星级 + * + * 1-5 星 + */ + private Integer descriptionScores; + /** + * 服务星级 + * + * 1-5 星 + */ + private Integer benefitScores; + /** + * 评论内容 + */ + private String content; + /** + * 评论图片地址数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List picUrls; + + /** + * 商家是否回复 + */ + private Boolean replyStatus; + /** + * 回复管理员编号 + * 关联 AdminUserDO 的 id 编号 + */ + private Long replyUserId; + /** + * 商家回复内容 + */ + private String replyContent; + /** + * 商家回复时间 + */ + private LocalDateTime replyTime; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java new file mode 100644 index 0000000..6e00eaa --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.favorite; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品收藏 DO + * + * @author 芋道源码 + */ +@TableName("product_favorite") +@KeySequence("product_favorite_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductFavoriteDO extends BaseDO { + + /** + * 编号,主键自增 + */ + @TableId + private Long id; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 商品 SPU 编号 + * + * 关联 {@link ProductSpuDO#getId()} + */ + private Long spuId; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java new file mode 100644 index 0000000..472574b --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/history/ProductBrowseHistoryDO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.history; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品浏览记录 DO + * + * @author owen + */ +@TableName("product_browse_history") +@KeySequence("product_browse_history_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductBrowseHistoryDO extends BaseDO { + + /** + * 记录编号 + */ + @TableId + private Long id; + /** + * 商品 SPU 编号 + */ + private Long spuId; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户是否删除 + */ + private Boolean userDeleted; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java new file mode 100644 index 0000000..d23a828 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.property; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商品属性项 DO + * + * @author 芋道源码 + */ +@TableName("product_property") +@KeySequence("product_property_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductPropertyDO extends BaseDO { + + /** + * SPU 单规格时,默认属性 id + */ + public static final Long ID_DEFAULT = 0L; + /** + * SPU 单规格时,默认属性名字 + */ + public static final String NAME_DEFAULT = "默认"; + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 名称 + */ + private String name; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java new file mode 100644 index 0000000..cefa2d9 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.property; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + + +/** + * 商品属性值 DO + * + * @author 芋道源码 + */ +@TableName("product_property_value") +@KeySequence("product_property_value_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductPropertyValueDO extends BaseDO { + + /** + * SPU 单规格时,默认属性值 id + */ + public static final Long ID_DEFAULT = 0L; + /** + * SPU 单规格时,默认属性值名字 + */ + public static final String NAME_DEFAULT = "默认"; + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 属性项的编号 + * + * 关联 {@link ProductPropertyDO#getId()} + */ + private Long propertyId; + /** + * 名称 + */ + private String name; + /** + * 备注 + * + */ + private String remark; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java new file mode 100755 index 0000000..267756a --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.sku; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.util.List; + +/** + * 商品 SKU DO + * + * @author 芋道源码 + */ +@TableName(value = "product_sku", autoResultMap = true) +@KeySequence("product_sku_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductSkuDO extends BaseDO { + + /** + * 商品 SKU 编号,自增 + */ + @TableId + private Long id; + /** + * SPU 编号 + * + * 关联 {@link ProductSpuDO#getId()} + */ + private Long spuId; + /** + * 属性数组,JSON 格式 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List properties; + /** + * 商品价格,单位:分 + */ + private Integer price; + /** + * 市场价,单位:分 + */ + private Integer marketPrice; + /** + * 成本价,单位:分 + */ + private Integer costPrice; + /** + * 商品条码 + */ + private String barCode; + /** + * 图片地址 + */ + private String picUrl; + /** + * 库存 + */ + private Integer stock; + /** + * 商品重量,单位:kg 千克 + */ + private Double weight; + /** + * 商品体积,单位:m^3 平米 + */ + private Double volume; + + /** + * 一级分销的佣金,单位:分 + */ + private Integer firstBrokeragePrice; + /** + * 二级分销的佣金,单位:分 + */ + private Integer secondBrokeragePrice; + + // ========== 营销相关字段 ========= + + // ========== 统计相关字段 ========= + /** + * 商品销量 + */ + private Integer salesCount; + + /** + * 商品属性 + */ + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Property { + + /** + * 属性编号 + * 关联 {@link ProductPropertyDO#getId()} + */ + private Long propertyId; + /** + * 属性名字 + * 冗余 {@link ProductPropertyDO#getName()} + * + * 注意:每次属性名字发生变化时,需要更新该冗余 + */ + private String propertyName; + + /** + * 属性值编号 + * 关联 {@link ProductPropertyValueDO#getId()} + */ + private Long valueId; + /** + * 属性值名字 + * 冗余 {@link ProductPropertyValueDO#getName()} + * + * 注意:每次属性值名字发生变化时,需要更新该冗余 + */ + private String valueName; + + } + +} + diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java new file mode 100755 index 0000000..d2b5195 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java @@ -0,0 +1,171 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.spu; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.util.List; + +/** + * 商品 SPU DO + * + * @author 芋道源码 + */ +@TableName(value = "product_spu", autoResultMap = true) +@KeySequence("product_spu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductSpuDO extends BaseDO { + + /** + * 商品 SPU 编号,自增 + */ + @TableId + private Long id; + + // ========== 基本信息 ========= + + /** + * 商品名称 + */ + private String name; + /** + * 关键字 + */ + private String keyword; + /** + * 商品简介 + */ + private String introduction; + /** + * 商品详情 + */ + private String description; + + /** + * 商品分类编号 + * + * 关联 {@link ProductCategoryDO#getId()} + */ + private Long categoryId; + /** + * 商品品牌编号 + * + * 关联 {@link ProductBrandDO#getId()} + */ + private Long brandId; + /** + * 商品封面图 + */ + private String picUrl; + /** + * 商品轮播图 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List sliderPicUrls; + + /** + * 排序字段 + */ + private Integer sort; + /** + * 商品状态 + * + * 枚举 {@link ProductSpuStatusEnum} + */ + private Integer status; + + // ========== SKU 相关字段 ========= + + /** + * 规格类型 + * + * false - 单规格 + * true - 多规格 + */ + private Boolean specType; + /** + * 商品价格,单位使用:分 + * + * 基于其对应的 {@link ProductSkuDO#getPrice()} sku单价最低的商品的 + */ + private Integer price; + /** + * 市场价,单位使用:分 + * + * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} sku单价最低的商品的 + */ + private Integer marketPrice; + /** + * 成本价,单位使用:分 + * + * 基于其对应的 {@link ProductSkuDO#getCostPrice()} sku单价最低的商品的 + */ + private Integer costPrice; + /** + * 库存 + * + * 基于其对应的 {@link ProductSkuDO#getStock()} 求和 + */ + private Integer stock; + + // ========== 物流相关字段 ========= + + /** + * 配送方式数组 + * + * 对应 DeliveryTypeEnum 枚举 + */ + @TableField(typeHandler = IntegerListTypeHandler.class) + private List deliveryTypes; + /** + * 物流配置模板编号 + * + * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 + */ + private Long deliveryTemplateId; + + // ========== 营销相关字段 ========= + + /** + * 赠送积分 + */ + private Integer giveIntegral; + + // TODO @puhui999:字段估计要改成 brokerageType + /** + * 分销类型 + * + * false - 默认 + * true - 自行设置 + */ + private Boolean subCommissionType; + + // ========== 统计相关字段 ========= + + /** + * 商品销量 + */ + private Integer salesCount; + /** + * 虚拟销量 + */ + private Integer virtualSalesCount; + /** + * 浏览量 + */ + private Integer browseCount; +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java new file mode 100644 index 0000000..b2c4bd5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.product.dal.mysql.brand; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ProductBrandMapper extends BaseMapperX { + + default PageResult selectPage(ProductBrandPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ProductBrandDO::getName, reqVO.getName()) + .eqIfPresent(ProductBrandDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(ProductBrandDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ProductBrandDO::getId)); + } + + + default List selectList(ProductBrandListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ProductBrandDO::getName, reqVO.getName())); + } + + default ProductBrandDO selectByName(String name) { + return selectOne(ProductBrandDO::getName, name); + } + + default List selectListByStatus(Integer status) { + return selectList(ProductBrandDO::getStatus, status); + } +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java new file mode 100644 index 0000000..4c212de --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.product.dal.mysql.category; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * 商品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ProductCategoryMapper extends BaseMapperX { + + default List selectList(ProductCategoryListReqVO listReqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ProductCategoryDO::getName, listReqVO.getName()) + .eqIfPresent(ProductCategoryDO::getParentId, listReqVO.getParentId()) + .inIfPresent(ProductCategoryDO::getId, listReqVO.getParentIds()) + .eqIfPresent(ProductCategoryDO::getStatus, listReqVO.getStatus()) + .orderByDesc(ProductCategoryDO::getId)); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(ProductCategoryDO::getParentId, parentId); + } + + default List selectListByStatus(Integer status) { + return selectList(ProductCategoryDO::getStatus, status); + } + + default List selectListByIdAndStatus(Collection ids, Integer status) { + return selectList(new LambdaQueryWrapperX() + .in(ProductCategoryDO::getId, ids) + .eq(ProductCategoryDO::getStatus, status)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java new file mode 100644 index 0000000..47421d3 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.product.dal.mysql.comment; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ProductCommentMapper extends BaseMapperX { + + default PageResult selectPage(ProductCommentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ProductCommentDO::getUserNickname, reqVO.getUserNickname()) + .eqIfPresent(ProductCommentDO::getOrderId, reqVO.getOrderId()) + .eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId()) + .eqIfPresent(ProductCommentDO::getScores, reqVO.getScores()) + .eqIfPresent(ProductCommentDO::getReplyStatus, reqVO.getReplyStatus()) + .betweenIfPresent(ProductCommentDO::getCreateTime, reqVO.getCreateTime()) + .likeIfPresent(ProductCommentDO::getSpuName, reqVO.getSpuName()) + .orderByDesc(ProductCommentDO::getId)); + } + + static void appendTabQuery(LambdaQueryWrapperX queryWrapper, Integer type) { + // 构建好评查询语句:好评计算 总评 >= 4 + if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) { + queryWrapper.ge(ProductCommentDO::getScores, 4); + } + // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4 + if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) { + queryWrapper.ge(ProductCommentDO::getScores, 3); + queryWrapper.lt(ProductCommentDO::getScores, 4); + } + // 构建差评查询语句:差评计算 总评 < 3 + if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) { + queryWrapper.lt(ProductCommentDO::getScores, 3); + } + } + + default PageResult selectPage(AppCommentPageReqVO reqVO, Boolean visible) { + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX() + .eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId()) + .eqIfPresent(ProductCommentDO::getVisible, visible); + // 构建评价查询语句 + appendTabQuery(queryWrapper, reqVO.getType()); + // 按评价时间排序最新的显示在前面 + queryWrapper.orderByDesc(ProductCommentDO::getCreateTime); + return selectPage(reqVO, queryWrapper); + } + + default ProductCommentDO selectByUserIdAndOrderItemId(Long userId, Long orderItemId) { + return selectOne(new LambdaQueryWrapperX() + .eq(ProductCommentDO::getUserId, userId) + .eq(ProductCommentDO::getOrderItemId, orderItemId)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java new file mode 100644 index 0000000..a681d42 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.product.dal.mysql.favorite; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ProductFavoriteMapper extends BaseMapperX { + + default ProductFavoriteDO selectByUserIdAndSpuId(Long userId, Long spuId) { + return selectOne(ProductFavoriteDO::getUserId, userId, + ProductFavoriteDO::getSpuId, spuId); + } + + default PageResult selectPageByUserAndType(Long userId, AppFavoritePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapper() + .eq(ProductFavoriteDO::getUserId, userId) + .orderByDesc(ProductFavoriteDO::getId)); + } + + default PageResult selectPageByUserId(ProductFavoritePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ProductFavoriteDO::getUserId, reqVO.getUserId()) + .orderByDesc(ProductFavoriteDO::getId)); + } + + default Long selectCountByUserId(Long userId) { + return selectCount(ProductFavoriteDO::getUserId, userId); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java new file mode 100644 index 0000000..8ea2ca5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.product.dal.mysql.history; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; + +/** + * 商品浏览记录 Mapper + * + * @author owen + */ +@Mapper +public interface ProductBrowseHistoryMapper extends BaseMapperX { + + default ProductBrowseHistoryDO selectByUserIdAndSpuId(Long userId, Long spuId) { + return selectFirstOne(ProductBrowseHistoryDO::getUserId, userId, + ProductBrowseHistoryDO::getSpuId, spuId); + } + + default PageResult selectPage(ProductBrowseHistoryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ProductBrowseHistoryDO::getUserId, reqVO.getUserId()) + .eqIfPresent(ProductBrowseHistoryDO::getUserDeleted, reqVO.getUserDeleted()) + .eqIfPresent(ProductBrowseHistoryDO::getSpuId, reqVO.getSpuId()) + .betweenIfPresent(ProductBrowseHistoryDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ProductBrowseHistoryDO::getId)); + } + + default void updateUserDeletedByUserId(Long userId, Collection spuIds, Boolean userDeleted) { + update(new LambdaUpdateWrapper() + .eq(ProductBrowseHistoryDO::getUserId, userId) + .in(CollUtil.isNotEmpty(spuIds), ProductBrowseHistoryDO::getSpuId, spuIds) + .set(ProductBrowseHistoryDO::getUserDeleted, userDeleted)); + } + + default Page selectPageByUserIdOrderByCreateTimeAsc(Long userId, Integer pageNo, Integer pageSize) { + Page page = Page.of(pageNo, pageSize); + return selectPage(page, new LambdaQueryWrapperX() + .eqIfPresent(ProductBrowseHistoryDO::getUserId, userId) + .orderByAsc(ProductBrowseHistoryDO::getCreateTime)); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java new file mode 100644 index 0000000..8a55eaf --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.product.dal.mysql.property; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ProductPropertyMapper extends BaseMapperX { + + default PageResult selectPage(ProductPropertyPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ProductPropertyDO::getName, reqVO.getName()) + .betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ProductPropertyDO::getId)); + } + + default ProductPropertyDO selectByName(String name) { + return selectOne(ProductPropertyDO::getName, name); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java new file mode 100644 index 0000000..402df51 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.product.dal.mysql.property; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface ProductPropertyValueMapper extends BaseMapperX { + + default List selectListByPropertyId(Collection propertyIds) { + return selectList(new LambdaQueryWrapperX() + .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds)); + } + + default ProductPropertyValueDO selectByName(Long propertyId, String name) { + return selectOne(new LambdaQueryWrapperX() + .eq(ProductPropertyValueDO::getPropertyId, propertyId) + .eq(ProductPropertyValueDO::getName, name)); + } + + default void deleteByPropertyId(Long propertyId) { + delete(new LambdaQueryWrapperX() + .eq(ProductPropertyValueDO::getPropertyId, propertyId)); + } + + default PageResult selectPage(ProductPropertyValuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId()) + .likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName()) + .orderByDesc(ProductPropertyValueDO::getId)); + } + + default Integer selectCountByPropertyId(Long propertyId) { + return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue(); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java new file mode 100755 index 0000000..da920a5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.product.dal.mysql.sku; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface ProductSkuMapper extends BaseMapperX { + + @Select("SELECT * FROM product_sku WHERE id = #{id}") + ProductSkuDO selectByIdIncludeDeleted(@Param("id") Long id); + + default List selectListBySpuId(Long spuId) { + return selectList(ProductSkuDO::getSpuId, spuId); + } + + default List selectListBySpuId(Collection spuIds) { + return selectList(ProductSkuDO::getSpuId, spuIds); + } + + default void deleteBySpuId(Long spuId) { + delete(new LambdaQueryWrapperX().eq(ProductSkuDO::getSpuId, spuId)); + } + + /** + * 更新 SKU 库存(增加)、销量(减少) + * + * @param id 编号 + * @param incrCount 增加库存(正数) + */ + default void updateStockIncr(Long id, Integer incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" stock = stock + " + incrCount + + ", sales_count = sales_count - " + incrCount) + .eq(ProductSkuDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新 SKU 库存(减少)、销量(增加) + * + * @param id 编号 + * @param incrCount 减少库存(负数) + * @return 更新条数 + */ + default int updateStockDecr(Long id, Integer incrCount) { + Assert.isTrue(incrCount < 0); + incrCount = - incrCount; // 取正 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .setSql(" stock = stock - " + incrCount + + ", sales_count = sales_count + " + incrCount) + .eq(ProductSkuDO::getId, id) + .ge(ProductSkuDO::getStock, incrCount); + return update(null, updateWrapper); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java new file mode 100755 index 0000000..fc00ae7 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java @@ -0,0 +1,154 @@ +package cn.iocoder.yudao.module.product.dal.mysql.spu; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.enums.ProductConstants; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Objects; +import java.util.Set; + +@Mapper +public interface ProductSpuMapper extends BaseMapperX { + + @Select("SELECT * FROM product_spu WHERE id = #{id}") + ProductSpuDO selectByIdIncludeDeleted(@Param("id") Long id); + + /** + * 获取商品 SPU 分页列表数据 + * + * @param reqVO 分页请求参数 + * @return 商品 SPU 分页列表数据 + */ + default PageResult selectPage(ProductSpuPageReqVO reqVO) { + Integer tabType = reqVO.getTabType(); + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX() + .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) + .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) + .betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ProductSpuDO::getSort) + .orderByDesc(ProductSpuDO::getId); + appendTabQuery(tabType, queryWrapper); + return selectPage(reqVO, queryWrapper); + } + + /** + * 查询触发警戒库存的 SPU 数量 + * + * @return 触发警戒库存的 SPU 数量 + */ + default Long selectCount() { + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX<>(); + // 库存小于等于警戒库存 + queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK) + // 如果库存触发警戒库存且状态为回收站的话则不计入触发警戒库存的个数 + .notIn(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()); + return selectCount(queryWrapper); + } + + /** + * 获得商品 SPU 分页,提供给用户 App 使用 + */ + default PageResult selectPage(AppProductSpuPageReqVO pageReqVO, Set categoryIds) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + // 关键字匹配,目前只匹配商品名 + .likeIfPresent(ProductSpuDO::getName, pageReqVO.getKeyword()) + // 分类 + .inIfPresent(ProductSpuDO::getCategoryId, categoryIds); + // 上架状态 且有库存 + query.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()); + + // 排序逻辑 + if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) { + query.last(String.format(" ORDER BY (sales_count + virtual_sales_count) %s, sort DESC, id DESC", + pageReqVO.getSortAsc() ? "ASC" : "DESC")); + } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) { + query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getPrice) + .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); + } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_CREATE_TIME)) { + query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getCreateTime) + .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); + } else { + query.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); + } + return selectPage(pageReqVO, query); + } + + /** + * 更新商品 SPU 库存 + * + * @param id 商品 SPU 编号 + * @param incrCount 增加的库存数量 + */ + default void updateStock(Long id, Integer incrCount) { + // 拼接 SQL + if (incrCount == 0) { + return; + } + String sql; + if (incrCount > 0) { + sql = " stock = stock + " + incrCount + ", sales_count = sales_count - " + incrCount; + } else { + sql = " stock = stock - " + Math.abs(incrCount) + ", sales_count = sales_count + " + Math.abs(incrCount); + } + // 执行更新 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .setSql(sql) + .eq(ProductSpuDO::getId, id); + update(null, updateWrapper); + } + + /** + * 添加后台 Tab 选项的查询条件 + * + * @param tabType 标签类型 + * @param query 查询条件 + */ + static void appendTabQuery(Integer tabType, LambdaQueryWrapperX query) { + // 出售中商品 + if (ObjectUtil.equals(ProductSpuPageReqVO.FOR_SALE, tabType)) { + query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()); + } + // 仓储中商品 + if (ObjectUtil.equals(ProductSpuPageReqVO.IN_WAREHOUSE, tabType)) { + query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()); + } + // 已售空商品 + if (ObjectUtil.equals(ProductSpuPageReqVO.SOLD_OUT, tabType)) { + query.eqIfPresent(ProductSpuDO::getStock, 0); + } + // 警戒库存 + if (ObjectUtil.equals(ProductSpuPageReqVO.ALERT_STOCK, tabType)) { + query.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK) + // 如果库存触发警戒库存且状态为回收站的话则不在警戒库存列表展示 + .notIn(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()); + } + // 回收站 + if (ObjectUtil.equals(ProductSpuPageReqVO.RECYCLE_BIN, tabType)) { + query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()); + } + } + + /** + * 更新商品 SPU 浏览量 + * + * @param id 商品 SPU 编号 + * @param incrCount 增加的数量 + */ + default void updateBrowseCount(Long id, int incrCount) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .setSql(" browse_count = browse_count +" + incrCount) + .eq(ProductSpuDO::getId, id); + update(null, updateWrapper); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java new file mode 100644 index 0000000..b96dde1 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.product.enums; + +/** + * product 字典类型的枚举类 + * + * @author HUIHUI + */ +public interface DictTypeConstants { + + String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态 + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java new file mode 100644 index 0000000..3531b14 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.product.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * Product 错误码枚举类 + * + * product 系统,使用 1-008-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== 商品分类相关 1-008-001-000 ============ + ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_008_001_000, "商品分类不存在"); + ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_008_001_001, "父分类不存在"); + ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_008_001_002, "父分类不能是二级分类"); + ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_008_001_003, "存在子分类,无法删除"); + ErrorCode CATEGORY_DISABLED = new ErrorCode(1_008_001_004, "商品分类({})已禁用,无法使用"); + ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1_008_001_005, "类别下存在商品,无法删除"); + + // ========== 商品品牌相关编号 1-008-002-000 ========== + ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1_008_002_000, "品牌不存在"); + ErrorCode BRAND_DISABLED = new ErrorCode(1_008_002_001, "品牌已禁用"); + ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1_008_002_002, "品牌名称已存在"); + + // ========== 商品属性项 1-008-003-000 ========== + ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1_008_003_000, "属性项不存在"); + ErrorCode PROPERTY_EXISTS = new ErrorCode(1_008_003_001, "属性项的名称已存在"); + ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1_008_003_002, "属性项下存在属性值,无法删除"); + + // ========== 商品属性值 1-008-004-000 ========== + ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1_008_004_000, "属性值不存在"); + ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1_008_004_001, "属性值的名称已存在"); + + // ========== 商品 SPU 1-008-005-000 ========== + ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在"); + ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下"); + ErrorCode SPU_SAVE_FAIL_COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_008_005_002, "商品 SPU 保存失败,原因:优惠劵不存在"); + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_003, "商品 SPU【{}】不处于上架状态"); + ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_004, "商品 SPU 不处于回收站状态"); + + // ========== 商品 SKU 1-008-006-000 ========== + ErrorCode SKU_NOT_EXISTS = new ErrorCode(1_008_006_000, "商品 SKU 不存在"); + ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1_008_006_001, "商品 SKU 的属性组合存在重复"); + ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1_008_006_002, "一个 SPU 下的每个 SKU,其属性项必须一致"); + ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1_008_006_003, "一个 SPU 下的每个 SKU,必须不重复"); + ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1_008_006_004, "商品 SKU 库存不足"); + + // ========== 商品 评价 1-008-007-000 ========== + ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1_008_007_000, "商品评价不存在"); + ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1_008_007_001, "订单的商品评价已存在"); + + // ========== 商品 收藏 1-008-008-000 ========== + ErrorCode FAVORITE_EXISTS = new ErrorCode(1_008_008_000, "该商品已经被收藏"); + ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1_008_008_001, "商品收藏不存在"); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java new file mode 100644 index 0000000..f3570c5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.product.enums; + +/** + * Product 常量 + * + * @author HUIHUI + */ +public interface ProductConstants { + + /** + * 警戒库存 TODO 警戒库存暂时为 10,后期需要使用常量或者数据库配置替换 + */ + int ALERT_STOCK = 10; + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java new file mode 100644 index 0000000..f128a60 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentAuditStatusEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.product.enums.comment; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 商品评论的审批状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum ProductCommentAuditStatusEnum implements ArrayValuable { + + NONE(0, "待审核"), + APPROVE(1, "审批通过"), + REJECT(2, "审批不通过"),; + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(ProductCommentAuditStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 审批状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java new file mode 100644 index 0000000..58c6a45 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/comment/ProductCommentScoresEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.product.enums.comment; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 商品评论的星级枚举 + * + * @author wangzhs + */ +@Getter +@AllArgsConstructor +public enum ProductCommentScoresEnum implements ArrayValuable { + + ONE(1, "1星"), + TWO(2, "2星"), + THREE(3, "3星"), + FOUR(4, "4星"), + FIVE(5, "5星"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(ProductCommentScoresEnum::getScores).toArray(Integer[]::new); + + /** + * 星级 + */ + private final Integer scores; + + /** + * 星级名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java new file mode 100644 index 0000000..5735f49 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.product.enums.spu; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 商品 SPU 状态 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum ProductSpuStatusEnum implements ArrayValuable { + + RECYCLE(-1, "回收站"), + DISABLE(0, "下架"), + ENABLE(1, "上架"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(ProductSpuStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + + /** + * 判断是否处于【上架】状态 + * + * @param status 状态 + * @return 是否处于【上架】状态 + */ + public static boolean isEnable(Integer status) { + return ENABLE.getStatus().equals(status); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java new file mode 100644 index 0000000..d2e1c93 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 product 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.product.framework; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java new file mode 100644 index 0000000..7da1799 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/config/ProductWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.product.framework.web.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * product 模块的 web 组件的 Configuration + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +public class ProductWebConfiguration { + + /** + * product 模块的 API 分组 + */ + @Bean + public GroupedOpenApi productGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("product"); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java new file mode 100644 index 0000000..f4adb2d --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * product 模块的 web 配置 + */ +package cn.iocoder.yudao.module.product.framework.web; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/package-info.java new file mode 100644 index 0000000..e329429 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/package-info.java @@ -0,0 +1,8 @@ +/** + * product 模块,主要实现交易相关功能 + * 例如:订单、退款、购物车等功能。 + * + * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 product_ 开头,方便在数据库中区分 + */ +package cn.iocoder.yudao.module.product; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java new file mode 100644 index 0000000..a7ed6b4 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.product.service.brand; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; + +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商品品牌 Service 接口 + * + * @author 芋道源码 + */ +public interface ProductBrandService { + + /** + * 创建品牌 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createBrand(@Valid ProductBrandCreateReqVO createReqVO); + + /** + * 更新品牌 + * + * @param updateReqVO 更新信息 + */ + void updateBrand(@Valid ProductBrandUpdateReqVO updateReqVO); + + /** + * 删除品牌 + * + * @param id 编号 + */ + void deleteBrand(Long id); + + /** + * 获得品牌 + * + * @param id 编号 + * @return 品牌 + */ + ProductBrandDO getBrand(Long id); + + /** + * 获得品牌列表 + * + * @param ids 编号 + * @return 品牌列表 + */ + List getBrandList(Collection ids); + + /** + * 获得品牌列表 + * + * @param listReqVO 请求参数 + * @return 品牌列表 + */ + List getBrandList(ProductBrandListReqVO listReqVO); + + /** + * 验证选择的商品分类是否合法 + * + * @param id 分类编号 + */ + void validateProductBrand(Long id); + + /** + * 获得品牌分页 + * + * @param pageReqVO 分页查询 + * @return 品牌分页 + */ + PageResult getBrandPage(ProductBrandPageReqVO pageReqVO); + + /** + * 获取指定状态的品牌列表 + * + * @param status 状态 + * @return 返回品牌列表 + */ + List getBrandListByStatus(Integer status); +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java new file mode 100644 index 0000000..a3fc918 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.product.service.brand; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; +import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper; +import com.google.common.annotations.VisibleForTesting; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 品牌 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductBrandServiceImpl implements ProductBrandService { + + @Resource + private ProductBrandMapper brandMapper; + + @Override + public Long createBrand(ProductBrandCreateReqVO createReqVO) { + // 校验 + validateBrandNameUnique(null, createReqVO.getName()); + + // 插入 + ProductBrandDO brand = ProductBrandConvert.INSTANCE.convert(createReqVO); + brandMapper.insert(brand); + // 返回 + return brand.getId(); + } + + @Override + public void updateBrand(ProductBrandUpdateReqVO updateReqVO) { + // 校验存在 + validateBrandExists(updateReqVO.getId()); + validateBrandNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // 更新 + ProductBrandDO updateObj = ProductBrandConvert.INSTANCE.convert(updateReqVO); + brandMapper.updateById(updateObj); + } + + @Override + public void deleteBrand(Long id) { + // 校验存在 + validateBrandExists(id); + // 删除 + brandMapper.deleteById(id); + } + + private void validateBrandExists(Long id) { + if (brandMapper.selectById(id) == null) { + throw exception(BRAND_NOT_EXISTS); + } + } + + @VisibleForTesting + public void validateBrandNameUnique(Long id, String name) { + ProductBrandDO brand = brandMapper.selectByName(name); + if (brand == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 + if (id == null) { + throw exception(BRAND_NAME_EXISTS); + } + if (!brand.getId().equals(id)) { + throw exception(BRAND_NAME_EXISTS); + } + } + + @Override + public ProductBrandDO getBrand(Long id) { + return brandMapper.selectById(id); + } + + @Override + public List getBrandList(Collection ids) { + return brandMapper.selectBatchIds(ids); + } + + @Override + public List getBrandList(ProductBrandListReqVO listReqVO) { + return brandMapper.selectList(listReqVO); + } + + @Override + public void validateProductBrand(Long id) { + ProductBrandDO brand = brandMapper.selectById(id); + if (brand == null) { + throw exception(BRAND_NOT_EXISTS); + } + if (brand.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { + throw exception(BRAND_DISABLED); + } + } + + @Override + public PageResult getBrandPage(ProductBrandPageReqVO pageReqVO) { + return brandMapper.selectPage(pageReqVO); + } + + @Override + public List getBrandListByStatus(Integer status) { + return brandMapper.selectListByStatus(status); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java new file mode 100644 index 0000000..59495a1 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * 商品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface ProductCategoryService { + + /** + * 创建商品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCategory(@Valid ProductCategorySaveReqVO createReqVO); + + /** + * 更新商品分类 + * + * @param updateReqVO 更新信息 + */ + void updateCategory(@Valid ProductCategorySaveReqVO updateReqVO); + + /** + * 删除商品分类 + * + * @param id 编号 + */ + void deleteCategory(Long id); + + /** + * 获得商品分类 + * + * @param id 编号 + * @return 商品分类 + */ + ProductCategoryDO getCategory(Long id); + + /** + * 校验商品分类 + * + * @param id 分类编号 + */ + void validateCategory(Long id); + + /** + * 获得商品分类的层级 + * + * @param id 编号 + * @return 商品分类的层级 + */ + Integer getCategoryLevel(Long id); + + /** + * 获得商品分类列表 + * + * @param listReqVO 查询条件 + * @return 商品分类列表 + */ + List getCategoryList(ProductCategoryListReqVO listReqVO); + + /** + * 获得开启状态的商品分类列表 + * + * @return 商品分类列表 + */ + List getEnableCategoryList(); + + /** + * 获得开启状态的商品分类列表,指定编号 + * + * @param ids 商品分类编号数组 + * @return 商品分类列表 + */ + List getEnableCategoryList(List ids); + + /** + * 校验商品分类是否有效。如下情况,视为无效: + * 1. 商品分类编号不存在 + * 2. 商品分类被禁用 + * 3. 商品分类层级校验,必须使用第二级的商品分类及以下 + * + * @param ids 商品分类编号数组 + */ + void validateCategoryList(Collection ids); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java new file mode 100644 index 0000000..0d30dd5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java @@ -0,0 +1,184 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL; +import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 商品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductCategoryServiceImpl implements ProductCategoryService { + + @Resource + private ProductCategoryMapper productCategoryMapper; + @Resource + @Lazy // 循环依赖,避免报错 + private ProductSpuService productSpuService; + + @Override + public Long createCategory(ProductCategorySaveReqVO createReqVO) { + // 校验父分类存在 + validateParentProductCategory(createReqVO.getParentId()); + + // 插入 + ProductCategoryDO category = BeanUtils.toBean(createReqVO, ProductCategoryDO.class); + productCategoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateCategory(ProductCategorySaveReqVO updateReqVO) { + // 校验分类是否存在 + validateProductCategoryExists(updateReqVO.getId()); + // 校验父分类存在 + validateParentProductCategory(updateReqVO.getParentId()); + + // 更新 + ProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ProductCategoryDO.class); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteCategory(Long id) { + // 校验分类是否存在 + validateProductCategoryExists(id); + // 校验是否还有子分类 + if (productCategoryMapper.selectCountByParentId(id) > 0) { + throw exception(CATEGORY_EXISTS_CHILDREN); + } + // 校验分类是否绑定了 SPU + Long spuCount = productSpuService.getSpuCountByCategoryId(id); + if (spuCount > 0) { + throw exception(CATEGORY_HAVE_BIND_SPU); + } + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateParentProductCategory(Long id) { + // 如果是根分类,无需验证 + if (Objects.equals(id, PARENT_ID_NULL)) { + return; + } + // 父分类不存在 + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_PARENT_NOT_EXISTS); + } + // 父分类不能是二级分类 + if (!Objects.equals(category.getParentId(), PARENT_ID_NULL)) { + throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL); + } + } + + private void validateProductCategoryExists(Long id) { + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + } + + @Override + public void validateCategoryList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + // 获得商品分类信息 + List list = productCategoryMapper.selectBatchIds(ids); + Map categoryMap = CollectionUtils.convertMap(list, ProductCategoryDO::getId); + // 校验 + ids.forEach(id -> { + // 校验分类是否存在 + ProductCategoryDO category = categoryMap.get(id); + if (category == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + // 校验分类是否启用 + if (!CommonStatusEnum.ENABLE.getStatus().equals(category.getStatus())) { + throw exception(CATEGORY_DISABLED, category.getName()); + } + // 商品分类层级校验,必须使用第二级的商品分类 + if (getCategoryLevel(id) < CATEGORY_LEVEL) { + throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR); + } + }); + } + + @Override + public ProductCategoryDO getCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public void validateCategory(Long id) { + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + if (Objects.equals(category.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(CATEGORY_DISABLED, category.getName()); + } + } + + @Override + public Integer getCategoryLevel(Long id) { + if (Objects.equals(id, PARENT_ID_NULL)) { + return 0; + } + int level = 1; + // for 的原因,是因为避免脏数据,导致可能的死循环。一般不会超过 100 层哈 + for (int i = 0; i < Byte.MAX_VALUE; i++) { + // 如果没有父节点,break 结束 + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null + || Objects.equals(category.getParentId(), PARENT_ID_NULL)) { + break; + } + // 继续递归父节点 + level++; + id = category.getParentId(); + } + return level; + } + + @Override + public List getCategoryList(ProductCategoryListReqVO listReqVO) { + return productCategoryMapper.selectList(listReqVO); + } + + @Override + public List getEnableCategoryList() { + return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); + } + + @Override + public List getEnableCategoryList(List ids) { + return productCategoryMapper.selectListByIdAndStatus(ids, CommonStatusEnum.ENABLE.getStatus()); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java new file mode 100644 index 0000000..b54e219 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.product.service.comment; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * 商品评论 Service 接口 + * + * @author wangzhs + */ +@Service +@Validated +public interface ProductCommentService { + + /** + * 创建商品评论 + * 后台管理员创建评论使用 + * + * @param createReqVO 商品评价创建 Request VO 对象 + */ + void createComment(ProductCommentCreateReqVO createReqVO); + + /** + * 创建评论 + * 创建商品评论 APP 端创建商品评论使用 + * + * @param createReqDTO 创建请求 dto + * @return 返回评论 id + */ + Long createComment(ProductCommentCreateReqDTO createReqDTO); + + /** + * 修改评论是否可见 + * + * @param updateReqVO 修改评论可见 + */ + void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO); + + /** + * 商家回复 + * + * @param replyVO 商家回复 + * @param userId 管理后台商家登陆人 ID + */ + void replyComment(ProductCommentReplyReqVO replyVO, Long userId); + + /** + * 【管理员】获得商品评价分页 + * + * @param pageReqVO 分页查询 + * @return 商品评价分页 + */ + PageResult getCommentPage(ProductCommentPageReqVO pageReqVO); + + /** + * 【会员】获得商品评价分页 + * + * @param pageVO 分页查询 + * @param visible 是否可见 + * @return 商品评价分页 + */ + PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java new file mode 100644 index 0000000..34b0766 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.product.service.comment; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; +import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 商品评论 Service 实现类 + * + * @author wangzhs + */ +@Service +@Validated +public class ProductCommentServiceImpl implements ProductCommentService { + + @Resource + private ProductCommentMapper productCommentMapper; + + @Resource + private ProductSpuService productSpuService; + + @Resource + @Lazy + private ProductSkuService productSkuService; + + @Resource + private MemberUserApi memberUserApi; + + @Override + public void createComment(ProductCommentCreateReqVO createReqVO) { + // 校验 SKU + ProductSkuDO sku = validateSku(createReqVO.getSkuId()); + // 校验 SPU + ProductSpuDO spu = validateSpu(sku.getSpuId()); + + // 创建评论 + ProductCommentDO comment = ProductCommentConvert.INSTANCE.convert(createReqVO, spu, sku); + productCommentMapper.insert(comment); + } + + @Override + public Long createComment(ProductCommentCreateReqDTO createReqDTO) { + // 校验 SKU + ProductSkuDO sku = validateSku(createReqDTO.getSkuId()); + // 校验 SPU + ProductSpuDO spu = validateSpu(sku.getSpuId()); + // 校验评论 + validateCommentExists(createReqDTO.getUserId(), createReqDTO.getOrderItemId()); + // 获取用户详细信息 + MemberUserRespDTO user = memberUserApi.getUser(createReqDTO.getUserId()); + + // 创建评论 + ProductCommentDO comment = ProductCommentConvert.INSTANCE.convert(createReqDTO, spu, sku, user); + productCommentMapper.insert(comment); + return comment.getId(); + } + + /** + * 判断当前订单的当前商品用户是否评价过 + * + * @param userId 用户编号 + * @param orderItemId 订单项编号 + */ + private void validateCommentExists(Long userId, Long orderItemId) { + ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemId(userId, orderItemId); + if (exist != null) { + throw exception(COMMENT_ORDER_EXISTS); + } + } + + private ProductSkuDO validateSku(Long skuId) { + ProductSkuDO sku = productSkuService.getSku(skuId, true); + if (sku == null) { + throw exception(SKU_NOT_EXISTS); + } + return sku; + } + + private ProductSpuDO validateSpu(Long spuId) { + ProductSpuDO spu = productSpuService.getSpu(spuId, true); + if (null == spu) { + throw exception(SPU_NOT_EXISTS); + } + return spu; + } + + @Override + public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) { + // 校验评论是否存在 + validateCommentExists(updateReqVO.getId()); + + // 更新可见状态 + productCommentMapper.updateById(new ProductCommentDO().setId(updateReqVO.getId()) + .setVisible(updateReqVO.getVisible())); + } + + @Override + public void replyComment(ProductCommentReplyReqVO replyVO, Long userId) { + // 校验评论是否存在 + validateCommentExists(replyVO.getId()); + // 回复评论 + productCommentMapper.updateById(new ProductCommentDO().setId(replyVO.getId()) + .setReplyTime(LocalDateTime.now()).setReplyUserId(userId) + .setReplyStatus(Boolean.TRUE).setReplyContent(replyVO.getReplyContent())); + } + + private ProductCommentDO validateCommentExists(Long id) { + ProductCommentDO productComment = productCommentMapper.selectById(id); + if (productComment == null) { + throw exception(COMMENT_NOT_EXISTS); + } + return productComment; + } + + @Override + public PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) { + return productCommentMapper.selectPage(pageVO, visible); + } + + @Override + public PageResult getCommentPage(ProductCommentPageReqVO pageReqVO) { + return productCommentMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java new file mode 100644 index 0000000..e71424d --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.product.service.favorite; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; + +import jakarta.validation.Valid; + +/** + * 商品收藏 Service 接口 + * + * @author jason + */ +public interface ProductFavoriteService { + + /** + * 创建商品收藏 + * + * @param userId 用户编号 + * @param spuId SPU 编号 + */ + Long createFavorite(Long userId, Long spuId); + + /** + * 取消商品收藏 + * + * @param userId 用户编号 + * @param spuId SPU 编号 + */ + void deleteFavorite(Long userId, Long spuId); + + /** + * 分页查询用户收藏列表 + * + * @param userId 用户编号 + * @param reqVO 请求 vo + */ + PageResult getFavoritePage(Long userId, @Valid AppFavoritePageReqVO reqVO); + + /** + * 分页查询用户收藏列表 + * + * @param reqVO 请求 vo + */ + PageResult getFavoritePage(@Valid ProductFavoritePageReqVO reqVO); + + /** + * 获取收藏过商品 + * + * @param userId 用户编号 + * @param spuId SPU 编号 + */ + ProductFavoriteDO getFavorite(Long userId, Long spuId); + + /** + * 获取用户收藏数量 + * + * @param userId 用户编号 + * @return 数量 + */ + Long getFavoriteCount(Long userId); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java new file mode 100644 index 0000000..61b4963 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.product.service.favorite; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.favorite.vo.ProductFavoritePageReqVO; +import cn.iocoder.yudao.module.product.controller.app.favorite.vo.AppFavoritePageReqVO; +import cn.iocoder.yudao.module.product.convert.favorite.ProductFavoriteConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO; +import cn.iocoder.yudao.module.product.dal.mysql.favorite.ProductFavoriteMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; +import jakarta.validation.Valid; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.FAVORITE_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.FAVORITE_NOT_EXISTS; + +/** + * 商品收藏 Service 实现类 + * + * @author jason + */ +@Service +@Validated +public class ProductFavoriteServiceImpl implements ProductFavoriteService { + + @Resource + private ProductFavoriteMapper productFavoriteMapper; + + @Override + public Long createFavorite(Long userId, Long spuId) { + ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); + if (favorite != null) { + throw exception(FAVORITE_EXISTS); + } + + ProductFavoriteDO entity = ProductFavoriteConvert.INSTANCE.convert(userId, spuId); + productFavoriteMapper.insert(entity); + return entity.getId(); + } + + @Override + public void deleteFavorite(Long userId, Long spuId) { + ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); + if (favorite == null) { + throw exception(FAVORITE_NOT_EXISTS); + } + + productFavoriteMapper.deleteById(favorite.getId()); + } + + @Override + public PageResult getFavoritePage(Long userId, @Valid AppFavoritePageReqVO reqVO) { + return productFavoriteMapper.selectPageByUserAndType(userId, reqVO); + } + + @Override + public PageResult getFavoritePage(@Valid ProductFavoritePageReqVO reqVO) { + return productFavoriteMapper.selectPageByUserId(reqVO); + } + + @Override + public ProductFavoriteDO getFavorite(Long userId, Long spuId) { + return productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); + } + + @Override + public Long getFavoriteCount(Long userId) { + return productFavoriteMapper.selectCountByUserId(userId); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java new file mode 100644 index 0000000..10f3a71 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.product.service.history; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; +import org.springframework.scheduling.annotation.Async; + +import java.util.Collection; + +/** + * 商品浏览记录 Service 接口 + * + * @author owen + */ +public interface ProductBrowseHistoryService { + + /** + * 创建商品浏览记录 + * + * @param userId 用户编号 + * @param spuId SPU 编号 + */ + @Async + void createBrowseHistory(Long userId, Long spuId); + + /** + * 隐藏用户商品浏览记录 + * + * @param userId 用户编号 + * @param spuId SPU 编号 + */ + void hideUserBrowseHistory(Long userId, Collection spuId); + + /** + * 获得商品浏览记录分页 + * + * @param pageReqVO 分页查询 + * @return 商品浏览记录分页 + */ + PageResult getBrowseHistoryPage(ProductBrowseHistoryPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java new file mode 100644 index 0000000..b015299 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.product.service.history; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; +import cn.iocoder.yudao.module.product.dal.mysql.history.ProductBrowseHistoryMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; + +/** + * 商品浏览记录 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryService { + + private static final int USER_STORE_MAXIMUM = 100; + + @Resource + private ProductBrowseHistoryMapper browseHistoryMapper; + + @Override + public void createBrowseHistory(Long userId, Long spuId) { + // 用户未登录时不记录 + if (userId == null) { + return; + } + + // 情况一:同一个商品,只保留最新的一条记录 + ProductBrowseHistoryDO history = browseHistoryMapper.selectByUserIdAndSpuId(userId, spuId); + if (history != null) { + browseHistoryMapper.deleteById(history); + } else { + // 情况二:限制每个用户的浏览记录的条数(只查一条最早地记录、记录总数) + // TODO @疯狂:这里最好先查询一次数量。如果发现超过了,再删除;主要考虑,可能有部分不超过,提前就多了一次 sql 查询了 + Page pageResult = browseHistoryMapper.selectPageByUserIdOrderByCreateTimeAsc(userId, 1, 1); + if (pageResult.getTotal() >= USER_STORE_MAXIMUM) { + browseHistoryMapper.deleteById(CollUtil.getFirst(pageResult.getRecords())); + } + } + + // 插入 + ProductBrowseHistoryDO browseHistory = new ProductBrowseHistoryDO() + .setUserId(userId) + .setSpuId(spuId); + browseHistoryMapper.insert(browseHistory); + } + + @Override + public void hideUserBrowseHistory(Long userId, Collection spuIds) { + browseHistoryMapper.updateUserDeletedByUserId(userId, spuIds, true); + } + + @Override + public PageResult getBrowseHistoryPage(ProductBrowseHistoryPageReqVO pageReqVO) { + return browseHistoryMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java new file mode 100644 index 0000000..0872136 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.product.service.property; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; + +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商品属性项 Service 接口 + * + * @author 芋道源码 + */ +public interface ProductPropertyService { + + /** + * 创建属性项 + * 注意,如果已经存在该属性项,直接返回它的编号即可 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProperty(@Valid ProductPropertySaveReqVO createReqVO); + + /** + * 更新属性项 + * + * @param updateReqVO 更新信息 + */ + void updateProperty(@Valid ProductPropertySaveReqVO updateReqVO); + + /** + * 删除属性项 + * + * @param id 编号 + */ + void deleteProperty(Long id); + + /** + * 获取属性名称分页 + * + * @param pageReqVO 分页条件 + * @return 属性项分页 + */ + PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO); + + /** + * 获得指定编号的属性项 + * + * @param id 编号 + * @return 属性项 + */ + ProductPropertyDO getProperty(Long id); + + /** + * 根据属性项的编号的集合,获得对应的属性项数组 + * + * @param ids 属性项的编号的集合 + * @return 属性项数组 + */ + List getPropertyList(Collection ids); + + /** + * 获得指定状态的属性项列表 + * + * @return 属性项列表 + */ + List getPropertyList(); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java new file mode 100644 index 0000000..6c1d328 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.product.service.property; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertySaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 商品属性项 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductPropertyServiceImpl implements ProductPropertyService { + + @Resource + private ProductPropertyMapper productPropertyMapper; + + @Resource + @Lazy // 延迟加载,解决循环依赖问题 + private ProductPropertyValueService productPropertyValueService; + + @Resource + private ProductSkuService productSkuService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createProperty(ProductPropertySaveReqVO createReqVO) { + // 如果已经添加过该属性项,直接返回 + ProductPropertyDO dbProperty = productPropertyMapper.selectByName(createReqVO.getName()); + if (dbProperty != null) { + return dbProperty.getId(); + } + + // 插入 + ProductPropertyDO property = BeanUtils.toBean(createReqVO, ProductPropertyDO.class); + productPropertyMapper.insert(property); + // 返回 + return property.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateProperty(ProductPropertySaveReqVO updateReqVO) { + validatePropertyExists(updateReqVO.getId()); + // 校验名字重复 + ProductPropertyDO property = productPropertyMapper.selectByName(updateReqVO.getName()); + if (property != null && + ObjUtil.notEqual(property.getId(), updateReqVO.getId())) { + throw exception(PROPERTY_EXISTS); + } + + // 更新 + ProductPropertyDO updateObj = BeanUtils.toBean(updateReqVO, ProductPropertyDO.class); + productPropertyMapper.updateById(updateObj); + // 更新 sku 相关属性 + productSkuService.updateSkuProperty(updateObj.getId(), updateObj.getName()); + } + + @Override + public void deleteProperty(Long id) { + // 校验存在 + validatePropertyExists(id); + // 校验其下是否有规格值 + if (productPropertyValueService.getPropertyValueCountByPropertyId(id) > 0) { + throw exception(PROPERTY_DELETE_FAIL_VALUE_EXISTS); + } + + // 删除 + productPropertyMapper.deleteById(id); + // 同步删除属性值 + productPropertyValueService.deletePropertyValueByPropertyId(id); + } + + private void validatePropertyExists(Long id) { + if (productPropertyMapper.selectById(id) == null) { + throw exception(PROPERTY_NOT_EXISTS); + } + } + + @Override + public PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO) { + return productPropertyMapper.selectPage(pageReqVO); + } + + @Override + public ProductPropertyDO getProperty(Long id) { + return productPropertyMapper.selectById(id); + } + + @Override + public List getPropertyList(Collection ids) { + return productPropertyMapper.selectBatchIds(ids); + } + + @Override + public List getPropertyList() { + return productPropertyMapper.selectList(); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java new file mode 100644 index 0000000..aaa7ff1 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.product.service.property; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueSaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; + +import java.util.Collection; +import java.util.List; + +/** + * 商品属性值 Service 接口 + * + * @author LuoWenFeng + */ +public interface ProductPropertyValueService { + + /** + * 创建属性值 + * 注意,如果已经存在该属性值,直接返回它的编号即可 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPropertyValue(ProductPropertyValueSaveReqVO createReqVO); + + /** + * 更新属性值 + * + * @param updateReqVO 更新信息 + */ + void updatePropertyValue(ProductPropertyValueSaveReqVO updateReqVO); + + /** + * 删除属性值 + * + * @param id 编号 + */ + void deletePropertyValue(Long id); + + /** + * 获得属性值 + * + * @param id 编号 + * @return 属性值 + */ + ProductPropertyValueDO getPropertyValue(Long id); + + /** + * 根据属性项编号数组,获得属性值列表 + * + * @param propertyIds 属性项目编号数组 + * @return 属性值列表 + */ + List getPropertyValueListByPropertyId(Collection propertyIds); + + /** + * 根据属性项编号,活的属性值数量 + * + * @param propertyId 属性项编号数 + * @return 属性值数量 + */ + Integer getPropertyValueCountByPropertyId(Long propertyId); + + /** + * 获取属性值的分页 + * + * @param pageReqVO 查询条件 + * @return 属性值的分页 + */ + PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO); + + /** + * 删除指定属性项编号下的属性值们 + * + * @param propertyId 属性项的编号 + */ + void deletePropertyValueByPropertyId(Long propertyId); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java new file mode 100644 index 0000000..1293458 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.product.service.property; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueSaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS; + +/** + * 商品属性值 Service 实现类 + * + * @author LuoWenFeng + */ +@Service +@Validated +public class ProductPropertyValueServiceImpl implements ProductPropertyValueService { + + @Resource + private ProductPropertyValueMapper productPropertyValueMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ProductSkuService productSkuService; + + @Override + public Long createPropertyValue(ProductPropertyValueSaveReqVO createReqVO) { + // 如果已经添加过该属性值,直接返回 + ProductPropertyValueDO dbValue = productPropertyValueMapper.selectByName( + createReqVO.getPropertyId(), createReqVO.getName()); + if (dbValue != null) { + return dbValue.getId(); + } + + // 新增 + ProductPropertyValueDO value = BeanUtils.toBean(createReqVO, ProductPropertyValueDO.class); + productPropertyValueMapper.insert(value); + return value.getId(); + } + + @Override + public void updatePropertyValue(ProductPropertyValueSaveReqVO updateReqVO) { + validatePropertyValueExists(updateReqVO.getId()); + // 校验名字唯一 + ProductPropertyValueDO value = productPropertyValueMapper.selectByName + (updateReqVO.getPropertyId(), updateReqVO.getName()); + if (value != null && !value.getId().equals(updateReqVO.getId())) { + throw exception(PROPERTY_VALUE_EXISTS); + } + + // 更新 + ProductPropertyValueDO updateObj = BeanUtils.toBean(updateReqVO, ProductPropertyValueDO.class); + productPropertyValueMapper.updateById(updateObj); + // 更新 sku 相关属性 + productSkuService.updateSkuPropertyValue(updateObj.getId(), updateObj.getName()); + } + + @Override + public void deletePropertyValue(Long id) { + validatePropertyValueExists(id); + productPropertyValueMapper.deleteById(id); + } + + private void validatePropertyValueExists(Long id) { + if (productPropertyValueMapper.selectById(id) == null) { + throw exception(PROPERTY_VALUE_NOT_EXISTS); + } + } + + @Override + public ProductPropertyValueDO getPropertyValue(Long id) { + return productPropertyValueMapper.selectById(id); + } + + @Override + public List getPropertyValueListByPropertyId(Collection propertyIds) { + return productPropertyValueMapper.selectListByPropertyId(propertyIds); + } + + @Override + public Integer getPropertyValueCountByPropertyId(Long propertyId) { + return productPropertyValueMapper.selectCountByPropertyId(propertyId); + } + + @Override + public PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO) { + return productPropertyValueMapper.selectPage(pageReqVO); + } + + @Override + public void deletePropertyValueByPropertyId(Long propertyId) { + productPropertyValueMapper.deleteByPropertyId(propertyId); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java new file mode 100755 index 0000000..749ef45 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.product.service.sku; + +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; + +import java.util.Collection; +import java.util.List; + +/** + * 商品 SKU Service 接口 + * + * @author 芋道源码 + */ +public interface ProductSkuService { + + /** + * 删除商品 SKU + * + * @param id 编号 + */ + void deleteSku(Long id); + + /** + * 获得商品 SKU 信息 + * + * @param id 编号 + * @return 商品 SKU 信息 + */ + ProductSkuDO getSku(Long id); + + /** + * 获得商品 SKU 信息 + * + * @param id 编号 + * @param includeDeleted 是否包含已删除的 + * @return 商品 SKU 信息 + */ + ProductSkuDO getSku(Long id, boolean includeDeleted); + + /** + * 获得商品 SKU 列表 + * + * @param ids 编号 + * @return 商品sku列表 + */ + List getSkuList(Collection ids); + + /** + * 对 sku 的组合的属性等进行合法性校验 + * + * @param list sku组合的集合 + */ + void validateSkuList(List list, Boolean specType); + + /** + * 批量创建 SKU + * + * @param spuId 商品 SPU 编号 + * @param list SKU 对象集合 + */ + void createSkuList(Long spuId, List list); + + /** + * 根据 SPU 编号,批量更新它的 SKU 信息 + * + * @param spuId SPU 编码 + * @param skus SKU 的集合 + */ + void updateSkuList(Long spuId, List skus); + + /** + * 更新 SKU 库存(增量) + *

+ * 如果更新的库存不足,会抛出异常 + * + * @param updateStockReqDTO 更行请求 + */ + void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); + + /** + * 获得商品 SKU 集合 + * + * @param spuId spu 编号 + * @return 商品sku 集合 + */ + List getSkuListBySpuId(Long spuId); + + /** + * 获得 spu 对应的 SKU 集合 + * + * @param spuIds spu 编码集合 + * @return 商品 sku 集合 + */ + List getSkuListBySpuId(Collection spuIds); + + /** + * 通过 spuId 删除 sku 信息 + * + * @param spuId spu 编码 + */ + void deleteSkuBySpuId(Long spuId); + + /** + * 更新 sku 属性 + * + * @param propertyId 属性 id + * @param propertyName 属性名 + * @return int 影响的行数 + */ + int updateSkuProperty(Long propertyId, String propertyName); + + /** + * 更新 sku 属性值 + * + * @param propertyValueId 属性值 id + * @param propertyValueName 属性值名字 + * @return int 影响的行数 + */ + int updateSkuPropertyValue(Long propertyValueId, String propertyValueName); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java new file mode 100755 index 0000000..d79e067 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java @@ -0,0 +1,278 @@ +package cn.iocoder.yudao.module.product.service.sku; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.*; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 商品 SKU Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductSkuServiceImpl implements ProductSkuService { + + @Resource + private ProductSkuMapper productSkuMapper; + + @Resource + @Lazy // 循环依赖,避免报错 + private ProductSpuService productSpuService; + @Resource + @Lazy // 循环依赖,避免报错 + private ProductPropertyService productPropertyService; + @Resource + private ProductPropertyValueService productPropertyValueService; + + @Override + public void deleteSku(Long id) { + // 校验存在 + validateSkuExists(id); + // 删除 + productSkuMapper.deleteById(id); + } + + private void validateSkuExists(Long id) { + if (productSkuMapper.selectById(id) == null) { + throw exception(SKU_NOT_EXISTS); + } + } + + @Override + public ProductSkuDO getSku(Long id) { + return productSkuMapper.selectById(id); + } + + @Override + public ProductSkuDO getSku(Long id, boolean includeDeleted) { + if (includeDeleted) { + return productSkuMapper.selectByIdIncludeDeleted(id); + } + return getSku(id); + } + + @Override + public List getSkuList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return productSkuMapper.selectBatchIds(ids); + } + + @Override + public void validateSkuList(List skus, Boolean specType) { + // 0、校验skus是否为空 + if (CollUtil.isEmpty(skus)) { + throw exception(SKU_NOT_EXISTS); + } + // 单规格,赋予单规格默认属性 + if (ObjectUtil.equal(specType, false)) { + ProductSkuSaveReqVO skuVO = skus.get(0); + List properties = new ArrayList<>(); + ProductSkuSaveReqVO.Property property = new ProductSkuSaveReqVO.Property() + .setPropertyId(ProductPropertyDO.ID_DEFAULT).setPropertyName(ProductPropertyDO.NAME_DEFAULT) + .setValueId(ProductPropertyValueDO.ID_DEFAULT).setValueName(ProductPropertyValueDO.NAME_DEFAULT); + properties.add(property); + skuVO.setProperties(properties); + return; // 单规格不需要后续的校验 + } + + // 1、校验属性项存在 + Set propertyIds = skus.stream().filter(p -> p.getProperties() != null) + // 遍历多个 Property 属性 + .flatMap(p -> p.getProperties().stream()) + // 将每个 Property 转换成对应的 propertyId,最后形成集合 + .map(ProductSkuSaveReqVO.Property::getPropertyId) + .collect(Collectors.toSet()); + List propertyList = productPropertyService.getPropertyList(propertyIds); + if (propertyList.size() != propertyIds.size()) { + throw exception(PROPERTY_NOT_EXISTS); + } + + // 2. 校验,一个 SKU 下,没有重复的属性。校验方式是,遍历每个 SKU ,看看是否有重复的属性 propertyId + Map propertyValueMap = convertMap(productPropertyValueService.getPropertyValueListByPropertyId(propertyIds), ProductPropertyValueDO::getId); + skus.forEach(sku -> { + Set skuPropertyIds = convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId()); + if (skuPropertyIds.size() != sku.getProperties().size()) { + throw exception(SKU_PROPERTIES_DUPLICATED); + } + }); + + // 3. 再校验,每个 Sku 的属性值的数量,是一致的。 + int attrValueIdsSize = skus.get(0).getProperties().size(); + for (int i = 1; i < skus.size(); i++) { + if (attrValueIdsSize != skus.get(i).getProperties().size()) { + throw exception(SPU_ATTR_NUMBERS_MUST_BE_EQUALS); + } + } + + // 4. 最后校验,每个 Sku 之间不是重复的 + // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. + Set> skuAttrValues = new HashSet<>(); + for (ProductSkuSaveReqVO sku : skus) { + // 添加失败,说明重复 + if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuSaveReqVO.Property::getValueId))) { + throw exception(SPU_SKU_NOT_DUPLICATE); + } + } + } + + @Override + public void createSkuList(Long spuId, List skuCreateReqList) { + List skus = BeanUtils.toBean(skuCreateReqList, ProductSkuDO.class, sku -> sku.setSpuId(spuId)); + productSkuMapper.insertBatch(skus); + } + + @Override + public List getSkuListBySpuId(Long spuId) { + return productSkuMapper.selectListBySpuId(spuId); + } + + @Override + public List getSkuListBySpuId(Collection spuIds) { + if (CollUtil.isEmpty(spuIds)) { + return Collections.emptyList(); + } + return productSkuMapper.selectListBySpuId(spuIds); + } + + @Override + public void deleteSkuBySpuId(Long spuId) { + productSkuMapper.deleteBySpuId(spuId); + } + + @Override + public int updateSkuProperty(Long propertyId, String propertyName) { + // 获取所有的 sku + List skuDOList = productSkuMapper.selectList(); + // 处理后需要更新的 sku + List updateSkus = new ArrayList<>(); + if (CollUtil.isEmpty(skuDOList)) { + return 0; + } + skuDOList.stream().filter(sku -> sku.getProperties() != null) + .forEach(sku -> sku.getProperties().forEach(property -> { + if (property.getPropertyId().equals(propertyId)) { + property.setPropertyName(propertyName); + updateSkus.add(sku); + } + })); + if (CollUtil.isEmpty(updateSkus)) { + return 0; + } + + productSkuMapper.updateBatch(updateSkus); + return updateSkus.size(); + } + + @Override + public int updateSkuPropertyValue(Long propertyValueId, String propertyValueName) { + // 获取所有的 sku + List skuDOList = productSkuMapper.selectList(); + // 处理后需要更新的 sku + List updateSkus = new ArrayList<>(); + if (CollUtil.isEmpty(skuDOList)) { + return 0; + } + skuDOList.stream() + .filter(sku -> sku.getProperties() != null) + .forEach(sku -> sku.getProperties().forEach(property -> { + if (property.getValueId().equals(propertyValueId)) { + property.setValueName(propertyValueName); + updateSkus.add(sku); + } + })); + if (CollUtil.isEmpty(updateSkus)) { + return 0; + } + + productSkuMapper.updateBatch(updateSkus); + return updateSkus.size(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSkuList(Long spuId, List skus) { + // 构建属性与 SKU 的映射关系; + Map existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId), + ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId); + + // 拆分三个集合,新插入的、需要更新的、需要删除的 + List insertSkus = new ArrayList<>(); + List updateSkus = new ArrayList<>(); + List allUpdateSkus = BeanUtils.toBean(skus, ProductSkuDO.class, sku -> sku.setSpuId(spuId)); + allUpdateSkus.forEach(sku -> { + String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku); + // 1、找得到的,进行更新 + Long existsSkuId = existsSkuMap.remove(propertiesKey); + if (existsSkuId != null) { + sku.setId(existsSkuId); + updateSkus.add(sku); + return; + } + // 2、找不到,进行插入 + sku.setSpuId(spuId); + insertSkus.add(sku); + }); + + // 执行最终的批量操作 + if (CollUtil.isNotEmpty(insertSkus)) { + productSkuMapper.insertBatch(insertSkus); + } + if (CollUtil.isNotEmpty(updateSkus)) { + updateSkus.forEach(sku -> productSkuMapper.updateById(sku)); + } + if (CollUtil.isNotEmpty(existsSkuMap)) { + productSkuMapper.deleteBatchIds(existsSkuMap.values()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) { + // 更新 SKU 库存 + updateStockReqDTO.getItems().forEach(item -> { + if (item.getIncrCount() > 0) { + productSkuMapper.updateStockIncr(item.getId(), item.getIncrCount()); + } else if (item.getIncrCount() < 0) { + int updateStockIncr = productSkuMapper.updateStockDecr(item.getId(), item.getIncrCount()); + if (updateStockIncr == 0) { + throw exception(SKU_STOCK_NOT_ENOUGH); + } + } + }); + + // 更新 SPU 库存 + List skus = productSkuMapper.selectBatchIds( + convertSet(updateStockReqDTO.getItems(), ProductSkuUpdateStockReqDTO.Item::getId)); + Map spuStockIncrCounts = ProductSkuConvert.INSTANCE.convertSpuStockMap( + updateStockReqDTO.getItems(), skus); + productSpuService.updateSpuStock(spuStockIncrCounts); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java new file mode 100755 index 0000000..6ed9460 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.product.service.spu; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import jakarta.validation.Valid; +import org.springframework.scheduling.annotation.Async; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 商品 SPU Service 接口 + * + * @author 芋道源码 + */ +public interface ProductSpuService { + + /** + * 创建商品 SPU + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSpu(@Valid ProductSpuSaveReqVO createReqVO); + + /** + * 更新商品 SPU + * + * @param updateReqVO 更新信息 + */ + void updateSpu(@Valid ProductSpuSaveReqVO updateReqVO); + + /** + * 删除商品 SPU + * + * @param id 编号 + */ + void deleteSpu(Long id); + + /** + * 获得商品 SPU + * + * @param id 编号 + * @return 商品 SPU + */ + ProductSpuDO getSpu(Long id); + + /** + * 获得商品 SPU + * + * @param id 编号 + * @param includeDeleted 是否包含已删除的 + * @return 商品 SPU + */ + ProductSpuDO getSpu(Long id, boolean includeDeleted); + + /** + * 获得商品 SPU 列表 + * + * @param ids 编号数组 + * @return 商品 SPU 列表 + */ + List getSpuList(Collection ids); + + /** + * 获得商品 SPU Map + * + * @param ids 编号数组 + * @return 商品 SPU Map + */ + default Map getSpuMap(Collection ids) { + List list = getSpuList(ids); + return CollectionUtils.convertMap(list, ProductSpuDO::getId); + } + + /** + * 获得指定状态的商品 SPU 列表 + * + * @param status 状态 + * @return 商品 SPU 列表 + */ + List getSpuListByStatus(Integer status); + + /** + * 获得商品 SPU 分页,提供给挂你兰后台使用 + * + * @param pageReqVO 分页查询 + * @return 商品spu分页 + */ + PageResult getSpuPage(ProductSpuPageReqVO pageReqVO); + + /** + * 获得商品 SPU 分页,提供给用户 App 使用 + * + * @param pageReqVO 分页查询 + * @return 商品 SPU 分页 + */ + PageResult getSpuPage(AppProductSpuPageReqVO pageReqVO); + + /** + * 更新商品 SPU 库存(增量) + * + * @param stockIncrCounts SPU 编号与库存变化(增量)的映射 + */ + void updateSpuStock(Map stockIncrCounts); + + /** + * 更新 SPU 状态 + * + * @param updateReqVO 更新请求 + */ + void updateSpuStatus(ProductSpuUpdateStatusReqVO updateReqVO); + + /** + * 获取 SPU 列表标签对应的 Count 数量 + * + * @return Count 数量 + */ + Map getTabsCount(); + + /** + * 通过分类 categoryId 查询 SPU 个数 + * + * @param categoryId 分类 categoryId + * @return SPU 数量 + */ + Long getSpuCountByCategoryId(Long categoryId); + + + /** + * 校验商品是否有效。如下情况,视为无效: + * 1. 商品编号不存在 + * 2. 商品被禁用 + * + * @param ids 商品编号数组 + * @return 商品 SPU 列表 + */ + List validateSpuList(Collection ids); + + /** + * 更新商品 SPU 浏览量 + * + * @param id 商品 SPU 编号 + * @param incrCount 增加的数量 + */ + @Async + void updateBrowseCount(Long id, int incrCount); + +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java new file mode 100755 index 0000000..fd7f96f --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -0,0 +1,284 @@ +package cn.iocoder.yudao.module.product.service.spu; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; +import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import com.google.common.collect.Maps; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; + +/** + * 商品 SPU Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductSpuServiceImpl implements ProductSpuService { + + @Resource + private ProductSpuMapper productSpuMapper; + + @Resource + @Lazy // 循环依赖,避免报错 + private ProductSkuService productSkuService; + @Resource + private ProductBrandService brandService; + @Resource + private ProductCategoryService categoryService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSpu(ProductSpuSaveReqVO createReqVO) { + // 校验分类、品牌 + validateCategory(createReqVO.getCategoryId()); + brandService.validateProductBrand(createReqVO.getBrandId()); + // 校验 SKU + List skuSaveReqList = createReqVO.getSkus(); + productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); + + ProductSpuDO spu = BeanUtils.toBean(createReqVO, ProductSpuDO.class); + // 初始化 SPU 中 SKU 相关属性 + initSpuFromSkus(spu, skuSaveReqList); + // 插入 SPU + productSpuMapper.insert(spu); + // 插入 SKU + productSkuService.createSkuList(spu.getId(), skuSaveReqList); + // 返回 + return spu.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSpu(ProductSpuSaveReqVO updateReqVO) { + // 校验 SPU 是否存在 + ProductSpuDO spu = validateSpuExists(updateReqVO.getId()); + // 校验分类、品牌 + validateCategory(updateReqVO.getCategoryId()); + brandService.validateProductBrand(updateReqVO.getBrandId()); + // 校验SKU + List skuSaveReqList = updateReqVO.getSkus(); + productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType()); + + // 更新 SPU + ProductSpuDO updateObj = BeanUtils.toBean(updateReqVO, ProductSpuDO.class).setStatus(spu.getStatus()); + initSpuFromSkus(updateObj, skuSaveReqList); + productSpuMapper.updateById(updateObj); + // 批量更新 SKU + productSkuService.updateSkuList(updateObj.getId(), updateReqVO.getSkus()); + } + + /** + * 基于 SKU 的信息,初始化 SPU 的信息 + * 主要是计数相关的字段,例如说市场价、最大最小价、库存等等 + * + * @param spu 商品 SPU + * @param skus 商品 SKU 数组 + */ + private void initSpuFromSkus(ProductSpuDO spu, List skus) { + // sku 单价最低的商品的价格 + spu.setPrice(getMinValue(skus, ProductSkuSaveReqVO::getPrice)); + // sku 单价最低的商品的市场价格 + spu.setMarketPrice(getMinValue(skus, ProductSkuSaveReqVO::getMarketPrice)); + // sku 单价最低的商品的成本价格 + spu.setCostPrice(getMinValue(skus, ProductSkuSaveReqVO::getCostPrice)); + // skus 库存总数 + spu.setStock(getSumValue(skus, ProductSkuSaveReqVO::getStock, Integer::sum)); + // 若是 spu 已有状态则不处理 + if (spu.getStatus() == null) { + spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); // 默认状态为上架 + spu.setSalesCount(0); // 默认商品销量 + spu.setBrowseCount(0); // 默认商品浏览量 + } + } + + /** + * 校验商品分类是否合法 + * + * @param id 商品分类编号 + */ + private void validateCategory(Long id) { + categoryService.validateCategory(id); + // 校验层级 + if (categoryService.getCategoryLevel(id) < CATEGORY_LEVEL) { + throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR); + } + } + + @Override + public List validateSpuList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + // 获得商品信息 + List list = productSpuMapper.selectBatchIds(ids); + Map spuMap = CollectionUtils.convertMap(list, ProductSpuDO::getId); + // 校验 + ids.forEach(id -> { + ProductSpuDO spu = spuMap.get(id); + if (spu == null) { + throw exception(SPU_NOT_EXISTS); + } + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { + throw exception(SPU_NOT_ENABLE, spu.getName()); + } + }); + return list; + } + + @Override + public void updateBrowseCount(Long id, int incrCount) { + productSpuMapper.updateBrowseCount(id , incrCount); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSpu(Long id) { + // 校验存在 + validateSpuExists(id); + // 校验商品状态不是回收站不能删除 + ProductSpuDO spuDO = productSpuMapper.selectById(id); + // 判断 SPU 状态是否为回收站 + if (ObjectUtil.notEqual(spuDO.getStatus(), ProductSpuStatusEnum.RECYCLE.getStatus())) { + throw exception(SPU_NOT_RECYCLE); + } + // TODO 芋艿:【可选】参与活动中的商品,不允许删除??? + + // 删除 SPU + productSpuMapper.deleteById(id); + // 删除关联的 SKU + productSkuService.deleteSkuBySpuId(id); + } + + private ProductSpuDO validateSpuExists(Long id) { + ProductSpuDO spuDO = productSpuMapper.selectById(id); + if (spuDO == null) { + throw exception(SPU_NOT_EXISTS); + } + return spuDO; + } + + @Override + public ProductSpuDO getSpu(Long id) { + return productSpuMapper.selectById(id); + } + + @Override + public ProductSpuDO getSpu(Long id, boolean includeDeleted) { + if (includeDeleted) { + return productSpuMapper.selectByIdIncludeDeleted(id); + } + return getSpu(id); + } + + @Override + public List getSpuList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + Map spuMap = convertMap(productSpuMapper.selectBatchIds(ids), ProductSpuDO::getId); + // 需要按照 ids 顺序返回。例如说:店铺装修选择了 [3, 1, 2] 三个商品,返回结果还是 [3, 1, 2] 这样的顺序 + return convertList(ids, spuMap::get); + } + + @Override + public List getSpuListByStatus(Integer status) { + return productSpuMapper.selectList(ProductSpuDO::getStatus, status); + } + + @Override + public PageResult getSpuPage(ProductSpuPageReqVO pageReqVO) { + return productSpuMapper.selectPage(pageReqVO); + } + + @Override + public PageResult getSpuPage(AppProductSpuPageReqVO pageReqVO) { + // 查找时,如果查找某个分类编号,则包含它的子分类。因为顶级分类不包含商品 + Set categoryIds = new HashSet<>(); + if (pageReqVO.getCategoryId() != null && pageReqVO.getCategoryId() > 0) { + categoryIds.add(pageReqVO.getCategoryId()); + List categoryChildren = categoryService.getCategoryList(new ProductCategoryListReqVO() + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentId(pageReqVO.getCategoryId())); + categoryIds.addAll(convertList(categoryChildren, ProductCategoryDO::getId)); + } + if (CollUtil.isNotEmpty(pageReqVO.getCategoryIds())) { + categoryIds.addAll(pageReqVO.getCategoryIds()); + List categoryChildren = categoryService.getCategoryList(new ProductCategoryListReqVO() + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentIds(pageReqVO.getCategoryIds())); + categoryIds.addAll(convertList(categoryChildren, ProductCategoryDO::getId)); + } + // 分页查询 + return productSpuMapper.selectPage(pageReqVO, categoryIds); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSpuStock(Map stockIncrCounts) { + stockIncrCounts.forEach((id, incCount) -> productSpuMapper.updateStock(id, incCount)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSpuStatus(ProductSpuUpdateStatusReqVO updateReqVO) { + // 校验存在 + validateSpuExists(updateReqVO.getId()); + // TODO 芋艿:【可选】参与活动中的商品,不允许下架??? + + // 更新状态 + ProductSpuDO productSpuDO = productSpuMapper.selectById(updateReqVO.getId()).setStatus(updateReqVO.getStatus()); + productSpuMapper.updateById(productSpuDO); + } + + @Override + public Map getTabsCount() { + Map counts = Maps.newLinkedHashMapWithExpectedSize(5); + // 查询销售中的商品数量 + counts.put(ProductSpuPageReqVO.FOR_SALE, + productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus())); + // 查询仓库中的商品数量 + counts.put(ProductSpuPageReqVO.IN_WAREHOUSE, + productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus())); + // 查询售空的商品数量 + counts.put(ProductSpuPageReqVO.SOLD_OUT, + productSpuMapper.selectCount(ProductSpuDO::getStock, 0)); + // 查询触发警戒库存的商品数量 + counts.put(ProductSpuPageReqVO.ALERT_STOCK, + productSpuMapper.selectCount()); + // 查询回收站中的商品数量 + counts.put(ProductSpuPageReqVO.RECYCLE_BIN, + productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus())); + return counts; + } + + @Override + public Long getSpuCountByCategoryId(Long categoryId) { + return productSpuMapper.selectCount(ProductSpuDO::getCategoryId, categoryId); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java new file mode 100644 index 0000000..2da8613 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.product.service.brand; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; +import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import jakarta.annotation.Resource; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** +* {@link ProductBrandServiceImpl} 的单元测试类 +* +* @author 芋道源码 +*/ +@Disabled // TODO 芋艿:后续 fix 补充的单测 +@Import(ProductBrandServiceImpl.class) +public class ProductBrandServiceImplTest extends BaseDbUnitTest { + + @Resource + private ProductBrandServiceImpl brandService; + + @Resource + private ProductBrandMapper brandMapper; + + @Test + public void testCreateBrand_success() { + // 准备参数 + ProductBrandCreateReqVO reqVO = randomPojo(ProductBrandCreateReqVO.class); + + // 调用 + Long brandId = brandService.createBrand(reqVO); + // 断言 + assertNotNull(brandId); + // 校验记录的属性是否正确 + ProductBrandDO brand = brandMapper.selectById(brandId); + assertPojoEquals(reqVO, brand); + } + + @Test + public void testUpdateBrand_success() { + // mock 数据 + ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class); + brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class, o -> { + o.setId(dbBrand.getId()); // 设置更新的 ID + }); + + // 调用 + brandService.updateBrand(reqVO); + // 校验是否更新正确 + ProductBrandDO brand = brandMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, brand); + } + + @Test + public void testUpdateBrand_notExists() { + // 准备参数 + ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> brandService.updateBrand(reqVO), BRAND_NOT_EXISTS); + } + + @Test + public void testDeleteBrand_success() { + // mock 数据 + ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class); + brandMapper.insert(dbBrand);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbBrand.getId(); + + // 调用 + brandService.deleteBrand(id); + // 校验数据不存在了 + assertNull(brandMapper.selectById(id)); + } + + @Test + public void testDeleteBrand_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> brandService.deleteBrand(id), BRAND_NOT_EXISTS); + } + + @Test + public void testGetBrandPage() { + // mock 数据 + ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class, o -> { // 等会查询到 + o.setName("芋道源码"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setCreateTime(buildTime(2022, 2, 1)); + }); + brandMapper.insert(dbBrand); + // 测试 name 不匹配 + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setName("源码"))); + // 测试 status 不匹配 + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 createTime 不匹配 + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(buildTime(2022, 3, 1)))); + // 准备参数 + ProductBrandPageReqVO reqVO = new ProductBrandPageReqVO(); + reqVO.setName("芋道"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 2, 25)})); + + // 调用 + PageResult pageResult = brandService.getBrandPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbBrand, pageResult.getList().get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java new file mode 100644 index 0000000..6478576 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java @@ -0,0 +1,163 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategorySaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; +import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * {@link ProductCategoryServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Disabled // TODO 芋艿:后续 fix 补充的单测 +@Import(ProductCategoryServiceImpl.class) +public class ProductCategoryServiceImplTest extends BaseDbUnitTest { + + @Resource + private ProductCategoryServiceImpl productCategoryService; + + @Resource + private ProductCategoryMapper productCategoryMapper; + + @Test + public void testCreateCategory_success() { + // 准备参数 + //ProductCategoryCreateReqVO reqVO = randomPojo(ProductCategoryCreateReqVO.class); + + // mock 父类 + //ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> { + // reqVO.setParentId(o.getId()); + // o.setParentId(PARENT_ID_NULL); + //}); + //productCategoryMapper.insert(parentProductCategory); + // + //// 调用 + //Long categoryId = productCategoryService.createCategory(reqVO); + //// 断言 + //assertNotNull(categoryId); + //// 校验记录的属性是否正确 + //ProductCategoryDO category = productCategoryMapper.selectById(categoryId); + //assertPojoEquals(reqVO, category); + } + + @Test + public void testUpdateCategory_success() { + // mock 数据 + ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class); + productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ProductCategorySaveReqVO reqVO = randomPojo(ProductCategorySaveReqVO.class, o -> { + o.setId(dbCategory.getId()); // 设置更新的 ID + }); + // mock 父类 + ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> o.setId(reqVO.getParentId())); + productCategoryMapper.insert(parentProductCategory); + + // 调用 + productCategoryService.updateCategory(reqVO); + // 校验是否更新正确 + ProductCategoryDO category = productCategoryMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, category); + } + + @Test + public void testUpdateCategory_notExists() { + // 准备参数 + ProductCategorySaveReqVO reqVO = randomPojo(ProductCategorySaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> productCategoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS); + } + + @Test + public void testDeleteCategory_success() { + // mock 数据 + ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class); + productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCategory.getId(); + + // 调用 + productCategoryService.deleteCategory(id); + // 校验数据不存在了 + assertNull(productCategoryMapper.selectById(id)); + } + + @Test + public void testDeleteCategory_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); + } + + @Test + public void testGetCategoryLevel() { + // mock 数据 + ProductCategoryDO category1 = randomPojo(ProductCategoryDO.class, + o -> o.setParentId(PARENT_ID_NULL)); + productCategoryMapper.insert(category1); + ProductCategoryDO category2 = randomPojo(ProductCategoryDO.class, + o -> o.setParentId(category1.getId())); + productCategoryMapper.insert(category2); + ProductCategoryDO category3 = randomPojo(ProductCategoryDO.class, + o -> o.setParentId(category2.getId())); + productCategoryMapper.insert(category3); + + // 调用,并断言 + assertEquals(productCategoryService.getCategoryLevel(category1.getId()), 1); + assertEquals(productCategoryService.getCategoryLevel(category2.getId()), 2); + assertEquals(productCategoryService.getCategoryLevel(category3.getId()), 3); + } + + @Test + public void testGetCategoryList() { + // mock 数据 + ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class, o -> { // 等会查询到 + o.setName("奥特曼"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setParentId(PARENT_ID_NULL); + }); + productCategoryMapper.insert(dbCategory); + // 测试 name 不匹配 + productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("奥特块"))); + // 测试 status 不匹配 + productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 parentId 不匹配 + productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setParentId(3333L))); + // 准备参数 + ProductCategoryListReqVO reqVO = new ProductCategoryListReqVO(); + reqVO.setName("特曼"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setParentId(PARENT_ID_NULL); + + // 调用 + List list = productCategoryService.getCategoryList(reqVO); + List all = productCategoryService.getCategoryList(new ProductCategoryListReqVO()); + // 断言 + assertEquals(1, list.size()); + assertEquals(4, all.size()); + assertPojoEquals(dbCategory, list.get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java new file mode 100644 index 0000000..1b92e21 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java @@ -0,0 +1,195 @@ +package cn.iocoder.yudao.module.product.service.comment; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; +import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; +import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Lazy; + +import java.time.LocalDateTime; +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +// TODO 芋艿:单测详细 review 下 +/** + * {@link ProductCommentServiceImpl} 的单元测试类 + * + * @author wangzhs + */ +@Disabled // TODO 芋艿:后续 fix 补充的单测 +@Import(ProductCommentServiceImpl.class) +public class ProductCommentServiceImplTest extends BaseDbUnitTest { + + @Resource + private ProductCommentMapper productCommentMapper; + + @Resource + @Lazy + private ProductCommentServiceImpl productCommentService; + + @MockBean + private ProductSpuService productSpuService; + @MockBean + private ProductSkuService productSkuService; + + public String generateNo() { + return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); + } + + public Long generateId() { + return RandomUtil.randomLong(100000, 999999); + } + + @Test + public void testCreateCommentAndGet_success() { + // mock 测试 + ProductCommentDO productComment = randomPojo(ProductCommentDO.class); + productCommentMapper.insert(productComment); + + // 断言 + // 校验记录的属性是否正确 + ProductCommentDO comment = productCommentMapper.selectById(productComment.getId()); + assertPojoEquals(productComment, comment); + } + + @Test + public void testGetCommentPage_success() { + // 准备参数 + ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> { + o.setUserNickname("王二狗"); + o.setSpuName("感冒药"); + o.setScores(ProductCommentScoresEnum.FOUR.getScores()); + o.setReplyStatus(Boolean.TRUE); + o.setVisible(Boolean.TRUE); + o.setId(generateId()); + o.setUserId(generateId()); + o.setAnonymous(Boolean.TRUE); + o.setOrderId(generateId()); + o.setOrderItemId(generateId()); + o.setSpuId(generateId()); + o.setSkuId(generateId()); + o.setDescriptionScores(ProductCommentScoresEnum.FOUR.getScores()); + o.setBenefitScores(ProductCommentScoresEnum.FOUR.getScores()); + o.setContent("真好吃"); + o.setReplyUserId(generateId()); + o.setReplyContent("确实"); + o.setReplyTime(LocalDateTime.now()); + o.setCreateTime(LocalDateTime.now()); + o.setUpdateTime(LocalDateTime.now()); + }); + productCommentMapper.insert(productComment); + + Long orderId = productComment.getOrderId(); + Long spuId = productComment.getSpuId(); + + // 测试 userNickname 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setUserNickname("王三").setScores(ProductCommentScoresEnum.ONE.getScores()))); + // 测试 orderId 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setOrderId(generateId()))); + // 测试 spuId 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuId(generateId()))); + // 测试 spuName 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuName("感康"))); + // 测试 scores 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setScores(ProductCommentScoresEnum.ONE.getScores()))); + // 测试 replied 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setReplyStatus(Boolean.FALSE))); + // 测试 visible 不匹配 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setVisible(Boolean.FALSE))); + + // 调用 + ProductCommentPageReqVO productCommentPageReqVO = new ProductCommentPageReqVO(); + productCommentPageReqVO.setUserNickname("王二"); + productCommentPageReqVO.setOrderId(orderId); + productCommentPageReqVO.setSpuId(spuId); + productCommentPageReqVO.setSpuName("感冒药"); + productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores()); + productCommentPageReqVO.setReplyStatus(Boolean.TRUE); + + PageResult commentPage = productCommentService.getCommentPage(productCommentPageReqVO); + PageResult result = BeanUtils.toBean(productCommentMapper.selectPage(productCommentPageReqVO), + ProductCommentRespVO.class); + assertEquals(result.getTotal(), commentPage.getTotal()); + + PageResult all = productCommentService.getCommentPage(new ProductCommentPageReqVO()); + assertEquals(8, all.getTotal()); + + // 测试获取所有商品分页评论数据 + PageResult result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE); + assertEquals(7, result1.getTotal()); + + // 测试获取所有商品分页中评数据 + PageResult result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); + assertEquals(2, result2.getTotal()); + + // 测试获取指定 spuId 商品分页中评数据 + PageResult result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); + assertEquals(2, result3.getTotal()); + + // 测试分页 tab count + //AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentStatistics(spuId, Boolean.TRUE); + //assertEquals(4, tabsCount.getGoodCount()); + //assertEquals(2, tabsCount.getMediocreCount()); + //assertEquals(0, tabsCount.getNegativeCount()); + + } + + @Test + public void testUpdateCommentVisible_success() { + // mock 测试 + ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> { + o.setVisible(Boolean.TRUE); + }); + productCommentMapper.insert(productComment); + + Long productCommentId = productComment.getId(); + + ProductCommentUpdateVisibleReqVO updateReqVO = new ProductCommentUpdateVisibleReqVO(); + updateReqVO.setId(productCommentId); + updateReqVO.setVisible(Boolean.FALSE); + productCommentService.updateCommentVisible(updateReqVO); + + ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId); + assertFalse(productCommentDO.getVisible()); + } + + + @Test + public void testCommentReply_success() { + // mock 测试 + ProductCommentDO productComment = randomPojo(ProductCommentDO.class); + productCommentMapper.insert(productComment); + + Long productCommentId = productComment.getId(); + + ProductCommentReplyReqVO replyVO = new ProductCommentReplyReqVO(); + replyVO.setId(productCommentId); + replyVO.setReplyContent("测试"); + productCommentService.replyComment(replyVO, 1L); + + ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId); + assertEquals("测试", productCommentDO.getReplyContent()); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java new file mode 100644 index 0000000..5bd79a2 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java @@ -0,0 +1,207 @@ +package cn.iocoder.yudao.module.product.service.sku; + +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.framework.test.core.util.AssertUtils; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import jakarta.annotation.Resource; +import java.util.Arrays; +import java.util.List; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; + +/** + * {@link ProductSkuServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Disabled // TODO 芋艿:后续 fix 补充的单测 +@Import(ProductSkuServiceImpl.class) +public class ProductSkuServiceTest extends BaseDbUnitTest { + + @Resource + private ProductSkuService productSkuService; + + @Resource + private ProductSkuMapper productSkuMapper; + + @MockBean + private ProductSpuService productSpuService; + @MockBean + private ProductPropertyService productPropertyService; + @MockBean + private ProductPropertyValueService productPropertyValueService; + + public Long generateId() { + return RandomUtil.randomLong(100000, 999999); + } + + @Test + public void testUpdateSkuList() { + // mock 数据 + ProductSkuDO sku01 = randomPojo(ProductSkuDO.class, o -> { // 测试更新 + o.setSpuId(1L); + o.setProperties(singletonList(new ProductSkuDO.Property( + 10L, "颜色", 20L, "红色"))); + }); + productSkuMapper.insert(sku01); + ProductSkuDO sku02 = randomPojo(ProductSkuDO.class, o -> { // 测试删除 + o.setSpuId(1L); + o.setProperties(singletonList(new ProductSkuDO.Property( + 10L, "颜色", 30L, "蓝色"))); + + }); + productSkuMapper.insert(sku02); + // 准备参数 + Long spuId = 1L; + String spuName = "测试商品"; + List skus = Arrays.asList( + randomPojo(ProductSkuSaveReqVO.class, o -> { // 测试更新 + o.setProperties(singletonList(new ProductSkuSaveReqVO.Property( + 10L, "颜色", 20L, "红色"))); + }), + randomPojo(ProductSkuSaveReqVO.class, o -> { // 测试新增 + o.setProperties(singletonList(new ProductSkuSaveReqVO.Property( + 10L, "颜色", 20L, "红色"))); + }) + ); + + // 调用 + productSkuService.updateSkuList(spuId, skus); + // 断言 + List dbSkus = productSkuMapper.selectListBySpuId(spuId); + assertEquals(dbSkus.size(), 2); + // 断言更新的 + assertEquals(dbSkus.get(0).getId(), sku01.getId()); + assertPojoEquals(dbSkus.get(0), skus.get(0), "properties"); + assertEquals(skus.get(0).getProperties().size(), 1); + assertPojoEquals(dbSkus.get(0).getProperties().get(0), skus.get(0).getProperties().get(0)); + // 断言新增的 + assertNotEquals(dbSkus.get(1).getId(), sku02.getId()); + assertPojoEquals(dbSkus.get(1), skus.get(1), "properties"); + assertEquals(skus.get(1).getProperties().size(), 1); + assertPojoEquals(dbSkus.get(1).getProperties().get(0), skus.get(1).getProperties().get(0)); + } + + @Test + public void testUpdateSkuStock_incrSuccess() { + // 准备参数 + ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() + .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(10))); + // mock 数据 + productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> { + o.setId(1L).setSpuId(10L).setStock(20); + o.getProperties().forEach(p -> { + // 指定 id 范围 解决 Value too long + p.setPropertyId(generateId()); + p.setValueId(generateId()); + }); + })); + + // 调用 + productSkuService.updateSkuStock(updateStockReqDTO); + // 断言 + ProductSkuDO sku = productSkuMapper.selectById(1L); + assertEquals(sku.getStock(), 30); + verify(productSpuService).updateSpuStock(argThat(spuStockIncrCounts -> { + assertEquals(spuStockIncrCounts.size(), 1); + assertEquals(spuStockIncrCounts.get(10L), 10); + return true; + })); + } + + @Test + public void testUpdateSkuStock_decrSuccess() { + // 准备参数 + ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() + .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-10))); + // mock 数据 + productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> { + o.setId(1L).setSpuId(10L).setStock(20); + o.getProperties().forEach(p -> { + // 指定 id 范围 解决 Value too long + p.setPropertyId(generateId()); + p.setValueId(generateId()); + }); + })); + + // 调用 + productSkuService.updateSkuStock(updateStockReqDTO); + // 断言 + ProductSkuDO sku = productSkuMapper.selectById(1L); + assertEquals(sku.getStock(), 10); + verify(productSpuService).updateSpuStock(argThat(spuStockIncrCounts -> { + assertEquals(spuStockIncrCounts.size(), 1); + assertEquals(spuStockIncrCounts.get(10L), -10); + return true; + })); + } + + @Test + public void testUpdateSkuStock_decrFail() { + // 准备参数 + ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() + .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-30))); + // mock 数据 + productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> { + o.setId(1L).setSpuId(10L).setStock(20); + o.getProperties().forEach(p -> { + // 指定 id 范围 解决 Value too long + p.setPropertyId(generateId()); + p.setValueId(generateId()); + }); + })); + // 调用并断言 + AssertUtils.assertServiceException(() -> productSkuService.updateSkuStock(updateStockReqDTO), + SKU_STOCK_NOT_ENOUGH); + } + + @Test + public void testDeleteSku_success() { + ProductSkuDO dbSku = randomPojo(ProductSkuDO.class, o -> { + o.setId(generateId()).setSpuId(generateId()); + o.getProperties().forEach(p -> { + // 指定 id 范围 解决 Value too long + p.setPropertyId(generateId()); + p.setValueId(generateId()); + }); + }); + // mock 数据 + productSkuMapper.insert(dbSku); + // 准备参数 + Long id = dbSku.getId(); + + // 调用 + productSkuService.deleteSku(id); + // 校验数据不存在了 + assertNull(productSkuMapper.selectById(id)); + } + + @Test + public void testDeleteSku_notExists() { + // 准备参数 + Long id = 1L; + + // 调用, 并断言异常 + assertServiceException(() -> productSkuService.deleteSku(id), SKU_NOT_EXISTS); + } +} diff --git a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java new file mode 100755 index 0000000..0273465 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -0,0 +1,470 @@ +package cn.iocoder.yudao.module.product.service.spu; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.product.service.brand.ProductBrandServiceImpl; +import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceImpl; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.assertj.core.util.Lists.newArrayList; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +// TODO @芋艿:review 下单元测试 + +/** + * {@link ProductSpuServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Disabled // TODO 芋艿:后续 fix 补充的单测 +@Import(ProductSpuServiceImpl.class) +public class ProductSpuServiceImplTest extends BaseDbUnitTest { + + @Resource + private ProductSpuServiceImpl productSpuService; + + @Resource + private ProductSpuMapper productSpuMapper; + + @MockBean + private ProductSkuServiceImpl productSkuService; + @MockBean + private ProductCategoryServiceImpl categoryService; + @MockBean + private ProductBrandServiceImpl brandService; + @MockBean + private ProductPropertyService productPropertyService; + @MockBean + private ProductPropertyValueService productPropertyValueService; + + public String generateNo() { + return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); + } + + public Long generateId() { + return RandomUtil.randomLong(100000, 999999); + } + + public int generaInt(){return RandomUtil.randomInt(1,9999999);} + + // TODO @芋艿:单测后续 review 哈 + + @Test + public void testCreateSpu_success() { + // 准备参数 + ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{ + // 限制范围为正整数 + o.setCostPrice(generaInt()); + o.setPrice(generaInt()); + o.setMarketPrice(generaInt()); + o.setStock(generaInt()); + o.setFirstBrokeragePrice(generaInt()); + o.setSecondBrokeragePrice(generaInt()); + // 限制分数为两位数 + o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); + o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); + }); + ProductSpuSaveReqVO createReqVO = randomPojo(ProductSpuSaveReqVO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO)); + }); + when(categoryService.getCategoryLevel(eq(createReqVO.getCategoryId()))).thenReturn(2); + Long spu = productSpuService.createSpu(createReqVO); + ProductSpuDO productSpuDO = productSpuMapper.selectById(spu); + assertPojoEquals(createReqVO, productSpuDO); + } + + @Test + public void testUpdateSpu_success() { + // 准备参数 + ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + }); + productSpuMapper.insert(createReqVO); + // 准备参数 + ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{ + // 限制范围为正整数 + o.setCostPrice(generaInt()); + o.setPrice(generaInt()); + o.setMarketPrice(generaInt()); + o.setStock(generaInt()); + o.setFirstBrokeragePrice(generaInt()); + o.setSecondBrokeragePrice(generaInt()); + // 限制分数为两位数 + o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); + o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); + }); + // 准备参数 + ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class, o -> { + o.setId(createReqVO.getId()); // 设置更新的 ID + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO)); + }); + when(categoryService.getCategoryLevel(eq(reqVO.getCategoryId()))).thenReturn(2); + // 调用 + productSpuService.updateSpu(reqVO); + // 校验是否更新正确 + ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, spu); + } + + @Test + public void testValidateSpuExists_exception() { + ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class); + // 调用 + Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO)); + } + + @Test + void deleteSpu() { + // 准备参数 + ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + o.setStatus(-1); // 加入回收站才可删除 + }); + productSpuMapper.insert(createReqVO); + + // 调用 + productSpuService.deleteSpu(createReqVO.getId()); + + Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId())); + } + + @Test + void getSpu() { + // 准备参数 + ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + }); + productSpuMapper.insert(createReqVO); + + ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId()); + assertPojoEquals(createReqVO, spu); + } + + @Test + void getSpuList() { + // 准备参数 + ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + }), randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + })); + productSpuMapper.insertBatch(createReqVOs); + + // 调用 + List spuList = productSpuService.getSpuList(createReqVOs.stream().map(ProductSpuDO::getId).collect(Collectors.toList())); + Assertions.assertIterableEquals(createReqVOs, spuList); + } + + @Test + void getSpuPage_alarmStock_empty() { + // 准备参数 + ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(11); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + }), randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(11); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + })); + productSpuMapper.insertBatch(createReqVOs); + // 调用 + ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); + productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK); + + PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); + + PageResult result = PageResult.empty(); + Assertions.assertIterableEquals(result.getList(), spuPage.getList()); + assertEquals(spuPage.getTotal(), result.getTotal()); + } + + @Test + void getSpuPage_alarmStock() { + // 准备参数 + ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(5); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + }), randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(9); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + })); + productSpuMapper.insertBatch(createReqVOs); + // 调用 + ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); + productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK); + PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); + assertEquals(createReqVOs.size(), spuPage.getTotal()); + } + + @Test + void testGetSpuPage() { + // 准备参数 + ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + }); + + // 准备参数 + productSpuMapper.insert(createReqVO); + // 测试 status 不匹配 + productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus()))); + productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setStatus(ProductSpuStatusEnum.RECYCLE.getStatus()))); + // 测试 SpecType 不匹配 + productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setSpecType(true))); + // 测试 BrandId 不匹配 + productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setBrandId(generateId()))); + // 测试 CategoryId 不匹配 + productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setCategoryId(generateId()))); + + // 调用 + ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); + // 查询条件 按需打开 + //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK); + //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.RECYCLE_BIN); + //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.FOR_SALE); + //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.IN_WAREHOUSE); + //productSpuPageReqVO.setTabType(ProductSpuPageReqVO.SOLD_OUT); + //productSpuPageReqVO.setName(createReqVO.getName()); + //productSpuPageReqVO.setCategoryId(createReqVO.getCategoryId()); + + PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); + + assertEquals(1, spuPage.getTotal()); + } + + /** + * 生成笛卡尔积 + * + * @param data 数据 + * @return 笛卡尔积 + */ + public static List> cartesianProduct(List> data) { + List> res = null; // 结果集(当前为第N个List,则该处存放的就为前N-1个List的笛卡尔积集合) + for (List list : data) { // 遍历数据 + List> temp = new ArrayList<>(); // 临时结果集,存放本次循环后生成的笛卡尔积集合 + if (res == null) { // 结果集为null表示第一次循环既list为第一个List + for (T t : list) { // 便利第一个List + // 利用stream生成List,第一个List的笛卡尔积集合约等于自己本身(需要创建一个List并把对象添加到当中),存放到临时结果集 + temp.add(Stream.of(t).collect(Collectors.toList())); + } + res = temp; // 将临时结果集赋值给结果集 + continue; // 跳过本次循环 + } + // 不为第一个List,计算前面的集合(笛卡尔积)和当前List的笛卡尔积集合 + for (T t : list) { // 便利 + for (List rl : res) { // 便利前面的笛卡尔积集合 + // 利用stream生成List + temp.add(Stream.concat(rl.stream(), Stream.of(t)).collect(Collectors.toList())); + } + } + res = temp; // 将临时结果集赋值给结果集 + } + // 返回结果 + return res; + } + + @Test + public void testUpdateSpuStock() { + // 准备参数 + Map stockIncrCounts = MapUtil.builder(1L, 10).put(2L, -20).build(); + // mock 方法(数据) + productSpuMapper.insert(randomPojo(ProductSpuDO.class, o ->{ + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + o.setId(1L).setStock(20); + })); + productSpuMapper.insert(randomPojo(ProductSpuDO.class, o -> { + o.setCategoryId(generateId()); + o.setBrandId(generateId()); + o.setDeliveryTemplateId(generateId()); + o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setVirtualSalesCount(generaInt()); // 限制范围为正整数 + o.setPrice(generaInt()); // 限制范围为正整数 + o.setMarketPrice(generaInt()); // 限制范围为正整数 + o.setCostPrice(generaInt()); // 限制范围为正整数 + o.setStock(generaInt()); // 限制范围为正整数 + o.setGiveIntegral(generaInt()); // 限制范围为正整数 + o.setSalesCount(generaInt()); // 限制范围为正整数 + o.setBrowseCount(generaInt()); // 限制范围为正整数 + o.setId(2L).setStock(30); + })); + + // 调用 + productSpuService.updateSpuStock(stockIncrCounts); + // 断言 + assertEquals(productSpuService.getSpu(1L).getStock(), 30); + assertEquals(productSpuService.getSpu(2L).getStock(), 10); + } + +} diff --git a/yudao-module-mall/yudao-module-product/src/test/resources/application-unit-test.yaml b/yudao-module-mall/yudao-module-product/src/test/resources/application-unit-test.yaml new file mode 100644 index 0000000..36aec5c --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/resources/application-unit-test.yaml @@ -0,0 +1,49 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + sql: + init: + schema-locations: classpath:/sql/create_tables.sql + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + data: + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis-plus: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao diff --git a/yudao-module-mall/yudao-module-product/src/test/resources/logback.xml b/yudao-module-mall/yudao-module-product/src/test/resources/logback.xml new file mode 100644 index 0000000..daf756b --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-mall/yudao-module-product/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-product/src/test/resources/sql/clean.sql new file mode 100644 index 0000000..e9616cd --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/resources/sql/clean.sql @@ -0,0 +1,7 @@ +DELETE FROM "product_sku"; +DELETE FROM "product_spu"; +DELETE FROM "product_category"; +DELETE FROM "product_brand"; +DELETE FROM "product_property"; +DELETE FROM "product_property_value"; +DELETE FROM "product_comment"; diff --git a/yudao-module-mall/yudao-module-product/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-product/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000..f0f0c70 --- /dev/null +++ b/yudao-module-mall/yudao-module-product/src/test/resources/sql/create_tables.sql @@ -0,0 +1,157 @@ +CREATE TABLE IF NOT EXISTS `product_sku` ( + `id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `spu_id` bigint NOT NULL COMMENT 'spu编号', + `properties` varchar(512) DEFAULT NULL COMMENT '属性数组,JSON 格式', + `price` int NOT NULL DEFAULT '-1' COMMENT '商品价格,单位:分', + `market_price` int DEFAULT NULL COMMENT '市场价,单位:分', + `cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分', + `bar_code` varchar(64) DEFAULT NULL COMMENT 'SKU 的条形码', + `pic_url` varchar(256) NOT NULL COMMENT '图片地址', + `stock` int DEFAULT NULL COMMENT '库存', + `weight` double DEFAULT NULL COMMENT '商品重量,单位:kg 千克', + `volume` double DEFAULT NULL COMMENT '商品体积,单位:m^3 平米', + `sub_commission_first_price` int DEFAULT NULL COMMENT '一级分销的佣金,单位:分', + `sub_commission_second_price` int DEFAULT NULL COMMENT '二级分销的佣金,单位:分', + `sales_count` int DEFAULT NULL COMMENT '商品销量', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY("id") +) COMMENT '商品sku'; + +CREATE TABLE IF NOT EXISTS `product_spu` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品 SPU 编号,自增', + `name` varchar(128) NOT NULL COMMENT '商品名称', + `keyword` varchar(256) NOT NULL COMMENT '关键字', + `introduction` varchar(256) NOT NULL COMMENT '商品简介', + `description` text NOT NULL COMMENT '商品详情', + `bar_code` varchar(64) NOT NULL COMMENT '条形码', + `category_id` bigint NOT NULL COMMENT '商品分类编号', + `brand_id` int DEFAULT NULL COMMENT '商品品牌编号', + `pic_url` varchar(256) NOT NULL COMMENT '商品封面图', + `slider_pic_urls` varchar(2000) DEFAULT '' COMMENT '商品轮播图地址\n 数组,以逗号分隔\n 最多上传15张', + `video_url` varchar(256) DEFAULT NULL COMMENT '商品视频', + `unit` tinyint NOT NULL COMMENT '单位', + `sort` int NOT NULL DEFAULT '0' COMMENT '排序字段', + `status` tinyint NOT NULL COMMENT '商品状态: 0 上架(开启) 1 下架(禁用)-1 回收', + `spec_type` bit(1) NOT NULL COMMENT '规格类型:0 单规格 1 多规格', + `price` int NOT NULL DEFAULT '-1' COMMENT '商品价格,单位使用:分', + `market_price` int NOT NULL COMMENT '市场价,单位使用:分', + `cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分', + `stock` int NOT NULL DEFAULT '0' COMMENT '库存', + `delivery_template_id` bigint NOT NULL COMMENT '物流配置模板编号', + `recommend_hot` bit(1) NOT NULL COMMENT '是否热卖推荐: 0 默认 1 热卖', + `recommend_benefit` bit(1) NOT NULL COMMENT '是否优惠推荐: 0 默认 1 优选', + `recommend_best` bit(1) NOT NULL COMMENT '是否精品推荐: 0 默认 1 精品', + `recommend_new` bit(1) NOT NULL COMMENT '是否新品推荐: 0 默认 1 新品', + `recommend_good` bit(1) NOT NULL COMMENT '是否优品推荐', + `give_integral` int NOT NULL COMMENT '赠送积分', + `give_coupon_template_ids` varchar(512) DEFAULT '' COMMENT '赠送的优惠劵编号的数组', + `sub_commission_type` bit(1) NOT NULL COMMENT '分销类型', + `activity_orders` varchar(16) NOT NULL DEFAULT '' COMMENT '活动显示排序0=默认, 1=秒杀,2=砍价,3=拼团', + `sales_count` int DEFAULT '0' COMMENT '商品销量', + `virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量', + `browse_count` int DEFAULT '0' COMMENT '商品点击量', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY("id") +) COMMENT '商品spu'; + +CREATE TABLE IF NOT EXISTS `product_category` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号', + `parent_id` bigint NOT NULL COMMENT '父分类编号', + `name` varchar(255) NOT NULL COMMENT '分类名称', + `pic_url` varchar(255) NOT NULL COMMENT '移动端分类图', + `big_pic_url` varchar(255) DEFAULT NULL COMMENT 'PC 端分类图', + `sort` int DEFAULT '0' COMMENT '分类排序', + `status` tinyint NOT NULL COMMENT '开启状态', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY("id") +) COMMENT '商品分类'; + +CREATE TABLE IF NOT EXISTS `product_brand` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号', + `name` varchar(255) NOT NULL COMMENT '品牌名称', + `pic_url` varchar(255) NOT NULL COMMENT '品牌图片', + `sort` int DEFAULT '0' COMMENT '品牌排序', + `description` varchar(1024) DEFAULT NULL COMMENT '品牌描述', + `status` tinyint NOT NULL COMMENT '状态', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY("id") +) COMMENT '商品品牌'; + +CREATE TABLE IF NOT EXISTS `product_property` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(64) DEFAULT NULL COMMENT '规格名称', + `status` tinyint DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + PRIMARY KEY("id") +) COMMENT '规格名称'; + +CREATE TABLE IF NOT EXISTS `product_property_value` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `property_id` bigint DEFAULT NULL COMMENT '规格键id', + `name` varchar(128) DEFAULT NULL COMMENT '规格值名字', + `status` tinyint DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + PRIMARY KEY("id") +) COMMENT '规格值'; + +DROP TABLE IF EXISTS `product_comment` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论编号,主键自增', + `user_id` bigint DEFAULT NULL COMMENT '评价人的用户编号关联 MemberUserDO 的 id 编号', + `user_nickname` varchar(255) DEFAULT NULL COMMENT '评价人名称', + `user_avatar` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '评价人头像', + `anonymous` bit(1) DEFAULT NULL COMMENT '是否匿名', + `order_id` bigint DEFAULT NULL COMMENT '交易订单编号关联 TradeOrderDO 的 id 编号', + `order_item_id` bigint DEFAULT NULL COMMENT '交易订单项编号关联 TradeOrderItemDO 的 id 编号', + `spu_id` bigint DEFAULT NULL COMMENT '商品 SPU 编号关联 ProductSpuDO 的 id', + `spu_name` varchar(255) DEFAULT NULL COMMENT '商品 SPU 名称', + `sku_id` bigint DEFAULT NULL COMMENT '商品 SKU 编号关联 ProductSkuDO 的 id 编号', + `visible` bit(1) DEFAULT NULL COMMENT '是否可见true:显示false:隐藏', + `scores` tinyint DEFAULT NULL COMMENT '评分星级1-5分', + `description_scores` tinyint DEFAULT NULL COMMENT '描述星级1-5 星', + `benefit_scores` tinyint DEFAULT NULL COMMENT '服务星级1-5 星', + `content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '评论内容', + `pic_urls` varchar(4096) DEFAULT NULL COMMENT '评论图片地址数组', + `reply_status` bit(1) DEFAULT NULL COMMENT '商家是否回复', + `reply_user_id` bigint DEFAULT NULL COMMENT '回复管理员编号关联 AdminUserDO 的 id 编号', + `reply_content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '商家回复内容', + `reply_time` datetime DEFAULT NULL COMMENT '商家回复时间', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '商品评论'; \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/pom.xml b/yudao-module-mall/yudao-module-promotion-biz/pom.xml index 64c55a7..f653b7b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/pom.xml +++ b/yudao-module-mall/yudao-module-promotion-biz/pom.xml @@ -26,7 +26,7 @@ cn.iocoder.boot - yudao-module-product-api + yudao-module-product ${revision} @@ -36,17 +36,17 @@ cn.iocoder.boot - yudao-module-system-api + yudao-module-system ${revision} cn.iocoder.boot - yudao-module-infra-api + yudao-module-infra ${revision} cn.iocoder.boot - yudao-module-member-api + yudao-module-member ${revision} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/CouponTakeByRegisterConsumer.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/CouponTakeByRegisterConsumer.java index 673e7dd..3e6a89e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/CouponTakeByRegisterConsumer.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/CouponTakeByRegisterConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.promotion.mq.consumer.coupon; -import cn.iocoder.yudao.module.member.message.user.MemberUserCreateMessage; +import cn.iocoder.yudao.module.member.api.message.user.MemberUserCreateMessage; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.EventListener; diff --git a/yudao-module-mall/yudao-module-statistics-biz/pom.xml b/yudao-module-mall/yudao-module-statistics-biz/pom.xml index fc15455..a8f1e59 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/pom.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/pom.xml @@ -30,7 +30,7 @@ cn.iocoder.boot - yudao-module-product-api + yudao-module-product ${revision} @@ -40,12 +40,12 @@ cn.iocoder.boot - yudao-module-member-api + yudao-module-member ${revision} cn.iocoder.boot - yudao-module-pay-api + yudao-module-pay ${revision} diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index fb046ee..8c639cc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -25,12 +25,12 @@ cn.iocoder.boot - yudao-module-product-api + yudao-module-product ${revision} cn.iocoder.boot - yudao-module-pay-api + yudao-module-pay ${revision} @@ -40,12 +40,12 @@ cn.iocoder.boot - yudao-module-member-api + yudao-module-member ${revision} cn.iocoder.boot - yudao-module-system-api + yudao-module-system ${revision} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java index a87afb6..d2165cb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java @@ -21,7 +21,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -- libgit2 0.21.4