|
|
|
|
@ -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<ErpFinInvoiceInfoBo> 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<ErpFin
|
|
|
|
|
public Boolean insertByBo(ErpFinInvoiceInfoBo bo) {
|
|
|
|
|
String code = remoteCodeRuleService.selectCodeRuleCode(INVOICE_CODE_RULE);
|
|
|
|
|
if (StringUtils.isBlank(code)) {
|
|
|
|
|
throw new ServiceException("生成回款编号失败");
|
|
|
|
|
throw new ServiceException("生成开票申请编号失败");
|
|
|
|
|
}
|
|
|
|
|
bo.setInvoiceCode(code);
|
|
|
|
|
|
|
|
|
|
@ -163,6 +168,8 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService<ErpFin
|
|
|
|
|
boolean flag = baseMapper.insert(add) > 0;
|
|
|
|
|
if (flag) {
|
|
|
|
|
List<ErpFinInvoiceDetail> erpFinInvoiceDetailList = bo.getErpFinInvoiceDetailList();
|
|
|
|
|
validInvoiceDetailList(erpFinInvoiceDetailList);
|
|
|
|
|
rebuildInvoiceDetailList(erpFinInvoiceDetailList);
|
|
|
|
|
erpFinInvoiceDetailList.forEach(erpFinInvoiceDetail -> {
|
|
|
|
|
erpFinInvoiceDetail.setInvoiceId(add.getInvoiceId());
|
|
|
|
|
});
|
|
|
|
|
@ -186,6 +193,8 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService<ErpFin
|
|
|
|
|
validEntityBeforeSave(update);
|
|
|
|
|
List<Long> toDeletedInvoiceDetailIdList = bo.getToDeletedInvoiceDetailIdList();
|
|
|
|
|
List<ErpFinInvoiceDetail> erpFinInvoiceDetailList = bo.getErpFinInvoiceDetailList();
|
|
|
|
|
validInvoiceDetailList(erpFinInvoiceDetailList);
|
|
|
|
|
rebuildInvoiceDetailList(erpFinInvoiceDetailList);
|
|
|
|
|
erpFinInvoiceDetailList.forEach(erpFinInvoiceDetail -> {
|
|
|
|
|
erpFinInvoiceDetail.setInvoiceId(bo.getInvoiceId());
|
|
|
|
|
});
|
|
|
|
|
@ -202,7 +211,93 @@ public class ErpFinInvoiceInfoServiceImpl extends AbstractWorkflowService<ErpFin
|
|
|
|
|
* 保存前的数据校验
|
|
|
|
|
*/
|
|
|
|
|
private void validEntityBeforeSave(ErpFinInvoiceInfo entity) {
|
|
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
|
|
if (entity == null) {
|
|
|
|
|
throw new ServiceException("开票信息不能为空");
|
|
|
|
|
}
|
|
|
|
|
if (entity.getProjectId() == null) {
|
|
|
|
|
throw new ServiceException("请选择项目");
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isBlank(entity.getProjectCode())) {
|
|
|
|
|
throw new ServiceException("项目编号不能为空");
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isBlank(entity.getInvoiceCategory())) {
|
|
|
|
|
throw new ServiceException("请选择项目类型");
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isBlank(entity.getEarlyFlag())) {
|
|
|
|
|
throw new ServiceException("请选择是否提前开票");
|
|
|
|
|
}
|
|
|
|
|
if (Objects.equals(entity.getEarlyFlag(), "1") && StringUtils.isBlank(entity.getEarlyReason())) {
|
|
|
|
|
throw new ServiceException("提前开票时必须填写提前开票原因");
|
|
|
|
|
}
|
|
|
|
|
if (!Objects.equals(entity.getEarlyFlag(), "1")
|
|
|
|
|
&& entity.getAcceptanceDate() == null
|
|
|
|
|
&& entity.getDeliveryDate() == null) {
|
|
|
|
|
throw new ServiceException("非提前开票时,验收日期和发货日期至少填写一个");
|
|
|
|
|
}
|
|
|
|
|
if (entity.getReturnedMoney() != null && entity.getTotalPrice() != null
|
|
|
|
|
&& entity.getReturnedMoney().compareTo(entity.getTotalPrice()) > 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<ErpFinInvoiceDetail> 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<ErpFinInvoiceDetail> 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<ErpFin
|
|
|
|
|
MPJLambdaWrapper<ErpContractPaymentMethod> lqw = JoinWrappers.lambda(ErpContractPaymentMethod.class)
|
|
|
|
|
.selectAll(ErpContractPaymentMethod.class)
|
|
|
|
|
.eq(contractId != null, ErpContractPaymentMethod::getContractId, contractId)
|
|
|
|
|
.eq(ErpContractPaymentMethod::getDelFlag, "0")
|
|
|
|
|
.orderByAsc(ErpContractPaymentMethod::getSortOrder);
|
|
|
|
|
List<ErpContractPaymentMethodVo> erpContractPaymentMethodVoList = erpContractPaymentMethodMapper.selectCustomErpContractPaymentMethodVoList(lqw);
|
|
|
|
|
return erpContractPaymentMethodVoList;
|
|
|
|
|
|