阅读这段代码:
// 子集合订单生成OrderNumber
for i := range subOrderList {
var subOrderNumberNo int
subOrderNumberNo, err = dao.Dao.Access.GenIdNo(nil, pkgconstant.T_ID_TYPE_WEALTH_NOMINEE_ORDER_RULE1_CHAR)
if err != nil {
log.Errorf(err.Error())
return err
}
subOrderList[i].OrderNumber = generateNomineeOrderNumber(subOrderNumberNo, nomineeOrder.OrderType)
}

// todo 只有一个
nomineeSubOrderList := append(subOrderList, *nomineeOrder)
if err = s.iFastOrderWarn(ctx, nomineeSubOrderList); err != nil {
    log.Error(err.Error())
    return err
}

err = mysql.WithContext(ctx, dao.Dao.Basedb).Transaction(func(tx *gorm.DB) error {
    if len(subOrderList) > 0 {
        err = tx.Create(subOrderList).Error
        if err != nil {
            return err
        }
    }

    err = tx.Create(nomineeOrder).Error
    if err != nil {
        return err
    }

    err = batchFrozenCustodianHolding(ctx, tx, nomineeSubOrderList)
    if err != nil {
        return err
    }

    // 更新子订单信息和状态等
    subOrders := consolidateOrder.Orders
    for _, id := range subOrders {
        order := new(model.TWealthOrder)
        order.Id = id
        order.RofNomineeOrderStatus = orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED
        order.NomineeOrderId = nomineeOrder.Id
        order.ExpectSettleDate = nomineeOrder.ExpectSettleDate // 预计结算日
        err = tx.Updates(order).Error
        if err != nil {
            break
        }
    }
    return nil
})

这段代码主要负责生成子订单的订单号,处理预警,事务处理包括创建子订单和主订单,冻结托管持有,并更新子订单的信息和状态。

下面是代码的逐步解释:

  1. 生成子订单订单号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    for i := range subOrderList {
    var subOrderNumberNo int
    subOrderNumberNo, err = dao.Dao.Access.GenIdNo(nil, pkgconstant.T_ID_TYPE_WEALTH_NOMINEE_ORDER_RULE1_CHAR)
    if err != nil {
    log.Errorf(err.Error())
    return err
    }
    subOrderList[i].OrderNumber = generateNomineeOrderNumber(subOrderNumberNo, nomineeOrder.OrderType)
    }

    这部分代码遍历 subOrderList,为每个子订单生成一个唯一的订单号。如果生成订单号时发生错误,会记录错误日志并返回错误。

  2. 预警处理

    1
    2
    3
    4
    5
    nomineeSubOrderList := append(subOrderList, *nomineeOrder)
    if err = s.iFastOrderWarn(ctx, nomineeSubOrderList); err != nil {
    log.Error(err.Error())
    return err
    }

    将主订单 nomineeOrder 添加到 subOrderList 中形成 nomineeSubOrderList,然后进行预警处理。如果预警处理失败,会记录错误并返回错误。

  3. 事务处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    err = mysql.WithContext(ctx, dao.Dao.Basedb).Transaction(func(tx *gorm.DB) error {
    if len(subOrderList) > 0 {
    err = tx.Create(subOrderList).Error
    if err != nil {
    return err
    }
    }

    err = tx.Create(nomineeOrder).Error
    if err != nil {
    return err
    }

    err = batchFrozenCustodianHolding(ctx, tx, nomineeSubOrderList)
    if err != nil {
    return err
    }

    subOrders := consolidateOrder.Orders
    for _, id := range subOrders {
    order := new(model.TWealthOrder)
    order.Id = id
    order.RofNomineeOrderStatus = orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED
    order.NomineeOrderId = nomineeOrder.Id
    order.ExpectSettleDate = nomineeOrder.ExpectSettleDate
    err = tx.Updates(order).Error
    if (err != nil) {
    break
    }
    }
    return nil
    })

    在事务中进行以下操作:

    • 如果有子订单,批量创建这些子订单。
    • 创建主订单。
    • 批量冻结托管持有。
    • 更新子订单的信息和状态,包括订单状态、关联的主订单ID和预计结算日。如果在更新过程中发生错误,事务会中断并回滚。

总之,这段代码涉及订单处理的多个步骤,包括生成订单号、预警处理、事务性的数据写入操作,确保数据的一致性和完整性。

——来自AI问答宝 https://ai.wendabao.net

假如现在nomineeOrder只有一份,还有必要append进nomineeSubOrderList里面吗?

如果 nomineeOrder 只有一份,而 nomineeSubOrderList 是专门用于包含多个子订单和主订单的组合列表,那么为了保持代码的一致性和灵活性,还是有必要将 nomineeOrder 添加进 nomineeSubOrderList 中。这样做的好处是即使 nomineeOrder 只有一个,代码仍然可以处理其他情况下可能存在的多个子订单的情况。

不过,如果你确定在你的应用场景中 nomineeOrder 永远只有一个,并且没有必要将其添加到 nomineeSubOrderList 中,可以做如下修改:

  1. 直接传递 subOrderListnomineeOrder 分别给预警处理函数和事务处理函数。
  2. 在事务处理部分,只处理 subOrderListnomineeOrder,而不是 nomineeSubOrderList

下面是修改后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 子集合订单生成OrderNumber
for i := range subOrderList {
var subOrderNumberNo int
subOrderNumberNo, err = dao.Dao.Access.GenIdNo(nil, pkgconstant.T_ID_TYPE_WEALTH_NOMINEE_ORDER_RULE1_CHAR)
if err != nil {
log.Errorf(err.Error())
return err
}
subOrderList[i].OrderNumber = generateNomineeOrderNumber(subOrderNumberNo, nomineeOrder.OrderType)
}

// 预警处理只传递subOrderList和nomineeOrder
if err = s.iFastOrderWarn(ctx, append(subOrderList, *nomineeOrder)); err != nil {
log.Error(err.Error())
return err
}

err = mysql.WithContext(ctx, dao.Dao.Basedb).Transaction(func(tx *gorm.DB) error {
if len(subOrderList) > 0 {
err = tx.Create(subOrderList).Error
if err != nil {
return err
}
}

err = tx.Create(nomineeOrder).Error
if err != nil {
return err
}

// 冻结托管持有处理subOrderList和nomineeOrder
if err = batchFrozenCustodianHolding(ctx, tx, append(subOrderList, *nomineeOrder)); err != nil {
return err
}

// 更新子订单信息和状态等
subOrders := consolidateOrder.Orders
for _, id := range subOrders {
order := new(model.TWealthOrder)
order.Id = id
order.RofNomineeOrderStatus = orderconstant.W_ORDER_ROFNOMINEEORDERSTATUS_CONSOLIDATED
order.NomineeOrderId = nomineeOrder.Id
order.ExpectSettleDate = nomineeOrder.ExpectSettleDate // 预计结算日
err = tx.Updates(order).Error
if err != nil {
break
}
}
return nil
})

这样改动的主要部分是:

  • nomineeOrder 直接传递给 iFastOrderWarnbatchFrozenCustodianHolding
  • 在事务处理函数中,分别处理 subOrderListnomineeOrder

这种修改会使代码更简洁一些,但前提是你确定 nomineeOrder 永远只有一个。如果有可能出现多个子订单的情况,保留原有的组合列表处理方式会更好。

——来自AI问答宝 https://ai.wendabao.net