feat: 收票登记新增所属合同带出承办部门替代手选结算组织
This commit is contained in:
+5
-1
@@ -59,10 +59,14 @@ public class InvoiceReceiptSaveRequest implements Serializable {
|
|||||||
private String attachmentsJson;
|
private String attachmentsJson;
|
||||||
private String remark;
|
private String remark;
|
||||||
/**
|
/**
|
||||||
* 结算组织(页面手选部门,先票后款链路收票登记不再必选关联结算单)
|
* 结算组织(历史兼容入参:现由所属合同承办部门带出,页面不再手选)
|
||||||
*/
|
*/
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
private String deptName;
|
private String deptName;
|
||||||
|
/**
|
||||||
|
* 所属合同编号(承运商合同,合同名称/承办部门按编号带出,不落库)
|
||||||
|
*/
|
||||||
|
private String contractNo;
|
||||||
/**
|
/**
|
||||||
* 关联结算单分摊(兼容历史入参:先票后款链路不再传,关联关系由付款结算单侧写入)
|
* 关联结算单分摊(兼容历史入参:先票后款链路不再传,关联关系由付款结算单侧写入)
|
||||||
*/
|
*/
|
||||||
|
|||||||
+4
@@ -112,6 +112,10 @@ public class InvoiceReceipt extends TenantEntity {
|
|||||||
* 收款方
|
* 收款方
|
||||||
*/
|
*/
|
||||||
private String payeeName;
|
private String payeeName;
|
||||||
|
/**
|
||||||
|
* 所属合同编号(承运商合同,结算组织=合同承办部门)
|
||||||
|
*/
|
||||||
|
private String contractNo;
|
||||||
/**
|
/**
|
||||||
* 往来户金蝶供应商代码(发票销售方,保存时经客商档案/A901-1 回填,推送 A303-2 前强校验)
|
* 往来户金蝶供应商代码(发票销售方,保存时经客商档案/A901-1 回填,推送 A303-2 前强校验)
|
||||||
*/
|
*/
|
||||||
|
|||||||
+38
-13
@@ -57,6 +57,7 @@ import org.springblade.transport.constant.KingdeeAttachmentConstant;
|
|||||||
import org.springblade.transport.constant.KingdeeBfiConstant;
|
import org.springblade.transport.constant.KingdeeBfiConstant;
|
||||||
import org.springblade.transport.constant.TransportBusiConstant;
|
import org.springblade.transport.constant.TransportBusiConstant;
|
||||||
import org.springblade.transport.event.KingdeeBillApprovedEvent;
|
import org.springblade.transport.event.KingdeeBillApprovedEvent;
|
||||||
|
import org.springblade.transport.mapper.ContractManageMapper;
|
||||||
import org.springblade.transport.mapper.CustomerArchiveMapper;
|
import org.springblade.transport.mapper.CustomerArchiveMapper;
|
||||||
import org.springblade.transport.mapper.CustomerContactMapper;
|
import org.springblade.transport.mapper.CustomerContactMapper;
|
||||||
import org.springblade.transport.mapper.CustomerInvoiceInfoMapper;
|
import org.springblade.transport.mapper.CustomerInvoiceInfoMapper;
|
||||||
@@ -150,6 +151,7 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
|||||||
private final InvoiceReceiptSettlementMapper settlementRelationMapper;
|
private final InvoiceReceiptSettlementMapper settlementRelationMapper;
|
||||||
private final InvoiceReceiptRecordMapper recordMapper;
|
private final InvoiceReceiptRecordMapper recordMapper;
|
||||||
private final FormalSettlementMapper formalSettlementMapper;
|
private final FormalSettlementMapper formalSettlementMapper;
|
||||||
|
private final ContractManageMapper contractManageMapper;
|
||||||
/** 票池认领关系 Mapper,实时视图的 claimed 装饰标记取数来源 */
|
/** 票池认领关系 Mapper,实时视图的 claimed 装饰标记取数来源 */
|
||||||
private final FormalSettlementInvoiceMapper formalSettlementInvoiceMapper;
|
private final FormalSettlementInvoiceMapper formalSettlementInvoiceMapper;
|
||||||
private final FormalSettlementDetailMapper formalSettlementDetailMapper;
|
private final FormalSettlementDetailMapper formalSettlementDetailMapper;
|
||||||
@@ -423,12 +425,25 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
|||||||
}
|
}
|
||||||
copyInvoiceInformation(entity, invoice);
|
copyInvoiceInformation(entity, invoice);
|
||||||
if (requestedRows.isEmpty()) {
|
if (requestedRows.isEmpty()) {
|
||||||
// 先票后款:结算组织=页面手选部门(合同承办部门口径);付款方=受票单位、收款方=开票单位
|
// 先票后款:结算组织=所属合同承办部门(金蝶公司代码沿承办部门对应平台公司派生);付款方=受票单位、收款方=开票单位
|
||||||
if (request.getDeptId() == null) {
|
// 所属合同仅落 contract_no,合同名称等其余信息按编号实时带出
|
||||||
throw new ServiceException("请选择结算组织");
|
if (Func.isBlank(request.getContractNo())) {
|
||||||
|
throw new ServiceException("请选择所属合同");
|
||||||
}
|
}
|
||||||
entity.setDeptId(request.getDeptId());
|
ContractManage contract = contractManageMapper.selectOne(Wrappers.<ContractManage>lambdaQuery()
|
||||||
entity.setDeptName(request.getDeptName());
|
.eq(ContractManage::getContractNo, request.getContractNo()));
|
||||||
|
if (contract == null) {
|
||||||
|
throw new ServiceException("所属合同" + request.getContractNo() + "不存在");
|
||||||
|
}
|
||||||
|
if (!"承运商合同".equals(contract.getContractCategory())) {
|
||||||
|
throw new ServiceException("所属合同须为承运商类型的合同");
|
||||||
|
}
|
||||||
|
if (contract.getOrganizationId() == null) {
|
||||||
|
throw new ServiceException("合同" + contract.getContractNo() + "未维护承办部门,请先在合同管理中补录");
|
||||||
|
}
|
||||||
|
entity.setContractNo(contract.getContractNo());
|
||||||
|
entity.setDeptId(contract.getOrganizationId());
|
||||||
|
entity.setDeptName(contract.getOrganizationName());
|
||||||
entity.setPayerName(invoice.getReceiverName());
|
entity.setPayerName(invoice.getReceiverName());
|
||||||
entity.setPayeeName(invoice.getIssuerName());
|
entity.setPayeeName(invoice.getIssuerName());
|
||||||
// 往来户=发票销售方金蝶供应商代码(A901-1),保存时尽力回填,推送前强校验缺失阻断
|
// 往来户=发票销售方金蝶供应商代码(A901-1),保存时尽力回填,推送前强校验缺失阻断
|
||||||
@@ -735,12 +750,14 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
|||||||
fetchMirrorItemsFromPool(plan.mirror());
|
fetchMirrorItemsFromPool(plan.mirror());
|
||||||
}
|
}
|
||||||
log.info("收票登记[{}]开始 A303-2 推送金蝶收票单", receipt.getInvoiceNo());
|
log.info("收票登记[{}]开始 A303-2 推送金蝶收票单", receipt.getInvoiceNo());
|
||||||
ContractManage contract = kingdeeApBillSyncSupport.requireContract(plan.settlement().getContractId(), context);
|
// 组织/币种/往来户按登记所属合同派生(结算组织=合同承办部门对应平台公司金蝶编码);合同按编号实时带出
|
||||||
// 明细分录与应付单 A102-2 同源同口径:复用同一结算明细解析结果,结算明细行+结算合计费用项各一条
|
ContractManage contract = contractManageMapper.selectOne(Wrappers.<ContractManage>lambdaQuery()
|
||||||
List<KingdeeApBillSyncSupport.BfiEntryGroup> entryGroups =
|
.eq(ContractManage::getContractNo, receipt.getContractNo()));
|
||||||
kingdeeApBillSyncSupport.resolveEntryGroups(plan.details(), context);
|
if (contract == null) {
|
||||||
|
throw new ServiceException("所属合同" + receipt.getContractNo() + "不存在,请核实合同状态");
|
||||||
|
}
|
||||||
KingdeeReceivedInvoiceSyncSupport.ReceivedInvoicePushOutcome pushOutcome =
|
KingdeeReceivedInvoiceSyncSupport.ReceivedInvoicePushOutcome pushOutcome =
|
||||||
kingdeeReceivedInvoiceSyncSupport.pushReceivedInvoice(receipt, plan.mirror(), contract, entryGroups, context);
|
kingdeeReceivedInvoiceSyncSupport.pushReceivedInvoice(receipt, plan.mirror(), contract, context);
|
||||||
billNo = pushOutcome.billNo();
|
billNo = pushOutcome.billNo();
|
||||||
billPkId = pushOutcome.billId();
|
billPkId = pushOutcome.billId();
|
||||||
log.info("收票登记[{}]A303-2 推送成功:金蝶收票单[{}],星瀚内码={}", receipt.getInvoiceNo(), billNo, billPkId);
|
log.info("收票登记[{}]A303-2 推送成功:金蝶收票单[{}],星瀚内码={}", receipt.getInvoiceNo(), billNo, billPkId);
|
||||||
@@ -833,8 +850,8 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
|||||||
if ("2".equals(mirror.getCheckStatus())) {
|
if ("2".equals(mirror.getCheckStatus())) {
|
||||||
return new ReceivedInvoicePushPlan(receipt, mirror, null, null, null, "金蝶发票查验不通过,请先人工核实票池发票");
|
return new ReceivedInvoicePushPlan(receipt, mirror, null, null, null, "金蝶发票查验不通过,请先人工核实票池发票");
|
||||||
}
|
}
|
||||||
if (receipt.getDeptId() == null) {
|
if (Func.isBlank(receipt.getContractNo())) {
|
||||||
return new ReceivedInvoicePushPlan(receipt, mirror, null, null, null, "收票登记未选择结算组织,无法确定金蝶结算组织编码");
|
return new ReceivedInvoicePushPlan(receipt, mirror, null, null, null, "收票登记未选择所属合同,无法确定金蝶结算组织编码");
|
||||||
}
|
}
|
||||||
return new ReceivedInvoicePushPlan(receipt, mirror, null, null, null, null);
|
return new ReceivedInvoicePushPlan(receipt, mirror, null, null, null, null);
|
||||||
}
|
}
|
||||||
@@ -874,7 +891,15 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
|||||||
receipt.setKingdeePushStatus(pushStatus);
|
receipt.setKingdeePushStatus(pushStatus);
|
||||||
receipt.setKingdeePushMsg(pushMsg);
|
receipt.setKingdeePushMsg(pushMsg);
|
||||||
receipt.setKingdeePushTime(LocalDateTime.now());
|
receipt.setKingdeePushTime(LocalDateTime.now());
|
||||||
updateById(receipt);
|
// updateById 默认忽略 null 字段,推送成功时失败原因须显式置空,改用 lambdaUpdate 落库
|
||||||
|
update(Wrappers.<InvoiceReceipt>lambdaUpdate()
|
||||||
|
.eq(InvoiceReceipt::getId, receipt.getId())
|
||||||
|
.set(InvoiceReceipt::getKingdeeReceivedInvoiceNo, receipt.getKingdeeReceivedInvoiceNo())
|
||||||
|
.set(Func.isNotBlank(receipt.getKingdeeReceivedInvoiceId()), InvoiceReceipt::getKingdeeReceivedInvoiceId, receipt.getKingdeeReceivedInvoiceId())
|
||||||
|
.set(InvoiceReceipt::getKingdeePushStatus, receipt.getKingdeePushStatus())
|
||||||
|
.set(InvoiceReceipt::getKingdeePushMsg, receipt.getKingdeePushMsg())
|
||||||
|
.set(InvoiceReceipt::getKingdeePushTime, receipt.getKingdeePushTime())
|
||||||
|
.set(InvoiceReceipt::getUpdateTime, LocalDateTime.now()));
|
||||||
if (writeRecord) {
|
if (writeRecord) {
|
||||||
record(receipt.getId(), "sync", "推送金蝶收票单", receipt.getApprovalStatus(), receipt.getApprovalStatus(),
|
record(receipt.getId(), "sync", "推送金蝶收票单", receipt.getApprovalStatus(), receipt.getApprovalStatus(),
|
||||||
Func.isNotBlank(pushMsg) ? pushMsg : "金蝶收票单[" + Func.toStr(receivedInvoiceNo) + "]已生成",
|
Func.isNotBlank(pushMsg) ? pushMsg : "金蝶收票单[" + Func.toStr(receivedInvoiceNo) + "]已生成",
|
||||||
|
|||||||
+7
-9
@@ -152,21 +152,19 @@ public class KingdeeReceivedInvoiceSyncSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 推送金蝶收票单(A303-2 批量保存,调用方已完成 A801-3 幂等预检)。
|
* 推送金蝶收票单(A303-2 批量保存,调用方已完成 A801-3 幂等预检)。
|
||||||
* 主表:组织/币种/往来户编码按分摊结算单关联合同派生(与应付单同源),销方=开票单位、购方=受票单位;
|
* 主表:组织/币种/往来户编码按收票登记所属合同派生(与应付单同源),销方=开票单位、购方=受票单位;
|
||||||
* 明细分录与财务应付单 A102-2 同源同口径:结算明细按 货物→费用大类→税率 拆分行+手动添加结算合计费用项每行一条,物料/数量/单价/金额取自
|
* 明细分录取发票明细行(镜像 items_json,A801-1),标识同键。
|
||||||
* 与应付单分录同一解析结果({@link KingdeeApBillSyncSupport.BfiEntryGroup}),分录标识同键。
|
|
||||||
* 联调口径沿用应付侧:先只送 DTO 标注【必填】字段与票面核心字段(发票号码),
|
* 联调口径沿用应付侧:先只送 DTO 标注【必填】字段与票面核心字段(发票号码),
|
||||||
* 非必填的税号/地址/电话/开户行等 setter 注释保留,联调确认后放开
|
* 非必填的税号/地址/电话/开户行等 setter 注释保留,联调确认后放开
|
||||||
*
|
*
|
||||||
* @param receipt 收票登记(审批通过、已绑定镜像)
|
* @param receipt 收票登记(审批通过、已绑定镜像)
|
||||||
* @param mirror 票池镜像(票面主表字段取数来源)
|
* @param mirror 票池镜像(票面主表字段取数来源)
|
||||||
* @param contract 分摊应付结算单关联合同(组织/币种/往来户派生)
|
* @param contract 收票登记所属合同(组织/币种/往来户派生,结算组织=合同承办部门对应平台公司)
|
||||||
* @param entryGroups 分摊结算单解析出的分录(与应付单 A102-2 同一解析结果)
|
* @param context 金蝶同步上下文(缓存载体)
|
||||||
* @param context 金蝶同步上下文(缓存载体)
|
|
||||||
* @return 推送结果(单据编号 + 星瀚收票单内码,A902 附件上传定位用)
|
* @return 推送结果(单据编号 + 星瀚收票单内码,A902 附件上传定位用)
|
||||||
*/
|
*/
|
||||||
public ReceivedInvoicePushOutcome pushReceivedInvoice(InvoiceReceipt receipt, KingdeeInvoicePool mirror, ContractManage contract,
|
public ReceivedInvoicePushOutcome pushReceivedInvoice(InvoiceReceipt receipt, KingdeeInvoicePool mirror, ContractManage contract,
|
||||||
List<KingdeeApBillSyncSupport.BfiEntryGroup> entryGroups, KingdeeSyncContext context) {
|
KingdeeSyncContext context) {
|
||||||
if (Func.isBlank(mirror.getInvoiceTypeCode())) {
|
if (Func.isBlank(mirror.getInvoiceTypeCode())) {
|
||||||
throw new ServiceException("推送金蝶收票单失败:镜像缺少票易通发票类型编码,请先重新绑定票池发票");
|
throw new ServiceException("推送金蝶收票单失败:镜像缺少票易通发票类型编码,请先重新绑定票池发票");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
-- 收票登记新增所属合同编号:页面去掉手选结算组织,改为选择承运商合同带出承办部门
|
||||||
|
-- 口径:仅落 contract_no,合同名称/承办部门按编号实时带出;
|
||||||
|
-- 结算组织 = 合同承办部门(dept_id/dept_name 取合同 organization_id/organization_name),
|
||||||
|
-- 金蝶结算组织编码沿承办部门对应平台公司派生(KingdeeApBillSyncSupport#bfiOrgNumber)
|
||||||
|
-- 幂等可重复执行:列已存在时重复执行报 Duplicate column 属预期,跳过即可
|
||||||
|
|
||||||
|
ALTER TABLE `blade_invoice_receipt`
|
||||||
|
ADD COLUMN `contract_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '所属合同编号(承运商合同)' AFTER `payee_name`;
|
||||||
|
|
||||||
|
-- 存量已审批未推送数据无所属合同,推送前需编辑补录(推送预检按 contract_no 拦截)
|
||||||
|
SELECT COUNT(*) AS approved_receipts_without_contract
|
||||||
|
FROM `blade_invoice_receipt`
|
||||||
|
WHERE `is_deleted` = 0
|
||||||
|
AND `approval_status` = 'approved'
|
||||||
|
AND (`contract_no` IS NULL OR `contract_no` = '');
|
||||||
Reference in New Issue
Block a user