Commit 96e2bf020f0e30209d57fa0a343d7f811270e820
1 parent
cd86620b
REVIEW 商品收藏的逻辑
Showing
10 changed files
with
43 additions
and
43 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
| @@ -48,7 +48,7 @@ public interface ErrorCodeConstants { | @@ -48,7 +48,7 @@ public interface ErrorCodeConstants { | ||
| 48 | ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作"); | 48 | ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作"); |
| 49 | ErrorCode COMMENT_ADDITIONAL_EXISTS = new ErrorCode(1008007003, "商品追加评价已存在"); | 49 | ErrorCode COMMENT_ADDITIONAL_EXISTS = new ErrorCode(1008007003, "商品追加评价已存在"); |
| 50 | 50 | ||
| 51 | - // ========== 喜爱商品 1008008000 ========== | 51 | + // ========== 商品 收藏 1008008000 ========== |
| 52 | ErrorCode COLLECTION_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏"); | 52 | ErrorCode COLLECTION_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏"); |
| 53 | ErrorCode COLLECTION_NOT_EXISTS = new ErrorCode(1008008001, "商品收藏不存在"); | 53 | ErrorCode COLLECTION_NOT_EXISTS = new ErrorCode(1008008001, "商品收藏不存在"); |
| 54 | 54 |
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/favorite/ProductFavoriteTypeEnum.java
| @@ -7,17 +7,19 @@ import lombok.Getter; | @@ -7,17 +7,19 @@ import lombok.Getter; | ||
| 7 | import java.util.Arrays; | 7 | import java.util.Arrays; |
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | - * 喜爱商品类型 枚举 | 10 | + * 商品收藏的类型枚举 |
| 11 | * | 11 | * |
| 12 | * @author jason | 12 | * @author jason |
| 13 | */ | 13 | */ |
| 14 | @Getter | 14 | @Getter |
| 15 | @AllArgsConstructor | 15 | @AllArgsConstructor |
| 16 | public enum ProductFavoriteTypeEnum implements IntArrayValuable { | 16 | public enum ProductFavoriteTypeEnum implements IntArrayValuable { |
| 17 | + | ||
| 17 | COLLECT(1,"收藏"), | 18 | COLLECT(1,"收藏"), |
| 18 | THUMBS_UP(2, "点赞"); | 19 | THUMBS_UP(2, "点赞"); |
| 19 | 20 | ||
| 20 | public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductFavoriteTypeEnum::getType).toArray(); | 21 | public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductFavoriteTypeEnum::getType).toArray(); |
| 22 | + | ||
| 21 | /** | 23 | /** |
| 22 | * 类型 | 24 | * 类型 |
| 23 | */ | 25 | */ |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java
| @@ -18,10 +18,7 @@ import java.util.Objects; | @@ -18,10 +18,7 @@ import java.util.Objects; | ||
| 18 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 18 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 19 | import static cn.iocoder.yudao.module.product.enums.favorite.ProductFavoriteTypeEnum.COLLECT; | 19 | import static cn.iocoder.yudao.module.product.enums.favorite.ProductFavoriteTypeEnum.COLLECT; |
| 20 | 20 | ||
| 21 | -/** | ||
| 22 | - * @author jason | ||
| 23 | - */ | ||
| 24 | -@Tag(name = "用户 APP - 喜爱商品") | 21 | +@Tag(name = "用户 APP - 商品收藏") |
| 25 | @RestController | 22 | @RestController |
| 26 | @RequestMapping("/product/favorite") | 23 | @RequestMapping("/product/favorite") |
| 27 | public class AppFavoriteController { | 24 | public class AppFavoriteController { |
| @@ -29,6 +26,7 @@ public class AppFavoriteController { | @@ -29,6 +26,7 @@ public class AppFavoriteController { | ||
| 29 | @Resource | 26 | @Resource |
| 30 | private ProductFavoriteService productFavoriteService; | 27 | private ProductFavoriteService productFavoriteService; |
| 31 | 28 | ||
| 29 | + // TODO @jason:创建;create | ||
| 32 | @PostMapping(value = "/collect") | 30 | @PostMapping(value = "/collect") |
| 33 | @Operation(summary = "商品收藏") | 31 | @Operation(summary = "商品收藏") |
| 34 | public CommonResult<Boolean> collect(@RequestBody @Valid AppFavoriteReqVO reqVO) { | 32 | public CommonResult<Boolean> collect(@RequestBody @Valid AppFavoriteReqVO reqVO) { |
| @@ -36,16 +34,22 @@ public class AppFavoriteController { | @@ -36,16 +34,22 @@ public class AppFavoriteController { | ||
| 36 | return success(productFavoriteService.collect(reqVO)); | 34 | return success(productFavoriteService.collect(reqVO)); |
| 37 | } | 35 | } |
| 38 | 36 | ||
| 37 | + // TODO @jason:创建;delete;使用 @DeleteMapping | ||
| 39 | @PostMapping(value = "/cancelCollect") | 38 | @PostMapping(value = "/cancelCollect") |
| 40 | @Operation(summary = "取消商品收藏(通过商品详情)") | 39 | @Operation(summary = "取消商品收藏(通过商品详情)") |
| 41 | public CommonResult<Boolean> cancelCollect(@RequestBody @Valid AppFavoriteReqVO reqVO) { | 40 | public CommonResult<Boolean> cancelCollect(@RequestBody @Valid AppFavoriteReqVO reqVO) { |
| 41 | + // TODO @jason:是不是不用校验呀? | ||
| 42 | Assert.isTrue(Objects.equals(COLLECT.getType(), reqVO.getType()), "参数type 不匹配"); | 42 | Assert.isTrue(Objects.equals(COLLECT.getType(), reqVO.getType()), "参数type 不匹配"); |
| 43 | return success(productFavoriteService.cancelCollect(reqVO)); | 43 | return success(productFavoriteService.cancelCollect(reqVO)); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | + // TODO @jason:page;分页 | ||
| 46 | @GetMapping(value = "/collectList") | 47 | @GetMapping(value = "/collectList") |
| 47 | @Operation(summary = "商品收藏列表") | 48 | @Operation(summary = "商品收藏列表") |
| 48 | public CommonResult<PageResult<AppFavoriteRespVO>> pageCollectList(AppFavoritePageReqVO reqVO) { | 49 | public CommonResult<PageResult<AppFavoriteRespVO>> pageCollectList(AppFavoritePageReqVO reqVO) { |
| 49 | return success(productFavoriteService.pageCollectList(reqVO)); | 50 | return success(productFavoriteService.pageCollectList(reqVO)); |
| 50 | } | 51 | } |
| 52 | + | ||
| 53 | + // TODO @json:需要在给一个,用户查询某个商品是否收藏;详情页要用 | ||
| 54 | + | ||
| 51 | } | 55 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoritePageReqVO.java
| @@ -10,15 +10,13 @@ import javax.validation.constraints.NotNull; | @@ -10,15 +10,13 @@ import javax.validation.constraints.NotNull; | ||
| 10 | 10 | ||
| 11 | import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; | 11 | import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; |
| 12 | 12 | ||
| 13 | -/** | ||
| 14 | - * @author jason | ||
| 15 | - */ | ||
| 16 | -@Schema(description = "用户APP - 喜爱商品分页查询 Request VO") | 13 | +@Schema(description = "用户APP - 商品收藏分页查询 Request VO") |
| 17 | @Data | 14 | @Data |
| 18 | public class AppFavoritePageReqVO extends PageParam { | 15 | public class AppFavoritePageReqVO extends PageParam { |
| 19 | 16 | ||
| 20 | - @Schema(description = "类型 1:收藏 2:点赞", requiredMode = REQUIRED, example = "1") | 17 | + @Schema(description = "类型", requiredMode = REQUIRED, example = "1") |
| 21 | @NotNull(message = "类型不能为空") | 18 | @NotNull(message = "类型不能为空") |
| 22 | @InEnum(ProductFavoriteTypeEnum.class) | 19 | @InEnum(ProductFavoriteTypeEnum.class) |
| 23 | private Integer type; | 20 | private Integer type; |
| 21 | + | ||
| 24 | } | 22 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java
| @@ -9,21 +9,17 @@ import javax.validation.constraints.NotNull; | @@ -9,21 +9,17 @@ import javax.validation.constraints.NotNull; | ||
| 9 | 9 | ||
| 10 | import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; | 10 | import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; |
| 11 | 11 | ||
| 12 | - | ||
| 13 | - | ||
| 14 | -/** | ||
| 15 | - * @author jason | ||
| 16 | - */ | ||
| 17 | -@Schema(description = "用户APP - 喜爱商品创建 Request VO") | 12 | +@Schema(description = "用户 APP - 商品收藏创建 Request VO") |
| 18 | @Data | 13 | @Data |
| 19 | public class AppFavoriteReqVO { | 14 | public class AppFavoriteReqVO { |
| 20 | 15 | ||
| 21 | - @Schema(description = "商品SPU编号", requiredMode = REQUIRED, example = "29502") | ||
| 22 | - @NotNull(message = "商品SPU编号不能为空") | 16 | + @Schema(description = "商品 SPU 编号", requiredMode = REQUIRED, example = "29502") |
| 17 | + @NotNull(message = "商品 SPU 编号不能为空") | ||
| 23 | private Long spuId; | 18 | private Long spuId; |
| 24 | 19 | ||
| 25 | - @Schema(description = "类型 1:收藏 2:点赞", requiredMode = REQUIRED, example = "1") | 20 | + @Schema(description = "类型", requiredMode = REQUIRED, example = "1") |
| 26 | @NotNull(message = "类型不能为空") | 21 | @NotNull(message = "类型不能为空") |
| 27 | @InEnum(ProductFavoriteTypeEnum.class) | 22 | @InEnum(ProductFavoriteTypeEnum.class) |
| 28 | private Integer type; | 23 | private Integer type; |
| 24 | + | ||
| 29 | } | 25 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java
| 1 | package cn.iocoder.yudao.module.product.controller.app.favorite.vo; | 1 | package cn.iocoder.yudao.module.product.controller.app.favorite.vo; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | ||
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | import lombok.Data; | 4 | import lombok.Data; |
| 6 | 5 | ||
| 7 | -/** | ||
| 8 | - * @author jason | ||
| 9 | - */ | ||
| 10 | -@Schema(description = "用户APP - 喜爱商品 Response VO") | 6 | +@Schema(description = "用户APP - 商品收藏 Response VO") |
| 11 | @Data | 7 | @Data |
| 12 | public class AppFavoriteRespVO { | 8 | public class AppFavoriteRespVO { |
| 13 | 9 | ||
| 10 | + // TODO @jason:required true 哈 | ||
| 14 | @Schema(description = "编号", example = "1") | 11 | @Schema(description = "编号", example = "1") |
| 15 | private Long id; | 12 | private Long id; |
| 16 | 13 | ||
| 17 | - @Schema(description = "商品SPU编号", example = "29502") | 14 | + // TODO @jason:required true 哈 |
| 15 | + @Schema(description = "商品 SPU 编号", example = "29502") | ||
| 18 | private Long spuId; | 16 | private Long spuId; |
| 19 | 17 | ||
| 20 | - @Schema(description = "商品SPU名称", example = "赵六") | 18 | + // TODO @jason:required true 哈 |
| 19 | + @Schema(description = "类型", example = "1") | ||
| 20 | + private Integer type; | ||
| 21 | + | ||
| 22 | + // ========== 商品相关字段 ========== | ||
| 23 | + | ||
| 24 | + @Schema(description = "商品 SPU 名称", example = "赵六") | ||
| 21 | private String spuName; | 25 | private String spuName; |
| 22 | 26 | ||
| 23 | @Schema(description = "商品封面图", example = "https://domain/pic.png") | 27 | @Schema(description = "商品封面图", example = "https://domain/pic.png") |
| @@ -26,6 +30,4 @@ public class AppFavoriteRespVO { | @@ -26,6 +30,4 @@ public class AppFavoriteRespVO { | ||
| 26 | @Schema(description = "商品单价", example = "100") | 30 | @Schema(description = "商品单价", example = "100") |
| 27 | private Integer price; | 31 | private Integer price; |
| 28 | 32 | ||
| 29 | - @Schema(description = "类型 1:收藏 2:点赞", example = "1") | ||
| 30 | - private Integer type; | ||
| 31 | } | 33 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/favorite/ProductFavoriteConvert.java
| @@ -5,11 +5,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO | @@ -5,11 +5,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.favorite.ProductFavoriteDO | ||
| 5 | import org.mapstruct.Mapper; | 5 | import org.mapstruct.Mapper; |
| 6 | import org.mapstruct.factory.Mappers; | 6 | import org.mapstruct.factory.Mappers; |
| 7 | 7 | ||
| 8 | -/** | ||
| 9 | - * 喜爱商品 Convert | ||
| 10 | - * | ||
| 11 | - * @author jason | ||
| 12 | - */ | ||
| 13 | @Mapper | 8 | @Mapper |
| 14 | public interface ProductFavoriteConvert { | 9 | public interface ProductFavoriteConvert { |
| 15 | 10 |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/favorite/ProductFavoriteDO.java
| @@ -20,7 +20,7 @@ import lombok.*; | @@ -20,7 +20,7 @@ import lombok.*; | ||
| 20 | @Builder | 20 | @Builder |
| 21 | @NoArgsConstructor | 21 | @NoArgsConstructor |
| 22 | @AllArgsConstructor | 22 | @AllArgsConstructor |
| 23 | -public class ProductFavoriteDO extends TenantBaseDO { | 23 | +public class ProductFavoriteDO extends TenantBaseDO { // TODO @jason:如无必要,使用 BaseDO 哈。例如说 tenant_id 在业务里,是否需要使用到 |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * 编号,主键自增 | 26 | * 编号,主键自增 |
| @@ -40,7 +40,7 @@ public class ProductFavoriteDO extends TenantBaseDO { | @@ -40,7 +40,7 @@ public class ProductFavoriteDO extends TenantBaseDO { | ||
| 40 | */ | 40 | */ |
| 41 | private Long spuId; | 41 | private Long spuId; |
| 42 | /** | 42 | /** |
| 43 | - * 类型 1 收藏;2 点赞 | 43 | + * 类型 1 收藏;2 点赞 // TODO @jason:不要注释 1 收藏 2 点赞;而是注释好,它对应的枚举类 |
| 44 | */ | 44 | */ |
| 45 | private Integer type; | 45 | private Integer type; |
| 46 | 46 |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java
| @@ -12,15 +12,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | @@ -12,15 +12,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||
| 12 | import org.apache.ibatis.annotations.Mapper; | 12 | import org.apache.ibatis.annotations.Mapper; |
| 13 | import org.apache.ibatis.annotations.Param; | 13 | import org.apache.ibatis.annotations.Param; |
| 14 | 14 | ||
| 15 | -/** | ||
| 16 | - * 喜爱商品 Mapper | ||
| 17 | - * | ||
| 18 | - * @author jason | ||
| 19 | - */ | ||
| 20 | @Mapper | 15 | @Mapper |
| 21 | public interface ProductFavoriteMapper extends BaseMapperX<ProductFavoriteDO> { | 16 | public interface ProductFavoriteMapper extends BaseMapperX<ProductFavoriteDO> { |
| 22 | 17 | ||
| 23 | - default ProductFavoriteDO selectByUserAndSpuAndType(Long userId, Long spuId, Integer type){ | 18 | + default ProductFavoriteDO selectByUserAndSpuAndType(Long userId, Long spuId, Integer type) { |
| 24 | Assert.notNull(userId, "the userId argument must not be null"); | 19 | Assert.notNull(userId, "the userId argument must not be null"); |
| 25 | Assert.notNull(spuId, "the spuId argument must not be null"); | 20 | Assert.notNull(spuId, "the spuId argument must not be null"); |
| 26 | Assert.notNull(type, "the type argument must not be null"); | 21 | Assert.notNull(type, "the type argument must not be null"); |
| @@ -36,6 +31,7 @@ public interface ProductFavoriteMapper extends BaseMapperX<ProductFavoriteDO> { | @@ -36,6 +31,7 @@ public interface ProductFavoriteMapper extends BaseMapperX<ProductFavoriteDO> { | ||
| 36 | return new PageResult<>(page.getRecords(), page.getTotal()); | 31 | return new PageResult<>(page.getRecords(), page.getTotal()); |
| 37 | } | 32 | } |
| 38 | 33 | ||
| 34 | + // TODO @jason:内存中拼接哈。这样好兼容更多的 db 类型; | ||
| 39 | Page<AppFavoriteRespVO> selectFavoriteProductList(Page<AppFavoriteRespVO> page, | 35 | Page<AppFavoriteRespVO> selectFavoriteProductList(Page<AppFavoriteRespVO> page, |
| 40 | @Param("userId") Long userId, | 36 | @Param("userId") Long userId, |
| 41 | @Param("type") Integer type); | 37 | @Param("type") Integer type); |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java
| @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.COLLECTIO | @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.COLLECTIO | ||
| 20 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.COLLECTION_NOT_EXISTS; | 20 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.COLLECTION_NOT_EXISTS; |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | - * 喜爱商品 Service 实现类 | 23 | + * 商品收藏 Service 实现类 |
| 24 | * | 24 | * |
| 25 | * @author jason | 25 | * @author jason |
| 26 | */ | 26 | */ |
| @@ -33,11 +33,15 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { | @@ -33,11 +33,15 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { | ||
| 33 | 33 | ||
| 34 | @Override | 34 | @Override |
| 35 | public Boolean collect(@Valid AppFavoriteReqVO reqVO) { | 35 | public Boolean collect(@Valid AppFavoriteReqVO reqVO) { |
| 36 | + // TODO @jason:userId 要从 Controller 传递过来,Service 不能有转台 | ||
| 36 | Long userId = getLoginUserId(); | 37 | Long userId = getLoginUserId(); |
| 38 | + // TODO @jason:代码缩进不对; | ||
| 37 | ProductFavoriteDO favoriteDO = mapper.selectByUserAndSpuAndType(userId, reqVO.getSpuId(), reqVO.getType()); | 39 | ProductFavoriteDO favoriteDO = mapper.selectByUserAndSpuAndType(userId, reqVO.getSpuId(), reqVO.getType()); |
| 38 | if (Objects.nonNull(favoriteDO)) { | 40 | if (Objects.nonNull(favoriteDO)) { |
| 39 | throw exception(COLLECTION_EXISTS); | 41 | throw exception(COLLECTION_EXISTS); |
| 40 | } | 42 | } |
| 43 | + | ||
| 44 | + // TODO @jason:插入只有成功,不用判断 1 | ||
| 41 | ProductFavoriteDO entity = ProductFavoriteConvert.INSTANCE.convert(userId, reqVO); | 45 | ProductFavoriteDO entity = ProductFavoriteConvert.INSTANCE.convert(userId, reqVO); |
| 42 | int count = mapper.insert(entity); | 46 | int count = mapper.insert(entity); |
| 43 | return count == 1; | 47 | return count == 1; |
| @@ -45,11 +49,13 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { | @@ -45,11 +49,13 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { | ||
| 45 | 49 | ||
| 46 | @Override | 50 | @Override |
| 47 | public Boolean cancelCollect(@Valid AppFavoriteReqVO reqVO) { | 51 | public Boolean cancelCollect(@Valid AppFavoriteReqVO reqVO) { |
| 52 | + // TODO @jason:代码缩进不对; | ||
| 48 | Long loginUserId = getLoginUserId(); | 53 | Long loginUserId = getLoginUserId(); |
| 49 | ProductFavoriteDO favoriteDO = mapper.selectByUserAndSpuAndType(loginUserId, reqVO.getSpuId(), reqVO.getType()); | 54 | ProductFavoriteDO favoriteDO = mapper.selectByUserAndSpuAndType(loginUserId, reqVO.getSpuId(), reqVO.getType()); |
| 50 | if (Objects.isNull(favoriteDO)) { | 55 | if (Objects.isNull(favoriteDO)) { |
| 51 | throw exception(COLLECTION_NOT_EXISTS); | 56 | throw exception(COLLECTION_NOT_EXISTS); |
| 52 | } | 57 | } |
| 58 | + // TODO @jason:插入只有成功,不用判断 1 | ||
| 53 | int count = mapper.deleteById(favoriteDO.getId()); | 59 | int count = mapper.deleteById(favoriteDO.getId()); |
| 54 | return count == 1; | 60 | return count == 1; |
| 55 | } | 61 | } |
| @@ -59,4 +65,5 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { | @@ -59,4 +65,5 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { | ||
| 59 | Long userId = getLoginUserId(); | 65 | Long userId = getLoginUserId(); |
| 60 | return mapper.selectPageByUserAndType(userId, reqVO.getType(), reqVO); | 66 | return mapper.selectPageByUserAndType(userId, reqVO.getType(), reqVO); |
| 61 | } | 67 | } |
| 68 | + | ||
| 62 | } | 69 | } |