• 做可用的软件!!!多次事务,缩小事务单位。


    /**
     * 超过过期时间未拼团成功的全部报废,并退款
     */
    public function clearUnSuccessOrder() {
        $group_order = M('group_order');
        $capture_group_order = $group_order
            ->where(['is_pay'=>1,'status'=>1,'expired_time'=>['lt',time()]])
            ->select();
    
        // todo改造,成功一条,commit一条
        $error_msg_arr = [];
        $success_count = 0;
        $fail_count = 0;
        if ($capture_group_order) {
            $group_purchase = M('group_purchase');
            $group_reward   = M('group_reward');
            vendor('Func.WxPay');
            foreach ($capture_group_order as $k=>$v) {
                M()->startTrans();
                // step1 修改订单状态
                $edit_data = [
                    'status' => -2,
                    'updatetime' => time()
                ];
                $edit_group_order_flag = $group_order
                    ->where(['id'=>$v['id']])
                    ->save($edit_data);
                if ($edit_group_order_flag === false) {
                    M()->rollback();
                    $error_msg_arr[] = date('Y-m-d H:i:s').'-清理过期时间未拼团成功订单:修改状态不成功';
                    $fail_count++;
                    continue;
                }
    
                // step2 撤回已占用库存
                $group_flag = $group_purchase->where(['id'=>$v['group_id']])->setDec('buyed_stock');
                if ($group_flag === false) {
                    M()->rollback();
                    $error_msg_arr[] = date('Y-m-d H:i:s').'-清理未支付订单:修改库存失败';
                    $fail_count++;
                    continue;
                }
    
                // step3 撤回已占用惊喜金额
                if ((int)$v['reward_id'] > 0) {
                    $reward_edit_data  = [
                        'status' => 1
                    ];
                    $group_reward_flag = $group_reward->where(['id' => $v['reward_id']])->save($reward_edit_data);
                    if ($group_reward_flag === false) {
                        M()->rollback();
                        $error_msg_arr[] = date('Y-m-d H:i:s').'-清理未支付订单:修改惊喜失败';
                        $fail_count++;
                        continue;
                    }
                }
                // step4 退回付款金额
                $refund_result = WxPay::refundOrder($v['billno'], $v['payed_price'], $v['payed_price']);
                if ((int)$refund_result['num'] === 1) {
                    $refund_order_edit_data = [
                        'refund_transaction_id' => $refund_result['refund_id'],
                        'refund_order_sn'       => $refund_result['refund_no'],
                        'is_refund'             => 1,
                    ];
                    $refund_order_edit_flag = $group_order->where(['id' => $v['id']])->save($refund_order_edit_data);
                    if ($refund_order_edit_flag === false) { // 如果失败,再改一次
                        $refund_order_edit_data = [
                            'is_refund'             => 1,
                        ];
                        $group_order->where(['id' => $v['id']])->save($refund_order_edit_data);
    //                        M()->rollback();
    //                        $error_msg_arr[] = date('Y-m-d H:i:s').'-清理未支付订单:修改退款失败'.$refund_result['desc'];
    //                        $fail_count++;
    //                        continue;
                    }
                } else {
                    M()->rollback();
                    $error_msg_arr[] = date('Y-m-d H:i:s').'-清理未支付订单:退款失败'.$refund_result['desc'];
                    $fail_count++;
                    continue;
                }
                M()->commit();
                $success_count++;
            }
    
        }
        $error_msg_arr[] = date('Y-m-d H:i').'-清理过期时间未拼团成功订单:本次共清理'.count($capture_group_order).'个拼团失败订单'.',成功了'.$success_count.',失败了'.$fail_count.'个'.PHP_EOL;
        exit(var_export($error_msg_arr,true).PHP_EOL);
    }
    

    一次循环,一个事务。
    确保大部分整体事务能够提交上去。
    并记录下,成功的数量,失败的数量。以及具体的原因。

  • 相关阅读:
    OSGI .Net 框架学习
    ArcEngine开发过程中的空间关系
    ITOCControl添加鼠标右键菜单
    IHookHelper的使用
    ITopologicalOperator接口调用
    GeoProcessor的使用方法
    ArcEngine内置工具条
    OSGI.NET插件方式开发你的应用
    C#在linux上运行实现
    Linux 下随机启动自己的应用 -请使用while(true) 不要Console.ReadKey()
  • 原文地址:https://www.cnblogs.com/jiqing9006/p/10943674.html
Copyright © 2020-2023  润新知