画布 1
交易系统
  前台层
    toC 系统
      可以提供一些业务能力/平台能力抽象，对非标订单而不能生成子列/子订单表的时候，使用 attribute
      根据支付场景确定具体属性
      注意这个模型和 order 的关系，要么有序号，要么有 requestid，要么有时间顺序。否则要考虑是不是多对一还是一对一。如果有设计约束上的强要求，才需要设计强一对一，强一对一只要设计一个 unique 的业务 fk 即可。
      简单模型的状态机可以使用 status_time，如果有复杂状态多次跃迁，则必须产生这种 log。
如果还有必要要生成 entity change log 而不只是 status log。有 log 的时候最好还要配上一个 version，甚至 logid
      警惕这个模型，注意它作为事务子表的作用，要看清楚支付是合单支付还是拆单支付的，要看它关联的事务是主事务还是子事务
      这个模型是记台账模型，是为了支撑 refund_record
      在做远近端请求的时候可以单独设计 log，也可以把部分错误信息记在 fund_instruct 之类的模型里
      order
        id
          autoincrement 小心 Java 类型和 db 类型不匹配
        order_id
          如果可以全局唯一，则可以用 order_id 去写 id，这样有天合并 db 或者使用 newSql 的时候不会产生唯一性冲突
        order_type
          商品类型的原信息，如保险产品或者 commodity
        user_type
        user_id
        order_channel
          上游来源，多渠道、多页面、分析销售漏斗必备，如果有必要还要可以细分业务线、app，枚举易造成混乱
        下层 orderid
          远端句柄冗余，要建索引
一个交易里面，只要主交易或者主句柄持有这种 id 即可，如果其他模型也持有这种 id，主要是为了便于查询
        payTime
        suspension_time
          中止时间
        reinstatement_time
          复效时间
        gmt_created
        gmt_modified
          可以加索引，如果查询的时候总能知道大概时间，则 modified_time 总是可以加在 status 前面
        total_干系人_count
        is_display
          订单是否显示
        显示总价
        total_购买_count
          本单的 count
        total_paid_price
          和原价格不一样，是用户实际的资金流里面支付的部分
        pay_record_id
          可以建索引
          注意，这有和 pay_record 是一对一的时候才适合使用，否则这种主控模型设计以后很容易后悔
        uuid
        order_holder
        如果有必要，加入其它事件人
        version
        contact_phone
        discount
          折扣金额
        pay_user_id
          冗余 pay_record 里的信息，便于利用索引查询
        instalment_payment
          是否分期
        status
          WAITING_FOR_PAYMENT("100", "待支付"),
          PAY_TIMEOUT("110", "支付超时"),
            有些订单有，有些订单没有
          CANCELED("120", "已取消"),
            售中取消终态，慎用，要注意和远端事务的互斥，只有调用远端支付服务的查询接口或者由绝对状态机保护的关闭接口以后，才可以进入这个状态
          PAID("140", "已支付"),
            见费出单前置状态
          BUYING("180", "购买中"),
          BUY_FAILED("190", "购买失败"),
          BUY_SUCCESS("200", "购买成功"),
          PARTIAL_BUY_SUCCESS("201", "部分购买成功"),
          SUSPENSION("209", "中止"),
            特殊商品才有的状态
          RETURNING("210", "退货中"),
            这里可以加入退款状态，也可以不加入退款状态，如果不加入退款状态，要有表达退款交易的子事务
          PARTIAL_RETURN_SUCCESS("220", "部分退货成功"),
          RETURN_SUCCESS("250", "全部退货");
        encrypt_way
          有敏感信息的列需要使用这个方法
        encrypt_token
          一个 token 化的示例
        bizTime
          平台型业务如果有必要，也要理解上游业务时间
        混合起来可以表达多种账户体系，要建索引
        事件、状态跃迁冗余
        可以加索引
        预聚合冗余，便于显示，保全等操作需要变更这个属性。对于订单中心、订单列表之类的场景有用
      order_attribute
        id
        user_type
        user_id
        order_id
        attritbute_name
        attribute_value
        attribute_value
        gmt_created
        gmt_modified
        要建索引
      order_return
        id
          autoincrement 小心 Java 类型和 db 类型不匹配
        user_type
        user_id
        order_id
          如果可以全局唯一，则可以用 order_id 去写 id，这样有天合并 db 或者使用 newSql 的时候不会产生唯一性冲突
        gmt_created
          datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        gmt_modified
          datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
        reason
          退单原因
        status
          NEW("100", "新建"),
          RETURNING("180", "退货中"),
          SUCCESS("200", "申请退货全部成功"),
          PARTIAL_SUCCESS("201", "申请退货部分成功"),
          FAIL("300", "申请退货全部失败"),
        下层 orderid
        item_count
          申请退货子单数量
        pay_record_id
          支付单号
        pay_total_price
          支付金额
        return_total_price
          实际退款金额
        refund_id
          退款记录表号
        下层 return_order_id
          退货订单号，对于双层的退货模型，这个号是需要的
        user_type
          user类型 0:平台一般用户 1:商家应用用户
        混合起来可以表达多种账户体系，要建索引
      order_status_change_log
        id
        user_type
        user_id
        order_id
        oldStatus
        newStatus
        gmt_created
        gmt_modified
        要建索引
      pay_record
        id
        user_type
          下游 type，如果下游通知要细分则需要记录这一信息
        user_id
        order_id
        tradeNo
          下游交易号，真正交易系统的交易号，也可以是 transNo
        pay_type
        third_pay_user_id
          第三方支付userId
        status
          WAITING_FOR_PAYMENT("100", "待支付"),
          PAY_TIMEOUT("110", "支付超时"),
          CANCELED("120", "已取消"),
          PAID("140", "已支付"),
          PAY_FAIL("150", "支付失败");
        order_price
          订单总金额
        topay_money
          应支付金额
        discount
          优惠金额
        gmt_created
        gmt_modified
        pay_token
          有些场景下会有，要防止这类 token 泄漏
        pay_time
          支付时间，一次性单据有用，否则要小心 LWW
        pre_trade_no
          预支付tradeNo，有些前端有用-如果有跳转收银台的机制的话
        pay_suc_time
          支付成功时间，回调场景下可能有用
        pay_flow_no
          单次请求流水号
        fromAccount
          出资账户，如果是商家支付则需要考虑多级商户账号系统
        toAccount
          受资账户
        pay_channel
          支付通道，分商家支付、c 端支付、代扣时有用，但这要求上面的账户信息也可以兼容这些配置
        type
          收银台
          代扣
        sub_order_id
          支付相关子订单号 id
        要建索引
        decimal 或者 bigint，注意单位和币种
      withhold_contract
        id
          bigint(20) NOT NULL AUTO_INCREMENT COMMENT
        withhold_agreement
          代扣协议号
        status
          1签约中 2签约成功 3签约失败 4已解约
          签约状态
          int(20) NOT NULL DEFAULT '1'
        pay_type
          代扣账户类型
        order_id
        withhold_paymec_no
          请求授权签约商户ID
        二级商户号
        代扣模板号
        user_type
          下游 type，如果下游通知要细分则需要记录这一信息
        user_id
        gmt_created
        gmt_modified
      withhold_contract_log
        id
        user_id
        contract_status
        error_code
          实际错误码',
        error_msg
          错误信息
        `request_log` text,
        `response_log` text,
        gmt_created
        gmt_modified
      withhold_record
        id
        order_id
        sub_order_id
        trade_no
          受理异步流水号
        pay_type
        status
          100 待扣缴 200扣缴中 300扣缴成功 400扣缴失败
        period_num
          支付期数，这里要引入其他缴费上下文信息亦可
        pay_time
          支付时间
        商户号
        pay_channel
          由下游支付通道决定
        withhold_date
          扣款日期
          这个日期的生成算法要非常仔细
        last_error_code
          最新的错误code',
        last_error_message
          最后的错误信息
        to_pay_money
          支付金额
        pay_token
          带跳转功能的支付通道必定返回的值
        user_id
        order_id
        gmt_created
        gmt_modified
        要建索引
      withhold_record_log
        id
        error_msg
          错误信息
        request_log
          请求日志
        response_log
          text，如果有必要换 long text
          响应日志
        pay_status
          支付状态 100代扣缴 200扣缴中 300扣缴成功 400扣缴失败',
        error_code
          实际错误码
        order_id
        sub_order_id
        gmt_created
        gmt_modified
      withhold_trade_flow
        id
        trade_no
          交易流水号
          varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL
        trade_status
          100 初始 200 成功 300 失败',
          交易状态
        gmt_created
        gmt_modified
        order_id
        sub_order_id
      refund_record
        id
          退款记录表ID
        order_id
          订单ID
        user_id
        trade_no
          支付平台交易号，如果有统一支付平台，它可以提供一个标准的交易号，否则这里可能要做宽支付指令设计
          varchar(50) COLLATE utf8_bin NOT NULL
        refund_money
          退款金额
        reason
          退款原因
        refund_status
          REFUND_NEW("100", "待退款"),
          REFUNDING("260", "退款中"),
          REFUND_SUCCESS("280", "已退款"),
          REFUND_FAIL("290", "退款失败");
        refund_time
          退款成功时间
        pay_refundflow_no
          支付平台退款记录唯一id
        pay_refundtime
          支付平台退款受理时间
        `iph_pay_merchant_no` varchar(50) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '支付商户号',
        `iph_sub_pay_merchant_no` varchar(50) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '支付子商户号',
        pay_user_id
          支付用户id
        pay_channel
        fromAccount
          出资账户，如果是商家支付则需要考虑多级商户账号系统
        toAccount
          受资账户
        user_type
      refund_record_detail
        id
        order_id
        refund_id
        sub_order_id
          订单明细ID
        sub_order_price
          订单明细价格
        refund_money
          退款金额
        user_type
          下游 type，如果下游通知要细分则需要记录这一信息
        user_id
      order_activity_discount
        order_id
        activity_id
        activity_name
        cost_type
          商户
          平台
        promotion_type
          1立减
          2返券
          3折扣类型
          4一口价类型
          5礼包类
          6服务类
        discount_data
        discount
        split_amount1
        split_amount2
        version
          有版本问题就意味着存在并发控制问题，这状态的使用要甄别
        gmt_created
        gmt_modified
      order_activity_discount_return
        id
        order_id
        sub_order_id
        activity_discount_id
        return_merchant_amount1
          退回商户优惠
        return_platform_amount
          退回平台优惠
        return_user_discount
          退回用户优惠
        gmt_created
        gmt_modified
      order_pay_timeout
        id
          这种子表的 id 最可怕的地方是：如果不使用 sequence 服务，则唯一性只能在单表上保持，如果使用 sequence，除非 sequence 支持批量获取主子 id 模式，否则调用量非常大，极易造成单点风险
        user_type
        user_id
        order_id
        pay_timeout_time
          在事务里插入
        attribute_value
        gmt_created
        gmt_modified
        company_id
          冗余元数据，其实是从底层的 subOrder 的 company_id。这里体现了子订单对 sku 的理解
        company_name
        status
        notified
          是否已通知用户 0 未通知 1 已通知'
        要建索引
      risk_log
        id
        order_id
        user_type
        user_id
        request_content
        result
        gmt_created
        gmt_modified
          可以加索引
        要建索引
      sub_order
        id
        order_id
        user_type
        user_id
        下层 order_id
          远端句柄冗余，要建索引
        下层 subOrder_id
          远端句柄冗余，要建索引
        commodity_id
        product_id
        product_name
        company_id
        company_name
        status
          WAITING_FOR_PAYMENT("100", "待支付"),
          PAY_TIMEOUT("110", "支付超时"),
          CANCELED("120", "已取消"),
          PAID("140", "已支付"),
          CAN_EDIT("141", "可编辑"),
          HAS_SUBMIT("142", "已提交"),
          BUYING("180", "购买中"),
          BUY_FAILED("190", "购买失败"),
          BUY_SUCCESS("200", "购买成功"),
          RETURNING("210", "申请退货中")
          RETURN_SUCCESS("230", "退货成功"),
          RETURN_FAIL("240", "退货失败"),
          REFUNDING("260", "退款中"),
          REFUND_SUCCESS("280", "已退款"),
          REFUND_FAIL("290", "退款失败");
          慎用
        display_price
        paid_price
        gmt_created
        gmt_modified
          可以加索引
        quntity 或者 count
          本单的商品含量
        起止期
          有些商品有
        商品电子地址
        要建索引
        这里也可以表达为 spNo、prodNo 等 spu 元数据属性和 sku 元数据属性
      sub_order_return
        id
          主键
        order_return_id
          申请退货记录ID
        order_id
          订单号
        sub_order_id
          子单号
        user_id
        下层子单号
        company_order_id
          供应链公司订单 id
        product_id
          产品 id、商品 id
        status
          NEW("100", "新建"),
          RETURNING("180", "退货中"),
          SUCCESS("200", "退货成功"),
          FAIL("300", "退货失败");
        pay_price
          原支付金额
        return_price
          实际退款金额
        return_price_predict
          预估退款金额
          decimal(12,2) NOT NULL DEFAULT '0.00'
        refund_id
          退款ID
        refund_detail_id
          退款详单ID
          bigint(20) DEFAULT NULL
        gmt_created
        gmt_modified
          datetime DEFAULT NULL
          '修改时间'
        user_type
        request_time
          业务请求退保时间
      sub_order_status_change_log
          id
          user_type
          user_id
          order_id
          sub_order_id
          oldStatus
          newStatus
          gmt_created
          gmt_modified
          要建索引
      sub_order_attribute
        id
        order_id
          订单号
        sub_order_id
          子订单号
        attritbute_name
        attribute_value
        attribute_value
        gmt_created
        gmt_modified
        encrypt_way
          加密标志 0.未加密 1.已加密
      order_person_info
        id
        user_id
        order_id
        sub_order_id
        name
        identity_type
        identity_no
        gender
        birthday
        type
          干系人类型
        relationship
          与干系人的关系
        gmt_created
        gmt_modified
          可以加索引
        要建索引
      shop_request
        一些店铺的地理信息：省市名、id、街道、area 信息、经纬度、poi 序号、uid、订单 id、渠道 id、appid
一般这种模型是为了上报新的元数据，这样下次基于店铺来购买商品（如商户保险）的时候，可以加速选择，优化用户体验
      biz_order_mapping
        order_id
        biz_order_id
      utm_info
        id
      在有些设计中，order 不能支持由外部 id 生成orderid，或者下游的服务不支持多列幂等路由，又有些设计要求分库分表，需要把不能路由的 order_id 设计成可以路由的 order_id，就需要这样一张窄表。窄表的特性的是占用 MySQL 数据页比较小，所以能容纳的记录行数比较多。
    toB 系统
  中台层
  gateway 层