diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpFinInvoiceDetail.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpFinInvoiceDetail.java index 55bb821b..937fbd78 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpFinInvoiceDetail.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpFinInvoiceDetail.java @@ -6,6 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serial; +import java.math.BigDecimal; /** * 开票明细对象 erp_fin_invoice_detail @@ -49,27 +50,32 @@ public class ErpFinInvoiceDetail{ /** * 数量 */ - private Long quantity; + private BigDecimal quantity; /** * 单价 */ - private Long unitPrice; + private BigDecimal unitPrice; /** * 金额,自动计算 */ - private Long totalPrice; + private BigDecimal totalPrice; + + /** + * 金额(不含税) + */ + private BigDecimal totalPriceNoTax; /** * 税率/征收率,默认13% */ - private Long taxRate; + private BigDecimal taxRate; /** * 税额,自动计算 */ - private Long taxPrice; + private BigDecimal taxPrice; } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpFinInvoiceDetailBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpFinInvoiceDetailBo.java index de212355..1c824bd1 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpFinInvoiceDetailBo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpFinInvoiceDetailBo.java @@ -8,6 +8,7 @@ import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; import lombok.EqualsAndHashCode; import jakarta.validation.constraints.*; +import java.math.BigDecimal; /** * 开票明细业务对象 erp_fin_invoice_detail @@ -52,29 +53,32 @@ public class ErpFinInvoiceDetailBo extends BaseEntity { * 数量 */ @NotNull(message = "数量不能为空", groups = { AddGroup.class, EditGroup.class }) - private Long quantity; + private BigDecimal quantity; /** * 单价 */ - @NotNull(message = "单价不能为空", groups = { AddGroup.class, EditGroup.class }) - private Long unitPrice; + private BigDecimal unitPrice; /** * 金额,自动计算 */ - private Long totalPrice; + private BigDecimal totalPrice; + + /** + * 金额(不含税) + */ + private BigDecimal totalPriceNoTax; /** * 税率/征收率,默认13% */ - private Long taxRate; + private BigDecimal taxRate; /** * 税额,自动计算 */ - @NotNull(message = "税额,自动计算不能为空", groups = { AddGroup.class, EditGroup.class }) - private Long taxPrice; + private BigDecimal taxPrice; } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpFinInvoiceDetailVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpFinInvoiceDetailVo.java index 673356e9..47fe3a4a 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpFinInvoiceDetailVo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpFinInvoiceDetailVo.java @@ -9,6 +9,7 @@ import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; import java.io.Serial; +import java.math.BigDecimal; import java.io.Serializable; import java.util.Date; @@ -62,31 +63,37 @@ public class ErpFinInvoiceDetailVo implements Serializable { * 数量 */ @ExcelProperty(value = "数量") - private Long quantity; + private BigDecimal quantity; /** * 单价 */ @ExcelProperty(value = "单价") - private Long unitPrice; + private BigDecimal unitPrice; /** * 金额,自动计算 */ @ExcelProperty(value = "金额,自动计算") - private Long totalPrice; + private BigDecimal totalPrice; + + /** + * 金额(不含税) + */ + @ExcelProperty(value = "金额(不含税)") + private BigDecimal totalPriceNoTax; /** * 税率/征收率,默认13% */ @ExcelProperty(value = "税率/征收率,默认13%") - private Long taxRate; + private BigDecimal taxRate; /** * 税额,自动计算 */ @ExcelProperty(value = "税额,自动计算") - private Long taxPrice; + private BigDecimal taxPrice; } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpFinInvoiceInfoServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpFinInvoiceInfoServiceImpl.java index ab64e9d8..6175ffdc 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpFinInvoiceInfoServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpFinInvoiceInfoServiceImpl.java @@ -33,10 +33,13 @@ import org.dromara.oa.erp.mapper.ErpFinInvoiceInfoMapper; import org.dromara.oa.erp.service.IErpFinInvoiceInfoService; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Collection; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -50,6 +53,8 @@ import java.util.concurrent.atomic.AtomicBoolean; public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService implements IErpFinInvoiceInfoService { private static final String INVOICE_CODE_RULE = "1030"; + private static final BigDecimal ZERO = BigDecimal.ZERO; + private static final BigDecimal ONE_HUNDRED = new BigDecimal("100"); private final ErpFinInvoiceInfoMapper baseMapper; @@ -153,7 +158,7 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService 0; if (flag) { List erpFinInvoiceDetailList = bo.getErpFinInvoiceDetailList(); + validInvoiceDetailList(erpFinInvoiceDetailList); + rebuildInvoiceDetailList(erpFinInvoiceDetailList); erpFinInvoiceDetailList.forEach(erpFinInvoiceDetail -> { erpFinInvoiceDetail.setInvoiceId(add.getInvoiceId()); }); @@ -186,6 +193,8 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService toDeletedInvoiceDetailIdList = bo.getToDeletedInvoiceDetailIdList(); List erpFinInvoiceDetailList = bo.getErpFinInvoiceDetailList(); + validInvoiceDetailList(erpFinInvoiceDetailList); + rebuildInvoiceDetailList(erpFinInvoiceDetailList); erpFinInvoiceDetailList.forEach(erpFinInvoiceDetail -> { erpFinInvoiceDetail.setInvoiceId(bo.getInvoiceId()); }); @@ -202,7 +211,93 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService 0) { + throw new ServiceException("累计回款金额不能大于合同金额"); + } + if (entity.getIssueAmount() != null && entity.getTotalPrice() != null + && entity.getIssueAmount().compareTo(entity.getTotalPrice()) > 0) { + throw new ServiceException("本次开具金额不能大于合同金额"); + } + if (entity.getIssuancePercentage() != null + && entity.getIssuancePercentage().compareTo(ONE_HUNDRED) > 0) { + throw new ServiceException("本次开具发票比例不能超过100%"); + } + } + + private void validInvoiceDetailList(List detailList) { + if (detailList == null || detailList.isEmpty()) { + throw new ServiceException("开票明细不能为空"); + } + for (int i = 0; i < detailList.size(); i++) { + ErpFinInvoiceDetail detail = detailList.get(i); + int rowNo = i + 1; + if (StringUtils.isBlank(detail.getBillingItems())) { + throw new ServiceException("第" + rowNo + "行开票内容不能为空"); + } + if (StringUtils.isBlank(detail.getUnitName())) { + throw new ServiceException("第" + rowNo + "行单位不能为空"); + } + if (detail.getTaxRate() == null) { + throw new ServiceException("第" + rowNo + "行税率不能为空"); + } + if (detail.getQuantity() == null || detail.getQuantity().compareTo(ZERO) <= 0) { + throw new ServiceException("第" + rowNo + "行数量必须大于0"); + } + if ((detail.getTotalPrice() == null || detail.getTotalPrice().compareTo(ZERO) <= 0) + && (detail.getUnitPrice() == null || detail.getUnitPrice().compareTo(ZERO) <= 0)) { + throw new ServiceException("第" + rowNo + "行金额(含税)必须大于0"); + } + } + } + + private void rebuildInvoiceDetailList(List detailList) { + for (ErpFinInvoiceDetail detail : detailList) { + BigDecimal quantity = detail.getQuantity(); + BigDecimal totalPrice = detail.getTotalPrice(); + BigDecimal unitPrice = detail.getUnitPrice(); + BigDecimal taxRate = detail.getTaxRate() == null ? ZERO : detail.getTaxRate(); + + if ((totalPrice == null || totalPrice.compareTo(ZERO) <= 0) && unitPrice != null && unitPrice.compareTo(ZERO) > 0) { + totalPrice = quantity.multiply(unitPrice).setScale(2, RoundingMode.HALF_UP); + } + if (totalPrice == null || totalPrice.compareTo(ZERO) <= 0) { + throw new ServiceException("开票明细金额(含税)必须大于0"); + } + unitPrice = totalPrice.divide(quantity, 2, RoundingMode.HALF_UP); + + BigDecimal divisor = ONE_HUNDRED.add(taxRate).divide(ONE_HUNDRED, 6, RoundingMode.HALF_UP); + BigDecimal totalPriceNoTax = totalPrice.divide(divisor, 2, RoundingMode.HALF_UP); + BigDecimal taxPrice = totalPrice.subtract(totalPriceNoTax).setScale(2, RoundingMode.HALF_UP); + + detail.setTotalPrice(totalPrice); + detail.setUnitPrice(unitPrice); + detail.setTotalPriceNoTax(totalPriceNoTax); + detail.setTaxPrice(taxPrice); + } } /** @@ -247,6 +342,7 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService lqw = JoinWrappers.lambda(ErpContractPaymentMethod.class) .selectAll(ErpContractPaymentMethod.class) .eq(contractId != null, ErpContractPaymentMethod::getContractId, contractId) + .eq(ErpContractPaymentMethod::getDelFlag, "0") .orderByAsc(ErpContractPaymentMethod::getSortOrder); List erpContractPaymentMethodVoList = erpContractPaymentMethodMapper.selectCustomErpContractPaymentMethodVoList(lqw); return erpContractPaymentMethodVoList;