## woker.go 在这个合单的work里面,订单从合单前变为合单后,哪些订单数据变更了 下面是合单处理过程中订单状态和数据发生变化的主要点: 1. **新增集合订单记录(TWealthNomineeOrder)** 在合单过程中,会生成一个新的集合订单记录,该记录将不同客户订单中的数据进行聚合,主要包括: - **申请金额(ApplyAmount)**:将各客户订单中的申请金额累加。 - **申请份额(ApplyQuantity)**:将各客户订单中的申请份额累加。 - **费用(Fee)**:各订单费用累加。 - 其他基础信息(如币种、产品代码、产品名称、产品类型、ISIN、交易方向、费率等)也会从其中一笔或聚合后赋值。 此外,还会生成新的**订单号**(通过 `generateNomineeOrderNumber` 函数计算),并设置初始订单状态(例如 `nomineeorderconstant.WealthNomineeOrderStatusWaiting`)。 2. **更新客户订单数据(TWealthOrder)** 对于每笔参与合单的客户订单,在合单成功后会进行如下更新: - **RofNomineeOrderStatus** 更新为合单后的状态(通常为“已合单”状态,对应常量 `orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED`),标识该订单已经被合单处理。 - **NomineeOrderId** 将字段设置为刚生成的集合订单记录的 ID,以建立从客户订单到集合订单的关联关系。 - **ExpectSettleDate** 更新为新计算的预计结算日(调用了 `getExpectSettledDateV3` 考虑基金节假日等因素后得到的结算日期)。 3. **对于赎回订单的特殊处理** - 当赎回订单存在来自多个非主上手的情况时,还可能对集合订单进行**拆分**,生成多个子集合订单。 - 对拆分出来的子集合订单,会单独生成订单号,并设置相应的标记(例如 `NomineeOrderTagTypeSub`),以及设置正确的上手信息(Custodian、CustodianAccountNumber)和运行模式(RunMode)。 不过对于原始的客户订单来说,更新的依然是上面提到的三个字段(订单状态、集合订单ID、预计结算日)。 4. **冻结持仓** 虽然不是直接更新订单字段,但合单过程中还会调用 `batchFrozenCustodianHolding` 方法,通过冻结相应的持仓来保证资金/份额在结算期间不会被重复使用,这也是合单后订单后续处理的重要步骤。 --- **总结:** 从合单前到合单后,主要发生变化的是: - 新增一条集合订单(TWealthNomineeOrder),其数据为来自各客户订单的聚合(申请金额、份额、费用、订单号、订单状态等)。 - 各客户订单(TWealthOrder)更新了三个字段: - **RofNomineeOrderStatus** 置为“已合单”; - **NomineeOrderId** 被设置为新生成的集合订单的 ID; - **ExpectSettleDate** 被更新为合单后的预计结算日。 ## 那请你根据合单work的合单条件,我想写检查的sql来检查今日该合单的订单是否全部都合单了,首先根据合单的条件查询今日应该合单的订单的数量,还要集合出所有总认购金额或者总认购份额,然后再根据合单后的集合订单的订单号搜出所有NomineeOrderId相同的客户订单,对比客户订单数量、总认购金额、总赎回份额是否和对应的集合订单对齐 下面给出一个示例思路和 SQL 检查脚本,假设你的数据表名如下(你可以根据实际情况调整): - 客户订单表:`TWealthOrder` - 合单(集合订单)表:`TWealthNomineeOrder` 在合单流程中,客户订单在合单后会更新如下字段: - 将字段 `RofNomineeOrderStatus` 的值更新为“合单后状态”(本例中我们用字符串 `'CONSOLIDATED'` 表示), - 填写字段 `NomineeOrderId`(指向产生的集合订单记录), - 同时更新预计结算日等字段。 同时,新产生的集合订单中会保存本批次客户订单累计的申请金额(`ApplyAmount`)和申请份额(`ApplyQuantity`)等信息。 下面给出两个步骤的 SQL 检查示例: --- ### 1. 查询今日应该合单的客户订单数量及累计金额/份额 首先根据合单条件(例如:下单日期为当日、订单状态处于合单前状态)查询客户订单数及累计金额/份额。假设有一个字段 `CreationTime` 或 `CreatedAt` 表示订单日期,且合单前订单状态为 `'PENDING'`(或其它条件,请根据实际情况替换),示例如下: ```sql -- 查询今日需要合单的客户订单数量及累计申请金额和申请份额 SELECT COUNT(*) AS TotalOrders, SUM(CAST(ApplyNetAmount AS DECIMAL(20,4))) AS TotalApplyNetAmount, SUM(CAST(ApplyQuantity AS DECIMAL(20,4))) AS TotalApplyQuantity FROM TWealthOrder WHERE DATE(CreationTime) = CURDATE() AND RofNomineeOrderStatus = 'PENDING'; -- 或其它合单前标识 ``` 如果你系统里“待合单”订单的筛选条件除日期和状态外还受其它限制(例如:仅针对货币型/非货币型基金),请在 `WHERE` 子句中补充相应逻辑。 --- ### 2. 根据生成的集合订单,检查对应的客户订单是否准确更新 在合单成功后,每一批(或者每组)客户订单会根据合单类型生成一个(主集合单)合单号,比如字段 `OrderNumber` 以及自动生成的主集合订单的 `Id`。而所有参与合单的客户订单的 `NomineeOrderId` 均指向该生成的集合订单记录。 下面这个 SQL 通过连接 `TWealthOrder` 和 `TWealthNomineeOrder` 表,按每个集合订单进行分组,计算对应客户订单的数量及累计金额/份额,同时将结果与集合订单自身保存的累计信息进行对比: ```sql -- 检查合单后每个集合订单对应的客户订单数量和累计申请金额/份额是否与集合订单中记录的值一致 SELECT n.Id AS ConsolidatedId, n.OrderNumber AS ConsolidatedOrderNumber, COUNT(o.Id) AS ClientOrderCount, SUM(CAST(o.ApplyNetAmount AS DECIMAL(20,4))) AS TotalClientApplyNetAmount, SUM(CAST(o.ApplyQuantity AS DECIMAL(20,4))) AS TotalClientApplyQuantity, n.ApplyAmount AS ConsolidatedApplyAmount, n.ApplyQuantity AS ConsolidatedApplyQuantity FROM TWealthNomineeOrder n JOIN TWealthOrder o ON o.NomineeOrderId = n.Id WHERE DATE(n.SubmitTime) = CURDATE() GROUP BY n.Id, n.OrderNumber, n.ApplyAmount, n.ApplyQuantity; ``` 在上面的 SQL 中: - 我们过滤出今天(`CURDATE()`)生成的集合订单(假设集合订单的提交时间存储在 `SubmitTime` 字段中), - 按集合订单的 `Id` 进行分组,同时聚合统计对应客户订单的数量与累计金额/份额。 对比后你可以判断: - 每个集合订单的累计申请金额(`ConsolidatedApplyAmount`)是否与该分组下各客户订单 `ApplyNetAmount` 的和一致; - 每个集合订单的累计申请份额(`ConsolidatedApplyQuantity`)是否与该分组下各客户订单 `ApplyQuantity` 的和一致; - 如果需要,也可以对每个组的客户订单数量与预期的数量进行比对。 --- ### 3. 补充检查:待合单客户订单检查 如果你还希望确保今日所有应该合单的客户订单都已更新为“合单”状态,即不存在“待合单”的订单,可以执行如下检查: ```sql -- 检查今日待合单但未更新(即状态仍非 'CONSOLIDATED')的客户订单数量 SELECT COUNT(*) AS NotConsolidatedCount FROM TWealthOrder WHERE DATE(CreationTime) = CURDATE() AND RofNomineeOrderStatus != 'CONSOLIDATED'; ``` 返回记录数应该为 0,此即表示今日所有待合单客户订单都已完成合单更新。 --- ### 总结 以上 SQL 脚本就是基于合单 worker 处理的条件: 1. 首先根据下单日期和合单前状态筛选出今日待合单的客户订单,并聚合出总申请金额/份额; 2. 然后通过集合订单(即合单后生成的记录)的订单号(或 ID)找到对应客户订单,并统计每个集合订单下的客户订单数量及累计申请金额/份额,进而和集合订单中保存的值进行对比; 3. 另外也可检查是否存在遗漏未更新为合单的客户订单。 你可以根据实际的字段名和业务逻辑(比如“货币型”与“非货币型”的区分、数值字段的存储类型等)做进一步调整。 ## 合单work的sql在@t\_wealth\_order.go 这段代码里面都有,请你根据我提供的t\_wealth\_orderde的代码,优化上面的sql。另外数据库中申请金额和申请份额的字段定义我也发给你看: \`applyAmount\` decimal(19,6) DEFAULT NULL COMMENT '申请金额',\`applyQuantity\` decimal(19,6) DEFAULT NULL COMMENT '申请份额', 下面给出的优化方案参考了你在 `t_wealth_order.go` 中的查询条件,假设系统中客户订单表为 `t_wealth_order`,合单(集合订单)表为 `t_wealth_nominee_order`。 注意: - 在合单前,合单订单查询条件(以非货币型为例)为: - `orderStatus = ` - `canConsolidate = 1` - `RofNomineeOrderStatus = 0` - 并通过产品类型(`productType`)以及货币型标识(`isMonetaryFund`)进行区分。 - 合单后,每笔客户订单会更新: - `RofNomineeOrderStatus`(改为已合单状态,例如非零的常量,如 “CONSOLIDATED”) - 同时将 `NomineeOrderId` 置为对应合单记录的 ID - 数据库中金额和份额字段类型均为 `DECIMAL(19,6)`,因此在 SQL 中可以直接进行数值计算而无需额外转换。 下面提供三个 SQL 查询示例: --- ### 1. 查询今日待合单的客户订单(即还未更新为合单状态)的数量及累计申请金额/申请份额 这里假设当天的客户订单以 `createTime` 记录日期,且合单前状态条件中 `orderStatus = 'ACCEPTED'`(你可替换为实际值)、`canConsolidate = 1`,并且尚未合单(`RofNomineeOrderStatus = 0`)。 ```sql:sql/check_consolidation.sql -- [CheckPendingOrders] -- 查询今日满足合单条件、但未更新为合单状态的客户订单数量以及累计的申请金额和申请份额 SELECT COUNT(*) AS pending_orders, COALESCE(SUM(applyAmount), 0) AS total_pending_apply_amount, COALESCE(SUM(applyQuantity), 0) AS total_pending_apply_quantity FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus = 0; ``` 如果有货币型跟非货币型之分,那么可在 WHERE 中增加: - 对货币型: `AND isMonetaryFund = 1` - 对非货币型: `AND isMonetaryFund = 0` --- ### 2. 根据合单后的集合订单,统计各个集合订单下关联的客户订单数量及累计申请金额/申请份额 该 SQL 通过 `t_wealth_nominee_order`(合单表)的提交时间(字段 `SubmitTime`)过滤当天生成的集合订单,然后连接客户订单表(通过字段 `NomineeOrderId`),按每个合单聚合统计对应的客户订单数据。 ```sql:sql/check_consolidation.sql -- [CheckConsolidatedOrders] -- 检查当天生成的每个集合订单(合单后的订单),并统计其下关联的客户订单的数量、累计申请金额和累计申请份额 SELECT n.Id AS consolidated_id, n.OrderNumber AS consolidated_order_number, COUNT(o.Id) AS client_order_count, COALESCE(SUM(o.applyAmount), 0) AS total_client_apply_amount, COALESCE(SUM(o.applyQuantity), 0) AS total_client_apply_quantity, n.applyAmount AS consolidated_apply_amount, n.applyQuantity AS consolidated_apply_quantity FROM t_wealth_nominee_order n JOIN t_wealth_order o ON o.NomineeOrderId = n.Id WHERE DATE(n.SubmitTime) = CURDATE() GROUP BY n.Id, n.OrderNumber, n.applyAmount, n.applyQuantity; ``` 通过上述查询,你可以对比每个集合订单(合单记录)中保存的 `applyAmount`/`applyQuantity` 与其下所有客户订单累计值是否一致,从而判断合单过程是否正确。 --- ### 3. 检查是否存在遗漏未合单的客户订单 最终,你可以再执行以下 SQL,确认今日所有应合单的客户订单均已更新(即没有仍处于待合单状态的记录): ```sql:sql/check_consolidation.sql -- [CheckAllOrdersConsolidated] -- 确认当天没有遗漏未合单的客户订单 SELECT COUNT(*) AS un_consolidated_count FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus = 0; ``` 返回的 `un_consolidated_count` 应为 0,否则说明还有未被合单处理的客户订单。 --- ### 总结 以上 SQL 脚本均参考了 `t_wealth_order.go` 中的查询条件并结合了数据库中 `applyAmount` 与 `applyQuantity` 字段的定义进行优化。 你可以根据业务的货币型/非货币型区分,在对应的 WHERE 子句中增加对 `isMonetaryFund` 或 `productType` 的判断条件,从而满足更加精细的检查需要。 ## 我突然意识到一个问题,我这个定时任务是在合单定时任务后面执行的,这个时候订单的状态都已经变了 下面的方案考虑到了定时任务执行时,所有客户订单已经从合单前(例如 `RofNomineeOrderStatus = 0`)更新为了合单后的状态(例如更新为 `CONSOLIDATED`,你可以根据实际定义替换条件),从而需要使用新状态进行检查。下面给出两组优化后的 SQL 语句示例: --- ### 1. 检查今日所有应合单客户订单的汇总数据 由于合单任务执行后,客户订单已经更新,即: - `orderStatus` 正常(例如 `'ACCEPTED'`) - `canConsolidate = 1` - `RofNomineeOrderStatus` 已更新为合单后的状态(例如 `'CONSOLIDATED'` 或对应数值) 因此,原先检查【待合单】的 SQL 条件应调整为使用合单后状态。例如: ```sql:sql/check_consolidated_orders.sql -- [CheckConsolidatedClientOrders] -- 查询今日已合单客户订单数量及累计申请金额/申请份额 SELECT COUNT(*) AS consolidated_orders, COALESCE(SUM(applyAmount), 0) AS total_consolidated_apply_amount, COALESCE(SUM(applyQuantity), 0) AS total_consolidated_apply_quantity FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus = 'CONSOLIDATED'; -- 此处请用实际的已合单标识(如果是数值,则改为相应数字) ``` **说明** - 注意这里假设合单后订单的 `RofNomineeOrderStatus` 被更新为 `'CONSOLIDATED'`;如果你系统中定义为数值(比如 1),请修改条件。 - 如果还需要区分货币型与非货币型,可额外在 WHERE 子句中添加 `AND isMonetaryFund = 1` 或 `= 0`。 --- ### 2. 根据合单后的集合订单,验证客户订单汇总是否与集合订单记录一致 在合单任务中,会生成一条集合订单记录(表 `t_wealth_nominee_order`),其中存储了该批客户订单的汇总数据(例如 `applyAmount`、`applyQuantity`)。同时,每笔关联的客户订单其 `NomineeOrderId` 指向该集合订单。检查时可以将两边对比,示例 SQL 如下: ```sql:sql/check_nominee_order_consistency.sql -- [CheckNomineeOrderConsistency] -- 按当天生成的集合订单,验证关联的客户订单数量及汇总数据是否与集合订单中记录一致 SELECT n.Id AS consolidated_id, n.OrderNumber AS consolidated_order_number, COUNT(o.Id) AS client_order_count, COALESCE(SUM(o.applyAmount), 0) AS total_client_apply_amount, COALESCE(SUM(o.applyQuantity), 0) AS total_client_apply_quantity, n.applyAmount AS consolidated_apply_amount, n.applyQuantity AS consolidated_apply_quantity FROM t_wealth_nominee_order n JOIN t_wealth_order o ON o.NomineeOrderId = n.Id WHERE DATE(n.SubmitTime) = CURDATE() GROUP BY n.Id, n.OrderNumber, n.applyAmount, n.applyQuantity; ``` **说明** - 这里过滤出当天生成的集合订单(通常使用 `SubmitTime` 字段记录提交时间),再通过 JOIN 关联这些集合订单对应的客户订单。 - 对比集合订单内保存的 `applyAmount`/`applyQuantity` 信息和所有客户订单的汇总结果,从而验证合单过程数据是否一致。 --- ### 总结 由于定时任务执行的时机在合单任务之后,客户订单的状态均已更新为合单后的状态,所以检查 SQL 的条件也应相应调整: - 用合单后的标识(例如 `RofNomineeOrderStatus = 'CONSOLIDATED'`)替换之前的待合单条件; - 根据当天生成的集合订单,联查对应客户订单并比较累计金额、累计份额以及订单数量是否一致。 通过以上两组 SQL 语句,你可以分别验证: 1. 今日客户订单的汇总数据是否全部被合单; 2. 每个集合订单下关联的客户订单数据是否与该集合订单记录保持一致。 ## 我把合单任务的代码发给你看,你根据这些代码优化一下sql 下面给出优化后的 SQL 示例,这里假设你的数据库表结构与代码一致,主要表为: - **客户订单表**:`t_wealth_order` - 字段: - `applyAmount`(DECIMAL(19,6)) - `applyQuantity`(DECIMAL(19,6)) - `RofNomineeOrderStatus`:合单后更新为某个值(例如代码中用常量 `orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED`,这里示例中取值为 1,可根据实际值调整) - `NomineeOrderId`:非空表示该订单已经被归入某个集合订单 - `createTime`:订单创建时间(可用来确认“今日订单”) - 其它如 `orderStatus`、`canConsolidate`(用来筛选本批需要合单的订单) - **集合订单表**:`t_wealth_nominee_order` - 字段: - `applyAmount`、`applyQuantity`:由待合单的客户订单合计后保存 - `SubmitTime`:由合单任务生成,保存当前时间 - `OrderNumber`、`Id`、`Tag`、`Custodian` 等字段,根据业务需要可能还有其它信息 下面给出两类主要的检查 SQL: --- ### 1. 按“集合订单”查验——对比每个集合订单记录与其下所有客户订单汇总是否一致 合单任务在执行时会将同一组客户订单生成一笔集合订单(同时可能拆分得到多个子集合订单),同时客户订单更新了字段 `NomineeOrderId` 和已合单状态(假设此状态为 1)。因此可以使用下面的 SQL 查询出当天生成的集合订单(通过 `SubmitTime`)以及对应的客户订单累计申请金额、申请份额和订单数量,并与集合订单中的存储值做比对: ```sql:sql/check_nominee_order_consistency.sql -- [CheckNomineeOrderConsistency] -- 此 SQL 将当天(CURDATE())生成的每个集合订单(合单记录)与其关联的客户订单进行汇总比对: SELECT tn.Id AS consolidated_id, tn.OrderNumber AS consolidated_order_number, COUNT(o.Id) AS client_order_count, tn.applyAmount AS nominee_order_total_apply_amount, SUM(o.applyAmount) AS client_orders_total_apply_amount, tn.applyQuantity AS nominee_order_total_apply_quantity, SUM(o.applyQuantity) AS client_orders_total_apply_quantity FROM t_wealth_nominee_order tn JOIN t_wealth_order o ON o.NomineeOrderId = tn.Id WHERE DATE(tn.SubmitTime) = CURDATE() GROUP BY tn.Id, tn.OrderNumber, tn.applyAmount, tn.applyQuantity; ``` **说明** - 此处用 `DATE(tn.SubmitTime) = CURDATE()` 过滤当天生成的集合订单。 - 对于每个集合订单,我们统计了下属客户端订单的数量、累计申请金额及申请份额,并可将其与集合订单自身保存的 `applyAmount` 及 `applyQuantity` 进行对比。 --- ### 2. 检查是否存在遗漏未更新为“合单后”状态的客户订单 因为定时任务执行时,客户订单状态已经都更新为合单后的状态(例如 `RofNomineeOrderStatus = 1`,实际值请根据你系统里的常量调整),因此可以查询当天应合单的数据里是否还存在未更新(例如 `RofNomineeOrderStatus <> 1`)的记录: ```sql:sql/check_unconsolidated_orders.sql -- [CheckUnconsolidatedOrders] -- 查询当天需要合单的客户订单,但状态尚未更新为 Consolidated 的记录个数 SELECT COUNT(*) AS unprocessed_client_orders FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus <> 1; -- 此处假设合单后状态为 1,根据实际情况修改 ``` **说明** - 这里假设当天(根据 `createTime`)原本应合单的订单满足 `orderStatus = 'ACCEPTED'` 与 `canConsolidate = 1`,如果有其他过滤条件请补充。 - 如果返回 0,则表示所有应合单的客户订单已经更新为合单后状态。 --- ### 注意事项 1. **状态值的判断** 根据代码,在执行合单时会调用 ```go order.RofNomineeOrderStatus = orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED ``` 你需要确保 SQL 文中使用的判断值(此处示例用 1)与实际数据库中更新的数值一致。 2. **日期字段的选用** 集合订单使用 `SubmitTime` 记录提交时间(合单生成时间),而客户订单可使用 `createTime`(下单时间)或者其他业务约定的时间字段,根据你统计的粒度选择合适的时间过滤条件。 3. **数据类型** 由于 `applyAmount` 与 `applyQuantity` 都为 DECIMAL(19,6),在 SQL 运算中直接使用聚合函数(SUM)即可,无需额外转换。 4. **其它筛选条件** 如果你的业务中需要区分货币型与非货币型基金(例如通过字段 `isMonetaryFund` 或产品类型判断),请在 WHERE 子句中相应地加上 `AND isMonetaryFund = 1` 或 `AND isMonetaryFund = 0` 等条件。 --- 以上两组 SQL 就是根据合单任务逻辑(见 `ConsolidateOrderWorker.Run` 及其调用的拆单、写库逻辑)优化后的检查脚本。通过这两组查询可以分别: - 对比集合订单记录与汇总的客户端订单数据是否一致 - 检查当天是否存在遗漏未合单的客户订单 请根据你项目中实际字段名以及状态值做适当调整。 ## 这样不行吧,万一合单任务遗漏订单,重复计算某个订单了,这个sql能对比查出来吗?另外都是用驼峰命令。另外请问这个订单为什么没有合单? 5580 FXCS20230424000048 b556a94e-5f92-46d2-a98a-1c4a7628b788 1003097 226 16727 888620084 10014129530 发个不会 9 易方达(香港)港元货币市场基金 mf0P0001HHM8 HK0000499787 0 0 1.000000 HK0000499787 2 HKD 5458.180000 52.312000 104.339000 5458.180000 5458.180000 0.000000 0.000000 200 2023-04-24 14:42:51 2024-12-30 15:28:56 2023-04-24 14:42:51.157 2024-12-30 15:28:56.188 8e7a569b3712582b8a192e0a12be539a 高志华 5458.180000 5458.180000 0.000000 0 1 0 0 1 0 0 0 0 0 2023-04-24 14:42:51.048 0 0 0 0 0 0 0 0 0 0 0 100 0 100 0 0 1 0 1 下面给出一个优化后的检查 SQL 示例,这个 SQL 脚本设计的思路是同时对比合单后生成的“集合订单”(NomineeOrder)表与它所关联的客户订单(Order)明细,从而能发现如下两种问题: 1. 如果合单任务遗漏了部分客户订单,即有一些应合单的订单没有被更新(或被分配到任何集合订单中),可以通过对比当天订单的汇总数与集合订单汇总数据发现不一致; 2. 如果因为逻辑疏漏导致某个客户订单被重复计入合单(例如在多个集合订单中出现),也会导致汇总“订单金额/份额”与集合订单存储的数据不匹配,从而暴露异常。 另外,这里所有字段名统一使用驼峰命名(例如 createTime、applyAmount、nomineeOrderId、submitTime 等)。 下面给出两部分 SQL: --- ### 1. 汇总比较 SQL 该 SQL 同时聚合了当天所有已合单的客户订单和当天生成的集合订单数据。对于客户订单,我们仅统计那些 nomineeOrderId 非空、且 rofNomineeOrderStatus 表示已合单(例如这里假设其值为 'CONSOLIDATED')的订单,保证只有已经被合单过的订单参与统计。如果合单任务遗漏或重复计入订单,下面的结果就会出现不一致。 ```sql:sql/compareConsolidation.sql -- [CompareConsolidationTotals] -- 左侧子查询聚合客户订单(明细)的累计数据; -- 右侧子查询聚合集合订单(合单)保存的数据。 SELECT (SELECT COUNT(1) FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND nomineeOrderId IS NOT NULL AND rofNomineeOrderStatus = 'CONSOLIDATED' ) AS ordersCount, (SELECT COUNT(1) FROM t_wealth_nominee_order WHERE DATE(submitTime) = CURDATE() ) AS nomineeOrdersCount, (SELECT COALESCE(SUM(applyAmount), 0) FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND nomineeOrderId IS NOT NULL AND rofNomineeOrderStatus = 'CONSOLIDATED' ) AS ordersTotalApplyAmount, (SELECT COALESCE(SUM(applyAmount), 0) FROM t_wealth_nominee_order WHERE DATE(submitTime) = CURDATE() ) AS nomineeOrdersTotalApplyAmount, (SELECT COALESCE(SUM(applyQuantity), 0) FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND nomineeOrderId IS NOT NULL AND rofNomineeOrderStatus = 'CONSOLIDATED' ) AS ordersTotalApplyQuantity, (SELECT COALESCE(SUM(applyQuantity), 0) FROM t_wealth_nominee_order WHERE DATE(submitTime) = CURDATE() ) AS nomineeOrdersTotalApplyQuantity; ``` **说明:** - 这里假设“合单后”的状态值为 `'CONSOLIDATED'`(如果实际是数字,如 1,请自行替换); - 如果统计结果中订单数量或金额/份额累计不匹配,就说明合单任务可能遗漏了部分订单或在某个集合中重复计入了订单。 --- ### 2. 分集合订单的明细核对 SQL 该 SQL 按每个集合订单(NomineeOrder)对其关联的客户订单进行聚合对比,能够明确定位出哪一笔集合订单的累计数据与明细数据不一致。 ```sql:sql/compareNomineeOrderDetail.sql -- [CompareNomineeOrderDetail] -- 该 SQL 将当天生成的各个集合订单(根据 submitTime 筛选)与其所有归属的客户订单进行聚合, -- 进而对比数据库中集合订单保存的累计数据与客户订单的实际累计数据是否一致。 SELECT n.id AS nomineeOrderId, n.orderNumber AS nomineeOrderNumber, COUNT(o.id) AS orderCount, n.applyAmount AS nomineeApplyAmount, COALESCE(SUM(o.applyAmount), 0) AS ordersTotalApplyAmount, n.applyQuantity AS nomineeApplyQuantity, COALESCE(SUM(o.applyQuantity), 0) AS ordersTotalApplyQuantity FROM t_wealth_nominee_order n LEFT JOIN t_wealth_order o ON o.nomineeOrderId = n.id WHERE DATE(n.submitTime) = CURDATE() GROUP BY n.id, n.orderNumber, n.applyAmount, n.applyQuantity; ``` **说明:** - 如果某个集合订单下的客户订单累计金额(或份额)与集合订单中记录的不符,就说明这批订单可能重复加载、丢失或部分遗漏更新; - 根据结果可以进一步定位到具体集合订单,检查是否存在重复合单或遗漏问题。 --- ### 关于“订单没有合单”的情况 举例中订单号为 **FXCS20230424000048** 的记录没有被合单。常见原因包括但不限于: 1. **合单逻辑不匹配** 根据合单任务的业务逻辑,订单需要满足一定条件(如订单状态、产品类型、渠道、交易方向等)才能被归入某个集合订单。如果该订单因任一条件不匹配,就不会被纳入合单计算。 2. **基金节假日判断** 代码中对基金节假日进行了判断(例如,若当日为基金节假日,则不执行合单),如果该订单对应的产品在当天存在基金节假日,该订单便不会被合单。 3. **合单任务遗漏** 如果定时任务执行时存在并发或数据漏查的情况,可能出现部分订单遗漏更新的情况。 4. **重复计算的防护** 为防止同一个订单被重复计入不同集合订单,通常合单程序会更新订单的 `nomineeOrderId` 与 `rofNomineeOrderStatus`。如果该更新未成功(例如数据库写入失败或事务回滚),该订单就不会形成有效合单记录。 你可以从这两个 SQL 的对比结果检查当天有哪些订单没有被纳入任何集合订单,或者是哪笔集合订单中累计的订单明细数据不一致。结合业务日志(例如日志中打印的“handle order %s”信息)和数据库字段状态(例如 rofNomineeOrderStatus 是否正确更新),可以进一步定位该订单没有合单的具体原因。 --- ### 总结 - **SQL 检查层面**: 1. 使用聚合查询将当天客户订单(已合单)的累计量与集合订单累计量对比; 2. 按集合订单分组对比详细明细,判断是否存在遗漏或重复计入情况。 - **订单未合单原因**: 根据合单任务代码,未合单可能是因为不满足合单条件(如状态、渠道、节假日判断等)、数据库更新失败或任务遗漏。建议结合业务日志和订单状态字段(如 rofNomineeOrderStatus)进一步排查。 通过以上检查 SQL 和日志分析,你可以更清楚地定位是否存在遗漏或重复合单的情况,并进一步调查订单(如 FXCS20230424000048)为什么没有进入合单流程。 Loading... ## woker.go 在这个合单的work里面,订单从合单前变为合单后,哪些订单数据变更了 下面是合单处理过程中订单状态和数据发生变化的主要点: 1. **新增集合订单记录(TWealthNomineeOrder)** 在合单过程中,会生成一个新的集合订单记录,该记录将不同客户订单中的数据进行聚合,主要包括: - **申请金额(ApplyAmount)**:将各客户订单中的申请金额累加。 - **申请份额(ApplyQuantity)**:将各客户订单中的申请份额累加。 - **费用(Fee)**:各订单费用累加。 - 其他基础信息(如币种、产品代码、产品名称、产品类型、ISIN、交易方向、费率等)也会从其中一笔或聚合后赋值。 此外,还会生成新的**订单号**(通过 `generateNomineeOrderNumber` 函数计算),并设置初始订单状态(例如 `nomineeorderconstant.WealthNomineeOrderStatusWaiting`)。 2. **更新客户订单数据(TWealthOrder)** 对于每笔参与合单的客户订单,在合单成功后会进行如下更新: - **RofNomineeOrderStatus** 更新为合单后的状态(通常为“已合单”状态,对应常量 `orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED`),标识该订单已经被合单处理。 - **NomineeOrderId** 将字段设置为刚生成的集合订单记录的 ID,以建立从客户订单到集合订单的关联关系。 - **ExpectSettleDate** 更新为新计算的预计结算日(调用了 `getExpectSettledDateV3` 考虑基金节假日等因素后得到的结算日期)。 3. **对于赎回订单的特殊处理** - 当赎回订单存在来自多个非主上手的情况时,还可能对集合订单进行**拆分**,生成多个子集合订单。 - 对拆分出来的子集合订单,会单独生成订单号,并设置相应的标记(例如 `NomineeOrderTagTypeSub`),以及设置正确的上手信息(Custodian、CustodianAccountNumber)和运行模式(RunMode)。 不过对于原始的客户订单来说,更新的依然是上面提到的三个字段(订单状态、集合订单ID、预计结算日)。 4. **冻结持仓** 虽然不是直接更新订单字段,但合单过程中还会调用 `batchFrozenCustodianHolding` 方法,通过冻结相应的持仓来保证资金/份额在结算期间不会被重复使用,这也是合单后订单后续处理的重要步骤。 --- **总结:** 从合单前到合单后,主要发生变化的是: - 新增一条集合订单(TWealthNomineeOrder),其数据为来自各客户订单的聚合(申请金额、份额、费用、订单号、订单状态等)。 - 各客户订单(TWealthOrder)更新了三个字段: - **RofNomineeOrderStatus** 置为“已合单”; - **NomineeOrderId** 被设置为新生成的集合订单的 ID; - **ExpectSettleDate** 被更新为合单后的预计结算日。 ## 那请你根据合单work的合单条件,我想写检查的sql来检查今日该合单的订单是否全部都合单了,首先根据合单的条件查询今日应该合单的订单的数量,还要集合出所有总认购金额或者总认购份额,然后再根据合单后的集合订单的订单号搜出所有NomineeOrderId相同的客户订单,对比客户订单数量、总认购金额、总赎回份额是否和对应的集合订单对齐 下面给出一个示例思路和 SQL 检查脚本,假设你的数据表名如下(你可以根据实际情况调整): - 客户订单表:`TWealthOrder` - 合单(集合订单)表:`TWealthNomineeOrder` 在合单流程中,客户订单在合单后会更新如下字段: - 将字段 `RofNomineeOrderStatus` 的值更新为“合单后状态”(本例中我们用字符串 `'CONSOLIDATED'` 表示), - 填写字段 `NomineeOrderId`(指向产生的集合订单记录), - 同时更新预计结算日等字段。 同时,新产生的集合订单中会保存本批次客户订单累计的申请金额(`ApplyAmount`)和申请份额(`ApplyQuantity`)等信息。 下面给出两个步骤的 SQL 检查示例: --- ### 1. 查询今日应该合单的客户订单数量及累计金额/份额 首先根据合单条件(例如:下单日期为当日、订单状态处于合单前状态)查询客户订单数及累计金额/份额。假设有一个字段 `CreationTime` 或 `CreatedAt` 表示订单日期,且合单前订单状态为 `'PENDING'`(或其它条件,请根据实际情况替换),示例如下: ```sql -- 查询今日需要合单的客户订单数量及累计申请金额和申请份额 SELECT COUNT(*) AS TotalOrders, SUM(CAST(ApplyNetAmount AS DECIMAL(20,4))) AS TotalApplyNetAmount, SUM(CAST(ApplyQuantity AS DECIMAL(20,4))) AS TotalApplyQuantity FROM TWealthOrder WHERE DATE(CreationTime) = CURDATE() AND RofNomineeOrderStatus = 'PENDING'; -- 或其它合单前标识 ``` 如果你系统里“待合单”订单的筛选条件除日期和状态外还受其它限制(例如:仅针对货币型/非货币型基金),请在 `WHERE` 子句中补充相应逻辑。 --- ### 2. 根据生成的集合订单,检查对应的客户订单是否准确更新 在合单成功后,每一批(或者每组)客户订单会根据合单类型生成一个(主集合单)合单号,比如字段 `OrderNumber` 以及自动生成的主集合订单的 `Id`。而所有参与合单的客户订单的 `NomineeOrderId` 均指向该生成的集合订单记录。 下面这个 SQL 通过连接 `TWealthOrder` 和 `TWealthNomineeOrder` 表,按每个集合订单进行分组,计算对应客户订单的数量及累计金额/份额,同时将结果与集合订单自身保存的累计信息进行对比: ```sql -- 检查合单后每个集合订单对应的客户订单数量和累计申请金额/份额是否与集合订单中记录的值一致 SELECT n.Id AS ConsolidatedId, n.OrderNumber AS ConsolidatedOrderNumber, COUNT(o.Id) AS ClientOrderCount, SUM(CAST(o.ApplyNetAmount AS DECIMAL(20,4))) AS TotalClientApplyNetAmount, SUM(CAST(o.ApplyQuantity AS DECIMAL(20,4))) AS TotalClientApplyQuantity, n.ApplyAmount AS ConsolidatedApplyAmount, n.ApplyQuantity AS ConsolidatedApplyQuantity FROM TWealthNomineeOrder n JOIN TWealthOrder o ON o.NomineeOrderId = n.Id WHERE DATE(n.SubmitTime) = CURDATE() GROUP BY n.Id, n.OrderNumber, n.ApplyAmount, n.ApplyQuantity; ``` 在上面的 SQL 中: - 我们过滤出今天(`CURDATE()`)生成的集合订单(假设集合订单的提交时间存储在 `SubmitTime` 字段中), - 按集合订单的 `Id` 进行分组,同时聚合统计对应客户订单的数量与累计金额/份额。 对比后你可以判断: - 每个集合订单的累计申请金额(`ConsolidatedApplyAmount`)是否与该分组下各客户订单 `ApplyNetAmount` 的和一致; - 每个集合订单的累计申请份额(`ConsolidatedApplyQuantity`)是否与该分组下各客户订单 `ApplyQuantity` 的和一致; - 如果需要,也可以对每个组的客户订单数量与预期的数量进行比对。 --- ### 3. 补充检查:待合单客户订单检查 如果你还希望确保今日所有应该合单的客户订单都已更新为“合单”状态,即不存在“待合单”的订单,可以执行如下检查: ```sql -- 检查今日待合单但未更新(即状态仍非 'CONSOLIDATED')的客户订单数量 SELECT COUNT(*) AS NotConsolidatedCount FROM TWealthOrder WHERE DATE(CreationTime) = CURDATE() AND RofNomineeOrderStatus != 'CONSOLIDATED'; ``` 返回记录数应该为 0,此即表示今日所有待合单客户订单都已完成合单更新。 --- ### 总结 以上 SQL 脚本就是基于合单 worker 处理的条件: 1. 首先根据下单日期和合单前状态筛选出今日待合单的客户订单,并聚合出总申请金额/份额; 2. 然后通过集合订单(即合单后生成的记录)的订单号(或 ID)找到对应客户订单,并统计每个集合订单下的客户订单数量及累计申请金额/份额,进而和集合订单中保存的值进行对比; 3. 另外也可检查是否存在遗漏未更新为合单的客户订单。 你可以根据实际的字段名和业务逻辑(比如“货币型”与“非货币型”的区分、数值字段的存储类型等)做进一步调整。 ## 合单work的sql在@t\_wealth\_order.go 这段代码里面都有,请你根据我提供的t\_wealth\_orderde的代码,优化上面的sql。另外数据库中申请金额和申请份额的字段定义我也发给你看: \`applyAmount\` decimal(19,6) DEFAULT NULL COMMENT '申请金额',\`applyQuantity\` decimal(19,6) DEFAULT NULL COMMENT '申请份额', 下面给出的优化方案参考了你在 `t_wealth_order.go` 中的查询条件,假设系统中客户订单表为 `t_wealth_order`,合单(集合订单)表为 `t_wealth_nominee_order`。 注意: - 在合单前,合单订单查询条件(以非货币型为例)为: - `orderStatus = <ACCEPTED>` - `canConsolidate = 1` - `RofNomineeOrderStatus = 0` - 并通过产品类型(`productType`)以及货币型标识(`isMonetaryFund`)进行区分。 - 合单后,每笔客户订单会更新: - `RofNomineeOrderStatus`(改为已合单状态,例如非零的常量,如 “CONSOLIDATED”) - 同时将 `NomineeOrderId` 置为对应合单记录的 ID - 数据库中金额和份额字段类型均为 `DECIMAL(19,6)`,因此在 SQL 中可以直接进行数值计算而无需额外转换。 下面提供三个 SQL 查询示例: --- ### 1. 查询今日待合单的客户订单(即还未更新为合单状态)的数量及累计申请金额/申请份额 这里假设当天的客户订单以 `createTime` 记录日期,且合单前状态条件中 `orderStatus = 'ACCEPTED'`(你可替换为实际值)、`canConsolidate = 1`,并且尚未合单(`RofNomineeOrderStatus = 0`)。 ```sql:sql/check_consolidation.sql -- [CheckPendingOrders] -- 查询今日满足合单条件、但未更新为合单状态的客户订单数量以及累计的申请金额和申请份额 SELECT COUNT(*) AS pending_orders, COALESCE(SUM(applyAmount), 0) AS total_pending_apply_amount, COALESCE(SUM(applyQuantity), 0) AS total_pending_apply_quantity FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus = 0; ``` 如果有货币型跟非货币型之分,那么可在 WHERE 中增加: - 对货币型: `AND isMonetaryFund = 1` - 对非货币型: `AND isMonetaryFund = 0` --- ### 2. 根据合单后的集合订单,统计各个集合订单下关联的客户订单数量及累计申请金额/申请份额 该 SQL 通过 `t_wealth_nominee_order`(合单表)的提交时间(字段 `SubmitTime`)过滤当天生成的集合订单,然后连接客户订单表(通过字段 `NomineeOrderId`),按每个合单聚合统计对应的客户订单数据。 ```sql:sql/check_consolidation.sql -- [CheckConsolidatedOrders] -- 检查当天生成的每个集合订单(合单后的订单),并统计其下关联的客户订单的数量、累计申请金额和累计申请份额 SELECT n.Id AS consolidated_id, n.OrderNumber AS consolidated_order_number, COUNT(o.Id) AS client_order_count, COALESCE(SUM(o.applyAmount), 0) AS total_client_apply_amount, COALESCE(SUM(o.applyQuantity), 0) AS total_client_apply_quantity, n.applyAmount AS consolidated_apply_amount, n.applyQuantity AS consolidated_apply_quantity FROM t_wealth_nominee_order n JOIN t_wealth_order o ON o.NomineeOrderId = n.Id WHERE DATE(n.SubmitTime) = CURDATE() GROUP BY n.Id, n.OrderNumber, n.applyAmount, n.applyQuantity; ``` 通过上述查询,你可以对比每个集合订单(合单记录)中保存的 `applyAmount`/`applyQuantity` 与其下所有客户订单累计值是否一致,从而判断合单过程是否正确。 --- ### 3. 检查是否存在遗漏未合单的客户订单 最终,你可以再执行以下 SQL,确认今日所有应合单的客户订单均已更新(即没有仍处于待合单状态的记录): ```sql:sql/check_consolidation.sql -- [CheckAllOrdersConsolidated] -- 确认当天没有遗漏未合单的客户订单 SELECT COUNT(*) AS un_consolidated_count FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus = 0; ``` 返回的 `un_consolidated_count` 应为 0,否则说明还有未被合单处理的客户订单。 --- ### 总结 以上 SQL 脚本均参考了 `t_wealth_order.go` 中的查询条件并结合了数据库中 `applyAmount` 与 `applyQuantity` 字段的定义进行优化。 你可以根据业务的货币型/非货币型区分,在对应的 WHERE 子句中增加对 `isMonetaryFund` 或 `productType` 的判断条件,从而满足更加精细的检查需要。 ## 我突然意识到一个问题,我这个定时任务是在合单定时任务后面执行的,这个时候订单的状态都已经变了 下面的方案考虑到了定时任务执行时,所有客户订单已经从合单前(例如 `RofNomineeOrderStatus = 0`)更新为了合单后的状态(例如更新为 `CONSOLIDATED`,你可以根据实际定义替换条件),从而需要使用新状态进行检查。下面给出两组优化后的 SQL 语句示例: --- ### 1. 检查今日所有应合单客户订单的汇总数据 由于合单任务执行后,客户订单已经更新,即: - `orderStatus` 正常(例如 `'ACCEPTED'`) - `canConsolidate = 1` - `RofNomineeOrderStatus` 已更新为合单后的状态(例如 `'CONSOLIDATED'` 或对应数值) 因此,原先检查【待合单】的 SQL 条件应调整为使用合单后状态。例如: ```sql:sql/check_consolidated_orders.sql -- [CheckConsolidatedClientOrders] -- 查询今日已合单客户订单数量及累计申请金额/申请份额 SELECT COUNT(*) AS consolidated_orders, COALESCE(SUM(applyAmount), 0) AS total_consolidated_apply_amount, COALESCE(SUM(applyQuantity), 0) AS total_consolidated_apply_quantity FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus = 'CONSOLIDATED'; -- 此处请用实际的已合单标识(如果是数值,则改为相应数字) ``` **说明** - 注意这里假设合单后订单的 `RofNomineeOrderStatus` 被更新为 `'CONSOLIDATED'`;如果你系统中定义为数值(比如 1),请修改条件。 - 如果还需要区分货币型与非货币型,可额外在 WHERE 子句中添加 `AND isMonetaryFund = 1` 或 `= 0`。 --- ### 2. 根据合单后的集合订单,验证客户订单汇总是否与集合订单记录一致 在合单任务中,会生成一条集合订单记录(表 `t_wealth_nominee_order`),其中存储了该批客户订单的汇总数据(例如 `applyAmount`、`applyQuantity`)。同时,每笔关联的客户订单其 `NomineeOrderId` 指向该集合订单。检查时可以将两边对比,示例 SQL 如下: ```sql:sql/check_nominee_order_consistency.sql -- [CheckNomineeOrderConsistency] -- 按当天生成的集合订单,验证关联的客户订单数量及汇总数据是否与集合订单中记录一致 SELECT n.Id AS consolidated_id, n.OrderNumber AS consolidated_order_number, COUNT(o.Id) AS client_order_count, COALESCE(SUM(o.applyAmount), 0) AS total_client_apply_amount, COALESCE(SUM(o.applyQuantity), 0) AS total_client_apply_quantity, n.applyAmount AS consolidated_apply_amount, n.applyQuantity AS consolidated_apply_quantity FROM t_wealth_nominee_order n JOIN t_wealth_order o ON o.NomineeOrderId = n.Id WHERE DATE(n.SubmitTime) = CURDATE() GROUP BY n.Id, n.OrderNumber, n.applyAmount, n.applyQuantity; ``` **说明** - 这里过滤出当天生成的集合订单(通常使用 `SubmitTime` 字段记录提交时间),再通过 JOIN 关联这些集合订单对应的客户订单。 - 对比集合订单内保存的 `applyAmount`/`applyQuantity` 信息和所有客户订单的汇总结果,从而验证合单过程数据是否一致。 --- ### 总结 由于定时任务执行的时机在合单任务之后,客户订单的状态均已更新为合单后的状态,所以检查 SQL 的条件也应相应调整: - 用合单后的标识(例如 `RofNomineeOrderStatus = 'CONSOLIDATED'`)替换之前的待合单条件; - 根据当天生成的集合订单,联查对应客户订单并比较累计金额、累计份额以及订单数量是否一致。 通过以上两组 SQL 语句,你可以分别验证: 1. 今日客户订单的汇总数据是否全部被合单; 2. 每个集合订单下关联的客户订单数据是否与该集合订单记录保持一致。 ## 我把合单任务的代码发给你看,你根据这些代码优化一下sql 下面给出优化后的 SQL 示例,这里假设你的数据库表结构与代码一致,主要表为: - **客户订单表**:`t_wealth_order` - 字段: - `applyAmount`(DECIMAL(19,6)) - `applyQuantity`(DECIMAL(19,6)) - `RofNomineeOrderStatus`:合单后更新为某个值(例如代码中用常量 `orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED`,这里示例中取值为 1,可根据实际值调整) - `NomineeOrderId`:非空表示该订单已经被归入某个集合订单 - `createTime`:订单创建时间(可用来确认“今日订单”) - 其它如 `orderStatus`、`canConsolidate`(用来筛选本批需要合单的订单) - **集合订单表**:`t_wealth_nominee_order` - 字段: - `applyAmount`、`applyQuantity`:由待合单的客户订单合计后保存 - `SubmitTime`:由合单任务生成,保存当前时间 - `OrderNumber`、`Id`、`Tag`、`Custodian` 等字段,根据业务需要可能还有其它信息 下面给出两类主要的检查 SQL: --- ### 1. 按“集合订单”查验——对比每个集合订单记录与其下所有客户订单汇总是否一致 合单任务在执行时会将同一组客户订单生成一笔集合订单(同时可能拆分得到多个子集合订单),同时客户订单更新了字段 `NomineeOrderId` 和已合单状态(假设此状态为 1)。因此可以使用下面的 SQL 查询出当天生成的集合订单(通过 `SubmitTime`)以及对应的客户订单累计申请金额、申请份额和订单数量,并与集合订单中的存储值做比对: ```sql:sql/check_nominee_order_consistency.sql -- [CheckNomineeOrderConsistency] -- 此 SQL 将当天(CURDATE())生成的每个集合订单(合单记录)与其关联的客户订单进行汇总比对: SELECT tn.Id AS consolidated_id, tn.OrderNumber AS consolidated_order_number, COUNT(o.Id) AS client_order_count, tn.applyAmount AS nominee_order_total_apply_amount, SUM(o.applyAmount) AS client_orders_total_apply_amount, tn.applyQuantity AS nominee_order_total_apply_quantity, SUM(o.applyQuantity) AS client_orders_total_apply_quantity FROM t_wealth_nominee_order tn JOIN t_wealth_order o ON o.NomineeOrderId = tn.Id WHERE DATE(tn.SubmitTime) = CURDATE() GROUP BY tn.Id, tn.OrderNumber, tn.applyAmount, tn.applyQuantity; ``` **说明** - 此处用 `DATE(tn.SubmitTime) = CURDATE()` 过滤当天生成的集合订单。 - 对于每个集合订单,我们统计了下属客户端订单的数量、累计申请金额及申请份额,并可将其与集合订单自身保存的 `applyAmount` 及 `applyQuantity` 进行对比。 --- ### 2. 检查是否存在遗漏未更新为“合单后”状态的客户订单 因为定时任务执行时,客户订单状态已经都更新为合单后的状态(例如 `RofNomineeOrderStatus = 1`,实际值请根据你系统里的常量调整),因此可以查询当天应合单的数据里是否还存在未更新(例如 `RofNomineeOrderStatus <> 1`)的记录: ```sql:sql/check_unconsolidated_orders.sql -- [CheckUnconsolidatedOrders] -- 查询当天需要合单的客户订单,但状态尚未更新为 Consolidated 的记录个数 SELECT COUNT(*) AS unprocessed_client_orders FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND orderStatus = 'ACCEPTED' AND canConsolidate = 1 AND RofNomineeOrderStatus <> 1; -- 此处假设合单后状态为 1,根据实际情况修改 ``` **说明** - 这里假设当天(根据 `createTime`)原本应合单的订单满足 `orderStatus = 'ACCEPTED'` 与 `canConsolidate = 1`,如果有其他过滤条件请补充。 - 如果返回 0,则表示所有应合单的客户订单已经更新为合单后状态。 --- ### 注意事项 1. **状态值的判断** 根据代码,在执行合单时会调用 ```go order.RofNomineeOrderStatus = orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED ``` 你需要确保 SQL 文中使用的判断值(此处示例用 1)与实际数据库中更新的数值一致。 2. **日期字段的选用** 集合订单使用 `SubmitTime` 记录提交时间(合单生成时间),而客户订单可使用 `createTime`(下单时间)或者其他业务约定的时间字段,根据你统计的粒度选择合适的时间过滤条件。 3. **数据类型** 由于 `applyAmount` 与 `applyQuantity` 都为 DECIMAL(19,6),在 SQL 运算中直接使用聚合函数(SUM)即可,无需额外转换。 4. **其它筛选条件** 如果你的业务中需要区分货币型与非货币型基金(例如通过字段 `isMonetaryFund` 或产品类型判断),请在 WHERE 子句中相应地加上 `AND isMonetaryFund = 1` 或 `AND isMonetaryFund = 0` 等条件。 --- 以上两组 SQL 就是根据合单任务逻辑(见 `ConsolidateOrderWorker.Run` 及其调用的拆单、写库逻辑)优化后的检查脚本。通过这两组查询可以分别: - 对比集合订单记录与汇总的客户端订单数据是否一致 - 检查当天是否存在遗漏未合单的客户订单 请根据你项目中实际字段名以及状态值做适当调整。 ## 这样不行吧,万一合单任务遗漏订单,重复计算某个订单了,这个sql能对比查出来吗?另外都是用驼峰命令。另外请问这个订单为什么没有合单? 5580 FXCS20230424000048 b556a94e-5f92-46d2-a98a-1c4a7628b788 1003097 226 16727 888620084 10014129530 发个不会 9 易方达(香港)港元货币市场基金 mf0P0001HHM8 HK0000499787 0 0 1.000000 HK0000499787 2 HKD 5458.180000 52.312000 104.339000 5458.180000 5458.180000 0.000000 0.000000 200 2023-04-24 14:42:51 2024-12-30 15:28:56 2023-04-24 14:42:51.157 2024-12-30 15:28:56.188 8e7a569b3712582b8a192e0a12be539a 高志华 5458.180000 5458.180000 0.000000 0 1 0 0 1 0 0 0 0 0 2023-04-24 14:42:51.048 0 0 0 0 0 0 0 0 0 0 0 100 0 100 0 0 1 0 1 下面给出一个优化后的检查 SQL 示例,这个 SQL 脚本设计的思路是同时对比合单后生成的“集合订单”(NomineeOrder)表与它所关联的客户订单(Order)明细,从而能发现如下两种问题: 1. 如果合单任务遗漏了部分客户订单,即有一些应合单的订单没有被更新(或被分配到任何集合订单中),可以通过对比当天订单的汇总数与集合订单汇总数据发现不一致; 2. 如果因为逻辑疏漏导致某个客户订单被重复计入合单(例如在多个集合订单中出现),也会导致汇总“订单金额/份额”与集合订单存储的数据不匹配,从而暴露异常。 另外,这里所有字段名统一使用驼峰命名(例如 createTime、applyAmount、nomineeOrderId、submitTime 等)。 下面给出两部分 SQL: --- ### 1. 汇总比较 SQL 该 SQL 同时聚合了当天所有已合单的客户订单和当天生成的集合订单数据。对于客户订单,我们仅统计那些 nomineeOrderId 非空、且 rofNomineeOrderStatus 表示已合单(例如这里假设其值为 'CONSOLIDATED')的订单,保证只有已经被合单过的订单参与统计。如果合单任务遗漏或重复计入订单,下面的结果就会出现不一致。 ```sql:sql/compareConsolidation.sql -- [CompareConsolidationTotals] -- 左侧子查询聚合客户订单(明细)的累计数据; -- 右侧子查询聚合集合订单(合单)保存的数据。 SELECT (SELECT COUNT(1) FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND nomineeOrderId IS NOT NULL AND rofNomineeOrderStatus = 'CONSOLIDATED' ) AS ordersCount, (SELECT COUNT(1) FROM t_wealth_nominee_order WHERE DATE(submitTime) = CURDATE() ) AS nomineeOrdersCount, (SELECT COALESCE(SUM(applyAmount), 0) FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND nomineeOrderId IS NOT NULL AND rofNomineeOrderStatus = 'CONSOLIDATED' ) AS ordersTotalApplyAmount, (SELECT COALESCE(SUM(applyAmount), 0) FROM t_wealth_nominee_order WHERE DATE(submitTime) = CURDATE() ) AS nomineeOrdersTotalApplyAmount, (SELECT COALESCE(SUM(applyQuantity), 0) FROM t_wealth_order WHERE DATE(createTime) = CURDATE() AND nomineeOrderId IS NOT NULL AND rofNomineeOrderStatus = 'CONSOLIDATED' ) AS ordersTotalApplyQuantity, (SELECT COALESCE(SUM(applyQuantity), 0) FROM t_wealth_nominee_order WHERE DATE(submitTime) = CURDATE() ) AS nomineeOrdersTotalApplyQuantity; ``` **说明:** - 这里假设“合单后”的状态值为 `'CONSOLIDATED'`(如果实际是数字,如 1,请自行替换); - 如果统计结果中订单数量或金额/份额累计不匹配,就说明合单任务可能遗漏了部分订单或在某个集合中重复计入了订单。 --- ### 2. 分集合订单的明细核对 SQL 该 SQL 按每个集合订单(NomineeOrder)对其关联的客户订单进行聚合对比,能够明确定位出哪一笔集合订单的累计数据与明细数据不一致。 ```sql:sql/compareNomineeOrderDetail.sql -- [CompareNomineeOrderDetail] -- 该 SQL 将当天生成的各个集合订单(根据 submitTime 筛选)与其所有归属的客户订单进行聚合, -- 进而对比数据库中集合订单保存的累计数据与客户订单的实际累计数据是否一致。 SELECT n.id AS nomineeOrderId, n.orderNumber AS nomineeOrderNumber, COUNT(o.id) AS orderCount, n.applyAmount AS nomineeApplyAmount, COALESCE(SUM(o.applyAmount), 0) AS ordersTotalApplyAmount, n.applyQuantity AS nomineeApplyQuantity, COALESCE(SUM(o.applyQuantity), 0) AS ordersTotalApplyQuantity FROM t_wealth_nominee_order n LEFT JOIN t_wealth_order o ON o.nomineeOrderId = n.id WHERE DATE(n.submitTime) = CURDATE() GROUP BY n.id, n.orderNumber, n.applyAmount, n.applyQuantity; ``` **说明:** - 如果某个集合订单下的客户订单累计金额(或份额)与集合订单中记录的不符,就说明这批订单可能重复加载、丢失或部分遗漏更新; - 根据结果可以进一步定位到具体集合订单,检查是否存在重复合单或遗漏问题。 --- ### 关于“订单没有合单”的情况 举例中订单号为 **FXCS20230424000048** 的记录没有被合单。常见原因包括但不限于: 1. **合单逻辑不匹配** 根据合单任务的业务逻辑,订单需要满足一定条件(如订单状态、产品类型、渠道、交易方向等)才能被归入某个集合订单。如果该订单因任一条件不匹配,就不会被纳入合单计算。 2. **基金节假日判断** 代码中对基金节假日进行了判断(例如,若当日为基金节假日,则不执行合单),如果该订单对应的产品在当天存在基金节假日,该订单便不会被合单。 3. **合单任务遗漏** 如果定时任务执行时存在并发或数据漏查的情况,可能出现部分订单遗漏更新的情况。 4. **重复计算的防护** 为防止同一个订单被重复计入不同集合订单,通常合单程序会更新订单的 `nomineeOrderId` 与 `rofNomineeOrderStatus`。如果该更新未成功(例如数据库写入失败或事务回滚),该订单就不会形成有效合单记录。 你可以从这两个 SQL 的对比结果检查当天有哪些订单没有被纳入任何集合订单,或者是哪笔集合订单中累计的订单明细数据不一致。结合业务日志(例如日志中打印的“handle order %s”信息)和数据库字段状态(例如 rofNomineeOrderStatus 是否正确更新),可以进一步定位该订单没有合单的具体原因。 --- ### 总结 - **SQL 检查层面**: 1. 使用聚合查询将当天客户订单(已合单)的累计量与集合订单累计量对比; 2. 按集合订单分组对比详细明细,判断是否存在遗漏或重复计入情况。 - **订单未合单原因**: 根据合单任务代码,未合单可能是因为不满足合单条件(如状态、渠道、节假日判断等)、数据库更新失败或任务遗漏。建议结合业务日志和订单状态字段(如 rofNomineeOrderStatus)进一步排查。 通过以上检查 SQL 和日志分析,你可以更清楚地定位是否存在遗漏或重复合单的情况,并进一步调查订单(如 FXCS20230424000048)为什么没有进入合单流程。 最后修改:2025 年 02 月 19 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏