From f6418632f1b9e1622963dba7042d826c2c5f54d4 Mon Sep 17 00:00:00 2001 From: liujiang <569804566@qq.com> Date: Mon, 31 Mar 2025 00:24:50 +0800 Subject: [PATCH] =?UTF-8?q?master=EF=BC=9A=E6=A1=A3=E5=8F=A3=E9=94=80?= =?UTF-8?q?=E5=94=AE=E5=87=BA=E5=BA=93=E5=8A=9F=E8=83=BD=E8=B0=83=E6=95=B4?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xkt/StoreProductStockController.java | 7 + .../controller/xkt/StoreSaleController.java | 114 +++++++--- .../storeCustomer/StoreCusGeneralSaleVO.java | 2 +- .../vo/storeSale/StoreSalePayStatusVO.java | 25 +++ .../xkt/vo/storeSale/StoreSaleVO.java | 15 +- .../utils/bigDecimal/BigDecimalFunction.java | 15 ++ .../utils/bigDecimal/CollectorsUtil.java | 120 +++++++++++ xkt/pom.xml | 7 + .../com/ruoyi/xkt/domain/StoreSaleDetail.java | 22 +- .../xkt/domain/StoreSaleRefundRecord.java | 2 + .../domain/StoreSaleRefundRecordDetail.java | 120 +++++++++++ .../storeCustomer/StoreCusGeneralSaleDTO.java | 2 +- .../ruoyi/xkt/dto/storeSale/StoreSaleDTO.java | 11 +- .../dto/storeSale/StoreSalePayStatusDTO.java | 24 +++ .../StoreSaleRefundRecordDetailMapper.java | 14 ++ .../ruoyi/xkt/service/IStoreSaleService.java | 10 +- .../service/impl/StoreSaleServiceImpl.java | 196 ++++++++++++++---- 17 files changed, 605 insertions(+), 101 deletions(-) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSalePayStatusVO.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/BigDecimalFunction.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/CollectorsUtil.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecordDetail.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSalePayStatusDTO.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleRefundRecordDetailMapper.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStockController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStockController.java index f9cc673ed..5a73970b3 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStockController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStockController.java @@ -33,6 +33,13 @@ public class StoreProductStockController extends XktBaseController { // TODO 商品销售/出库 时读货号,然后查询当前货号颜色的库存 + // TODO 销售出库时扣件库存 + // TODO 销售出库时扣件库存 + // TODO 销售出库时扣件库存 + // TODO 销售出库时扣件库存 + // TODO 销售出库时扣件库存 + + /** * 查询档口商品库存列表 */ diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java index 8a3cb4b73..5437012de 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java @@ -9,10 +9,12 @@ import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.web.controller.xkt.vo.storeCustomer.StoreCusGeneralSaleVO; import com.ruoyi.web.controller.xkt.vo.storeSale.StoreSalePageVO; +import com.ruoyi.web.controller.xkt.vo.storeSale.StoreSalePayStatusVO; import com.ruoyi.web.controller.xkt.vo.storeSale.StoreSaleVO; import com.ruoyi.xkt.domain.StoreSale; import com.ruoyi.xkt.dto.storeSale.StoreSaleDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageDTO; +import com.ruoyi.xkt.dto.storeSale.StoreSalePayStatusDTO; import com.ruoyi.xkt.service.IStoreSaleService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -43,7 +45,7 @@ public class StoreSaleController extends XktBaseController { */ @PreAuthorize("@ss.hasPermi('system:sale:list')") @ApiOperation(value = "根据当前客户查询最近的销售业绩,以及欠款金额", httpMethod = "GET", response = R.class) - @GetMapping("/sixty-general") + @GetMapping("/cus-overall") public R getCusGeneralSale(@RequestParam("days") Integer days, @RequestParam("storeId") Long storeId, @RequestParam("storeCusId") Long storeCusId) { return success(BeanUtil.toBean(storeSaleService.getCusGeneralSale(days, storeId, storeCusId), StoreCusGeneralSaleVO.class)); @@ -59,7 +61,6 @@ public class StoreSaleController extends XktBaseController { return storeSaleService.page(BeanUtil.toBean(salePageVO, StoreSalePageDTO.class)); } - /** * 新增档口销售出库 */ @@ -68,6 +69,23 @@ public class StoreSaleController extends XktBaseController { @Log(title = "档口销售出库", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody StoreSaleVO storeSaleVO) { + + + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + + + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + return success(storeSaleService.insertStoreSale(BeanUtil.toBean(storeSaleVO, StoreSaleDTO.class))); } @@ -79,25 +97,70 @@ public class StoreSaleController extends XktBaseController { @ApiOperation(value = "修改档口销售出库", httpMethod = "PUT", response = R.class) @PutMapping public R edit(@Validated @RequestBody StoreSaleVO storeSaleVO) { + + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + + + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 return success(storeSaleService.updateStoreSale(BeanUtil.toBean(storeSaleVO, StoreSaleDTO.class))); } + /** + * 查询档口销售出库详情 + */ + @PreAuthorize("@ss.hasPermi('system:sale:query')") + @ApiOperation(value = "查询档口销售出库详情", httpMethod = "GET", response = R.class) + @GetMapping(value = "/{storeSaleId}") + public R getInfo(@PathVariable("storeSaleId") Long storeSaleId) { + return success(storeSaleService.selectStoreSaleByStoreSaleId(storeSaleId)); + } + + /** + * 客户欠款结算 + */ + @PreAuthorize("@ss.hasPermi('system:sale:edit')") + @Log(title = "客户欠款结算", businessType = BusinessType.UPDATE) + @ApiOperation(value = "客户欠款结算", httpMethod = "PUT", response = R.class) + @PutMapping("/clear-debt") + public R clearStoreCusDebt(@Validated @RequestBody StoreSalePayStatusVO payStatusVO) { + storeSaleService.clearStoreCusDebt(BeanUtil.toBean(payStatusVO, StoreSalePayStatusDTO.class)); + return success(); + } + + /** + * 删除档口销售出库 + */ + @PreAuthorize("@ss.hasPermi('system:sale:remove')") + @Log(title = "档口销售出库", businessType = BusinessType.DELETE) + @DeleteMapping("/{storeSaleId}") + public R remove(@PathVariable Long storeSaleId) { + + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 - - - - - - - - - - - - - - + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + return success(storeSaleService.deleteStoreSaleByStoreSaleId(storeSaleId)); + } /** @@ -112,23 +175,8 @@ public class StoreSaleController extends XktBaseController { util.exportExcel(response, list, "档口销售出库数据"); } - /** - * 获取档口销售出库详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:sale:query')") - @GetMapping(value = "/{storeSaleId}") - public R getInfo(@PathVariable("storeSaleId") Long storeSaleId) { - return success(storeSaleService.selectStoreSaleByStoreSaleId(storeSaleId)); - } - /** - * 删除档口销售出库 - */ - @PreAuthorize("@ss.hasPermi('system:sale:remove')") - @Log(title = "档口销售出库", businessType = BusinessType.DELETE) - @DeleteMapping("/{storeSaleIds}") - public R remove(@PathVariable Long[] storeSaleIds) { - return success(storeSaleService.deleteStoreSaleByStoreSaleIds(storeSaleIds)); - } + + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeCustomer/StoreCusGeneralSaleVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeCustomer/StoreCusGeneralSaleVO.java index 2d2c44664..8a16bb2c2 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeCustomer/StoreCusGeneralSaleVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeCustomer/StoreCusGeneralSaleVO.java @@ -22,7 +22,7 @@ public class StoreCusGeneralSaleVO { @ApiModelProperty(name = "档口客户ID") private Long storeCusId; @ApiModelProperty(name = "档口客户名称") - private String cusName; + private String storeCusName; @ApiModelProperty(name = "销售多少双") private Long saleCount; @ApiModelProperty(name = "销售金额") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSalePayStatusVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSalePayStatusVO.java new file mode 100644 index 000000000..13d1e2eea --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSalePayStatusVO.java @@ -0,0 +1,25 @@ +package com.ruoyi.web.controller.xkt.vo.storeSale; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口商品销售客户欠款结算") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreSalePayStatusVO { + + @ApiModelProperty(name = "结算的storeSaleId列表") + @NotNull(message = "结算的storeSaleId列表不能为空!") + private List storeSaleIdList; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleVO.java index 96ab8fb11..7423e3a41 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleVO.java @@ -32,18 +32,17 @@ public class StoreSaleVO { @ApiModelProperty(name = "档口客户ID") @NotNull(message = "档口客户ID不能为空!") private Long storeCusId; + @ApiModelProperty(name = "档口客户名称") + @NotBlank(message = "档口客户名称不能为空!") + private String storeCusName; @ApiModelProperty(name = "销售类型(普通销售 GENERAL_SALE、销售退货 SALE_REFUND、普通销售/销售退货 SALE_AND_REFUND)") @NotBlank(message = "销售类型不能为空!") private String saleType; - @ApiModelProperty(name = "数量") - @NotNull(message = "数量不能为空!") - private Integer quantity; - @ApiModelProperty(name = "总金额") - @NotNull(message = "总金额不能为空!") - private BigDecimal amount; @NotBlank(message = "支付方式不能为空!") @ApiModelProperty(name = "支付方式(支付宝、微信、现金、欠款)ALIPAY WECHAT_PAY CASH DEBT") private String payWay; + @ApiModelProperty(name = "结款状态(已结清、欠款) SETTLED、DEBT") + private String paymentStatus; @NotNull(message = "销售详情列表不能为空!") @Valid @ApiModelProperty(name = "销售详情列表") @@ -58,6 +57,10 @@ public class StoreSaleVO { @NotNull(message = "档口商品颜色尺码ID不能为空!") @ApiModelProperty(name = "档口商品颜色尺码ID") private Long storeProdColorSizeId; + @ApiModelProperty(name = "颜色") + private String colorName; + @ApiModelProperty(name = "尺码") + private Integer size; @ApiModelProperty(name = "商品货号") @NotBlank(message = "商品货号不能为空!") private String prodArtNum; diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/BigDecimalFunction.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/BigDecimalFunction.java new file mode 100644 index 000000000..2b7729af7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/BigDecimalFunction.java @@ -0,0 +1,15 @@ +package com.ruoyi.common.utils.bigDecimal; + +import java.math.BigDecimal; + +/** + * @author liujiang + * @version v1.0 + * @date 2023/11/11 9:08 + */ +@FunctionalInterface +public interface BigDecimalFunction { + + BigDecimal applyAsBigDecimal(T value); + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/CollectorsUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/CollectorsUtil.java new file mode 100644 index 000000000..159796efc --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bigDecimal/CollectorsUtil.java @@ -0,0 +1,120 @@ +package com.ruoyi.common.utils.bigDecimal; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + +/** + * @author liujiang + * @version v1.0 + * @description BigDecimal转Double 会存在精度丢失问题。封装工具类,解决 lamda 表达式没有 BigDecimal相关API问题 + * @date 2023/11/11 9:09 + */ +public class CollectorsUtil { + + static final Set CH_NOID = Collections.emptySet(); + + private CollectorsUtil() { + } + + @SuppressWarnings("unchecked") + private static Function castingIdentity() { + return i -> (R) i; + } + + static class CollectorImpl implements Collector { + private final Supplier supplier; + private final BiConsumer accumulator; + private final BinaryOperator combiner; + private final Function finisher; + private final Set characteristics; + + CollectorImpl(Supplier supplier, BiConsumer accumulator, BinaryOperator combiner, + Function finisher, Set characteristics) { + this.supplier = supplier; + this.accumulator = accumulator; + this.combiner = combiner; + this.finisher = finisher; + this.characteristics = characteristics; + } + + CollectorImpl(Supplier supplier, BiConsumer accumulator, BinaryOperator combiner, + Set characteristics) { + this(supplier, accumulator, combiner, castingIdentity(), characteristics); + } + + @Override + public BiConsumer accumulator() { + return accumulator; + } + + @Override + public Supplier supplier() { + return supplier; + } + + @Override + public BinaryOperator combiner() { + return combiner; + } + + @Override + public Function finisher() { + return finisher; + } + + @Override + public Set characteristics() { + return characteristics; + } + } + + //求和方法 + public static Collector summingBigDecimal(BigDecimalFunction mapper) { + return new CollectorImpl<>( + () -> new BigDecimal[]{BigDecimal.ZERO}, + (a, t) -> { + a[0] = a[0].add(mapper.applyAsBigDecimal(t)); + }, + (a, b) -> { + a[0] = a[0].add(b[0]); + return a; + }, + a -> a[0], CH_NOID); + } + + //求最大值 + public static Collector maxBy(BigDecimalFunction mapper) { + return new CollectorImpl<>( + () -> new BigDecimal[]{new BigDecimal(Long.MIN_VALUE)}, + (a, t) -> { + a[0] = a[0].max(mapper.applyAsBigDecimal(t)); + }, + (a, b) -> { + a[0] = a[0].max(b[0]); + return a; + }, + a -> a[0], CH_NOID); + } + + //求最小值 + public static Collector minBy(BigDecimalFunction mapper) { + return new CollectorImpl<>( + () -> new BigDecimal[]{new BigDecimal(Long.MAX_VALUE)}, + (a, t) -> { + a[0] = a[0].min(mapper.applyAsBigDecimal(t)); + }, + (a, b) -> { + a[0] = a[0].min(b[0]); + return a; + }, + a -> a[0], CH_NOID); + } + +} + diff --git a/xkt/pom.xml b/xkt/pom.xml index fce5b90d7..e6851a8b8 100644 --- a/xkt/pom.xml +++ b/xkt/pom.xml @@ -22,6 +22,13 @@ ruoyi-framework + + + com.ruoyi + ruoyi-common + + + io.springfox diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleDetail.java b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleDetail.java index ccd201337..d3359d894 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleDetail.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleDetail.java @@ -21,81 +21,77 @@ import java.math.BigDecimal; @Data @Accessors(chain = true) public class StoreSaleDetail extends XktBaseEntity { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; /** * 档口商品销售出库明细ID */ @TableId private Long id; - /** * 档口商品销售ID */ @Excel(name = "档口商品销售ID") private Long storeSaleId; - /** * 档口商品ID */ @Excel(name = "档口商品ID") private Long storeProdId; - /** * 档口商品颜色尺码ID */ @Excel(name = "档口商品颜色尺码ID") private Long storeProdColorSizeId; - + /** + * 颜色 + */ + private String colorName; + /** + * 尺码 + */ + private Integer size; /** * 销售类型(普通销售、销售退货) */ @Excel(name = "销售类型", readConverterExp = "普=通销售、销售退货") private String saleType; - /** * 商品货号 */ @Excel(name = "商品货号") private String prodArtNum; - /** * 销售单价 */ @Excel(name = "销售单价") private BigDecimal price; - /** * 给客户优惠后单价 */ @Excel(name = "给客户优惠后单价") private BigDecimal discountedPrice; - /** * 数量 */ @Excel(name = "数量") private Integer quantity; - /** * 总金额 */ @Excel(name = "总金额") private BigDecimal amount; - /** * 其它优惠 */ @Excel(name = "其它优惠") private BigDecimal otherDiscount; - /** * 条码 */ @Excel(name = "条码") private String sns; - @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecord.java b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecord.java index 980e1071b..6f3afa92a 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecord.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecord.java @@ -6,6 +6,7 @@ import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.core.domain.XktBaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -20,6 +21,7 @@ import java.util.Date; */ @EqualsAndHashCode(callSuper = true) @Data +@Accessors(chain = true) public class StoreSaleRefundRecord extends XktBaseEntity { private static final long serialVersionUID = 1L; diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecordDetail.java b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecordDetail.java new file mode 100644 index 000000000..5e5b65102 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreSaleRefundRecordDetail.java @@ -0,0 +1,120 @@ +package com.ruoyi.xkt.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.XktBaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.math.BigDecimal; + +/** + * 档口销售返单明细对象 store_sale_refund_record_detail + * + * @author ruoyi + * @date 2025-03-26 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +public class StoreSaleRefundRecordDetail extends XktBaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 档口商品销售返单出库明细ID + */ + @TableId + private Long id; + + /** + * 档口商品销售返单ID + */ + @Excel(name = "档口商品销售ID") + private Long storeSaleRefundRecordId; + + /** + * 档口商品ID + */ + @Excel(name = "档口商品ID") + private Long storeProdId; + + /** + * 档口商品颜色尺码ID + */ + @Excel(name = "档口商品颜色尺码ID") + private Long storeProdColorSizeId; + /** + * 颜色 + */ + private String colorName; + /** + * 尺码 + */ + private Integer size; + /** + * 销售类型(普通销售、销售退货) + */ + @Excel(name = "销售类型", readConverterExp = "普=通销售、销售退货") + private String saleType; + /** + * 商品货号 + */ + @Excel(name = "商品货号") + private String prodArtNum; + /** + * 销售单价 + */ + @Excel(name = "销售单价") + private BigDecimal price; + /** + * 给客户优惠后单价 + */ + @Excel(name = "给客户优惠后单价") + private BigDecimal discountedPrice; + /** + * 数量 + */ + @Excel(name = "数量") + private Integer quantity; + /** + * 总金额 + */ + @Excel(name = "总金额") + private BigDecimal amount; + /** + * 其它优惠 + */ + @Excel(name = "其它优惠") + private BigDecimal otherDiscount; + /** + * 条码 + */ + @Excel(name = "条码") + private String sns; + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("storeSaleRefundRecordId", getStoreSaleRefundRecordId()) + .append("storeProdId", getStoreProdId()) + .append("storeProdColorSizeId", getStoreProdColorSizeId()) + .append("saleType", getSaleType()) + .append("price", getPrice()) + .append("discountedPrice", getDiscountedPrice()) + .append("quantity", getQuantity()) + .append("amount", getAmount()) + .append("otherDiscount", getOtherDiscount()) + .append("version", getVersion()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeCustomer/StoreCusGeneralSaleDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeCustomer/StoreCusGeneralSaleDTO.java index a1e2554db..30da65cfb 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/storeCustomer/StoreCusGeneralSaleDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeCustomer/StoreCusGeneralSaleDTO.java @@ -26,7 +26,7 @@ public class StoreCusGeneralSaleDTO { @ApiModelProperty(name = "档口客户ID") private Long storeCusId; @ApiModelProperty(name = "档口客户名称") - private String cusName; + private String storeCusName; @ApiModelProperty(name = "销售多少双") private Long saleCount; @ApiModelProperty(name = "销售金额") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDTO.java index 82e0fc698..f36006f05 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDTO.java @@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.math.BigDecimal; import java.util.List; @@ -26,12 +27,10 @@ public class StoreSaleDTO { private Long storeId; @ApiModelProperty(name = "档口客户ID") private Long storeCusId; + @ApiModelProperty(name = "档口客户名称") + private String storeCusName; @ApiModelProperty(name = "销售类型(普通销售 GENERAL_SALE、销售退货 SALE_REFUND、普通销售/销售退货 SALE_AND_REFUND)") private String saleType; - @ApiModelProperty(name = "数量") - private Integer quantity; - @ApiModelProperty(name = "总金额") - private BigDecimal amount; @ApiModelProperty(name = "支付方式(支付宝、微信、现金、欠款)ALIPAY WECHAT_PAY CASH DEBT") private String payWay; @ApiModelProperty(name = "结款状态(已结清、欠款) SETTLED、DEBT") @@ -45,6 +44,10 @@ public class StoreSaleDTO { private Long storeProdId; @ApiModelProperty(name = "档口商品颜色尺码ID") private Long storeProdColorSizeId; + @ApiModelProperty(name = "颜色") + private String colorName; + @ApiModelProperty(name = "尺码") + private Integer size; @ApiModelProperty(name = "商品货号") private String prodArtNum; @ApiModelProperty(name = "销售条码") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSalePayStatusDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSalePayStatusDTO.java new file mode 100644 index 000000000..7ad0a2324 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSalePayStatusDTO.java @@ -0,0 +1,24 @@ +package com.ruoyi.xkt.dto.storeSale; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口商品销售客户欠款结算") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreSalePayStatusDTO { + + @ApiModelProperty(name = "结算的storeSaleId列表") + private List storeSaleIdList; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleRefundRecordDetailMapper.java b/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleRefundRecordDetailMapper.java new file mode 100644 index 000000000..7888a0f95 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleRefundRecordDetailMapper.java @@ -0,0 +1,14 @@ +package com.ruoyi.xkt.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.xkt.domain.StoreSaleRefundRecordDetail; + +/** + * 档口销售返单Mapper接口 + * + * @author ruoyi + * @date 2025-03-26 + */ +public interface StoreSaleRefundRecordDetailMapper extends BaseMapper { + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java index 242237a21..bb19905f0 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java @@ -6,6 +6,7 @@ import com.ruoyi.xkt.dto.storeCustomer.StoreCusGeneralSaleDTO; import com.ruoyi.xkt.dto.storeSale.StoreSaleDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageResDTO; +import com.ruoyi.xkt.dto.storeSale.StoreSalePayStatusDTO; import java.util.List; @@ -22,7 +23,7 @@ public interface IStoreSaleService { * @param storeSaleId 档口销售出库主键 * @return 档口销售出库 */ - public StoreSale selectStoreSaleByStoreSaleId(Long storeSaleId); + public StoreSaleDTO selectStoreSaleByStoreSaleId(Long storeSaleId); /** * 查询档口销售出库列表 @@ -80,4 +81,11 @@ public interface IStoreSaleService { */ Page page(StoreSalePageDTO pageDTO); + /** + * 批量结算客户欠款 + * @param payStatusDTO + * @return int + */ + void clearStoreCusDebt(StoreSalePayStatusDTO payStatusDTO); + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java index 242af1c81..73ebc10ac 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java @@ -5,19 +5,19 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.page.Page; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.xkt.domain.StoreCustomer; -import com.ruoyi.xkt.domain.StoreSale; -import com.ruoyi.xkt.domain.StoreSaleDetail; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.bigDecimal.CollectorsUtil; +import com.ruoyi.xkt.domain.*; import com.ruoyi.xkt.dto.storeCustomer.StoreCusGeneralSaleDTO; import com.ruoyi.xkt.dto.storeSale.StoreSaleDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageResDTO; -import com.ruoyi.xkt.mapper.StoreCustomerMapper; -import com.ruoyi.xkt.mapper.StoreSaleDetailMapper; -import com.ruoyi.xkt.mapper.StoreSaleMapper; +import com.ruoyi.xkt.dto.storeSale.StoreSalePayStatusDTO; +import com.ruoyi.xkt.mapper.*; import com.ruoyi.xkt.service.IStoreSaleService; import com.ruoyi.xkt.service.IVoucherSequenceService; import lombok.RequiredArgsConstructor; @@ -49,6 +49,8 @@ public class StoreSaleServiceImpl implements IStoreSaleService { final StoreCustomerMapper storeCusMapper; final IVoucherSequenceService sequenceService; final StoreSaleDetailMapper storeSaleDetailMapper; + final StoreSaleRefundRecordMapper refundRecordMapper; + final StoreSaleRefundRecordDetailMapper refundRecordDetailMapper; /** * 获取当前档口客户的销售业绩 @@ -61,7 +63,6 @@ public class StoreSaleServiceImpl implements IStoreSaleService { @Override @Transactional(readOnly = true) public StoreCusGeneralSaleDTO getCusGeneralSale(Integer days, Long storeId, Long storeCusId) { - // 获取档口客户 StoreCustomer storeCus = Optional.ofNullable(this.storeCusMapper.selectOne(new LambdaQueryWrapper() .eq(StoreCustomer::getId, storeCusId).eq(StoreCustomer::getDelFlag, "0"))) .orElseThrow(() -> new ServiceException("档口客户不存在!", HttpStatus.ERROR)); @@ -75,7 +76,7 @@ public class StoreSaleServiceImpl implements IStoreSaleService { .eq(StoreSale::getDelFlag, "0").between(StoreSale::getVoucherDate, pastDate, nowDate)); // 初始化返回对象 StoreCusGeneralSaleDTO generalSaleDTO = StoreCusGeneralSaleDTO.builder().storeId(storeId).storeCusId(storeCusId) - .cusName(storeCus.getCusName()).saleAmount(BigDecimal.ZERO).debtAmount(BigDecimal.ZERO) + .storeCusName(storeCus.getCusName()).saleAmount(BigDecimal.ZERO).debtAmount(BigDecimal.ZERO) .saleCount(0L).build(); if (CollectionUtils.isEmpty(saleList)) { return generalSaleDTO; @@ -85,7 +86,7 @@ public class StoreSaleServiceImpl implements IStoreSaleService { // 总的销售数量 Long saleCount = saleList.stream().map(x -> x.getQuantity() == null ? 0L : x.getQuantity()).reduce(0L, Long::sum); // 总的欠款金额 - BigDecimal debtAmount = saleList.stream().filter(x -> Objects.equals(x.getPayWay(), "DEBT")) + BigDecimal debtAmount = saleList.stream().filter(x -> Objects.equals(x.getPaymentStatus(), "DEBT")) .map(x -> ObjectUtils.defaultIfNull(x.getAmount(), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add); return generalSaleDTO.setSaleAmount(saleAmount).setSaleCount(saleCount).setDebtAmount(debtAmount); } @@ -104,6 +105,27 @@ public class StoreSaleServiceImpl implements IStoreSaleService { return Page.convert(new PageInfo<>(list)); } + /** + * 批量结算客户欠款 + * + * @param payStatusDTO 入参 + * @return int + */ + @Override + @Transactional + public void clearStoreCusDebt(StoreSalePayStatusDTO payStatusDTO) { + List storeSaleList = Optional.ofNullable(this.storeSaleMapper.selectList(new LambdaQueryWrapper() + .in(StoreSale::getId, payStatusDTO.getStoreSaleIdList()).eq(StoreSale::getDelFlag, "0"))) + .orElseThrow(() -> new ServiceException("没有找到对应的销售出库单!", HttpStatus.ERROR)); + // 勾选订单是否有已结算的 + List settledList = storeSaleList.stream().filter(x -> Objects.equals(x.getPaymentStatus(), "SETTLED")).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(settledList)) { + throw new ServiceException("当前订单已结算!" + settledList.stream().map(StoreSale::getCode).collect(Collectors.toList()), HttpStatus.ERROR); + } + storeSaleList.forEach(x -> x.setPaymentStatus("SETTLED")); + this.storeSaleMapper.updateById(storeSaleList); + } + /** * 新增档口销售出库 * @@ -116,39 +138,34 @@ public class StoreSaleServiceImpl implements IStoreSaleService { StoreSale storeSale = BeanUtil.toBean(storeSaleDTO, StoreSale.class); // 生成code String code = this.sequenceService.generateCode(storeSaleDTO.getStoreId(), "STORE_SALE", DateUtils.getDate()); - storeSale.setCode(code).setVoucherDate(DateUtils.getNowDate()); + // 总的数量 + Integer quantity = storeSaleDTO.getDetailList().stream().map(x -> ObjectUtils.defaultIfNull(x.getQuantity(), 0)).reduce(0, Integer::sum); + // 总的金额 + BigDecimal amount = storeSaleDTO.getDetailList().stream().map(x -> ObjectUtils.defaultIfNull(x.getAmount(), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add); + // 当前登录用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + // 属性赋值 + storeSale.setCode(code).setVoucherDate(DateUtils.getNowDate()).setQuantity(quantity).setAmount(amount) + .setOperatorId(loginUser.getUserId()).setOperatorName(loginUser.getUsername()); int count = storeSaleMapper.insert(storeSale); // 处理订单明细 List saleDetailList = storeSaleDTO.getDetailList().stream().map(x -> BeanUtil.toBean(x, StoreSaleDetail.class) .setSaleType(storeSaleDTO.getSaleType()).setStoreSaleId(storeSale.getId())).collect(Collectors.toList()); this.storeSaleDetailMapper.insert(saleDetailList); + + + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + + + return count; } - - /** - * 查询档口销售出库 - * - * @param storeSaleId 档口销售出库主键 - * @return 档口销售出库 - */ - @Override - public StoreSale selectStoreSaleByStoreSaleId(Long storeSaleId) { - return storeSaleMapper.selectStoreSaleByStoreSaleId(storeSaleId); - } - - /** - * 查询档口销售出库列表 - * - * @param storeSale 档口销售出库 - * @return 档口销售出库 - */ - @Override - public List selectStoreSaleList(StoreSale storeSale) { - return storeSaleMapper.selectStoreSaleList(storeSale); - } - - /** * 修改档口销售出库 * @@ -158,17 +175,110 @@ public class StoreSaleServiceImpl implements IStoreSaleService { @Override @Transactional public int updateStoreSale(StoreSaleDTO storeSaleDTO) { + // 当前登录用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); StoreSale storeSale = Optional.ofNullable(this.storeSaleMapper.selectOne(new LambdaQueryWrapper() .eq(StoreSale::getId, storeSaleDTO.getStoreSaleId()).eq(StoreSale::getDelFlag, "0"))) .orElseThrow(() -> new ServiceException("档口销售出库订单不存在!", HttpStatus.ERROR)); + // 档口销售出库明细列表 + List saleDetailList = this.storeSaleDetailMapper.selectList(new LambdaQueryWrapper() + .eq(StoreSaleDetail::getStoreSaleId, storeSaleDTO.getStoreSaleId()).eq(StoreSaleDetail::getDelFlag, "0")); // 若为返单,则将之前数据记录到返单记录表中 if (Objects.equals(storeSaleDTO.getRefund(), Boolean.TRUE)) { - + // 订单记录到StoreSaleRefundRecord + StoreSaleRefundRecord refundRecord = BeanUtil.toBean(storeSale, StoreSaleRefundRecord.class).setStoreSaleId(storeSale.getId()) + .setOperatorId(loginUser.getUserId()).setOperatorName(loginUser.getUsername()); + this.refundRecordMapper.insert(refundRecord); + // 明细记录到StoreSaleRefundRecordDetail + List refundDetailRecordList = saleDetailList.stream().map(x -> BeanUtil.toBean(x, StoreSaleRefundRecordDetail.class) + .setStoreSaleRefundRecordId(refundRecord.getId())).collect(Collectors.toList()); + this.refundRecordDetailMapper.insert(refundDetailRecordList); } - storeSale.setUpdateTime(DateUtils.getNowDate()); - return storeSaleMapper.updateStoreSale(storeSale); + // 更新档口销售数据 + BeanUtil.copyProperties(storeSaleDTO, storeSale); + // 总的数量 + Integer quantity = storeSaleDTO.getDetailList().stream().map(x -> ObjectUtils.defaultIfNull(x.getQuantity(), 0)).reduce(0, Integer::sum); + // 总的金额 + BigDecimal amount = storeSaleDTO.getDetailList().stream().map(x -> ObjectUtils.defaultIfNull(x.getAmount(), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add); + int count = this.storeSaleMapper.updateById(storeSale.setQuantity(quantity).setAmount(amount) + .setOperatorId(loginUser.getUserId()).setOperatorName(loginUser.getUsername())); + // 先将所有明细置为无效,再新增 + this.storeSaleDetailMapper.updateById(saleDetailList.stream().peek(x -> x.setDelFlag("2")).collect(Collectors.toList())); + + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + // TODO 扣件库存 + + + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + + + // 再新增档口销售出库明细数据 + List detailList = storeSaleDTO.getDetailList().stream().map(x -> BeanUtil.toBean(x, StoreSaleDetail.class) + .setSaleType(storeSaleDTO.getSaleType()).setStoreSaleId(storeSale.getId())).collect(Collectors.toList()); + this.storeSaleDetailMapper.insert(detailList); + return count; } + /** + * 查询档口销售出库 + * + * @param storeSaleId 档口销售出库主键 + * @return 档口销售出库 + */ + @Override + @Transactional(readOnly = true) + public StoreSaleDTO selectStoreSaleByStoreSaleId(Long storeSaleId) { + StoreSale storeSale = Optional.ofNullable(this.storeSaleMapper.selectOne(new LambdaQueryWrapper() + .eq(StoreSale::getId, storeSaleId).eq(StoreSale::getDelFlag, "0"))) + .orElseThrow(() -> new ServiceException("档口销售出库订单不存在!", HttpStatus.ERROR)); + StoreSaleDTO storeSaleDTO = BeanUtil.toBean(storeSale, StoreSaleDTO.class); + // 查询销售出库明细 + List saleDetailList = this.storeSaleDetailMapper.selectList(new LambdaQueryWrapper() + .eq(StoreSaleDetail::getStoreSaleId, storeSaleId).eq(StoreSaleDetail::getDelFlag, "0")); + storeSaleDTO.setDetailList(saleDetailList.stream().map(x -> BeanUtil.toBean(x, StoreSaleDTO.SaleDetailVO.class)).collect(Collectors.toList())); + return storeSaleDTO; + } + + /** + * 删除档口销售出库信息 + * + * @param storeSaleId 档口销售出库主键 + * @return 结果 + */ + @Override + public int deleteStoreSaleByStoreSaleId(Long storeSaleId) { + + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + // TODO 增加库存 + + // TODO 客户销售金额扣减、商品销售金额扣减 + + // 删除档口销售出库数据 + StoreSale storeSale = Optional.ofNullable(this.storeSaleMapper.selectOne(new LambdaQueryWrapper() + .eq(StoreSale::getId, storeSaleId).eq(StoreSale::getDelFlag, "0"))) + .orElseThrow(() -> new ServiceException("档口销售出库订单不存在!", HttpStatus.ERROR)); + storeSale.setDelFlag("2"); + int count = this.storeSaleMapper.updateById(storeSale); + // 删除档口销售出库明细数据 + List saleDetailList = this.storeSaleDetailMapper.selectList(new LambdaQueryWrapper() + .eq(StoreSaleDetail::getStoreSaleId, storeSaleId).eq(StoreSaleDetail::getDelFlag, "0")); + this.storeSaleDetailMapper.updateById(saleDetailList.stream().peek(x -> x.setDelFlag("2")).collect(Collectors.toList())); + return count; + } + + /** * 批量删除档口销售出库 * @@ -180,16 +290,18 @@ public class StoreSaleServiceImpl implements IStoreSaleService { return storeSaleMapper.deleteStoreSaleByStoreSaleIds(storeSaleIds); } + /** - * 删除档口销售出库信息 + * 查询档口销售出库列表 * - * @param storeSaleId 档口销售出库主键 - * @return 结果 + * @param storeSale 档口销售出库 + * @return 档口销售出库集合 */ @Override - public int deleteStoreSaleByStoreSaleId(Long storeSaleId) { - return storeSaleMapper.deleteStoreSaleByStoreSaleId(storeSaleId); + public List selectStoreSaleList(StoreSale storeSale) { + return null; } + }