[msBonus2] Миграция с msBonus на msBonus2


Ситуация с миграцией на вторую версию несколько сложнее, чем может показаться обывателю. Вместе с цифрами в аккаунте переносить нужно ещё и логи начислений. К тому же, на сайте может быть не сотня юзеров, а несколько десятков тысяч — тут уже проблема возникает с max_execution_time.

Предлагаю скрипт, который вместе с цифрами бонусов переносит ещё и логи, а также может работать из Console с десятками тысяч юзеров, не боясь max_execution_time.

Код:


$modx->addPackage('msbonus', MODX_CORE_PATH . 'components/msbonus/model/');
$modx->loadClass('msBonusTransaction');
$msb2 = $modx->getService('msbonus2', 'msBonus2', MODX_CORE_PATH . 'components/msbonus2/model/msbonus2/');
$msb2->initialize($modx->context->key);
$manager = $msb2->getManager();

//
$limit = 1;
$_SESSION['Console']['msBonusMigration'] = isset($_SESSION['Console']['msBonusMigration'])
    ? $_SESSION['Console']['msBonusMigration'] : [
        'offset' => 0,
    ];
$offset = &$_SESSION['Console']['msBonusMigration']['offset'];
$count = $modx->getCount('msCustomerProfile', ['id:!=' => 0]);

//
if ($offset < $count) {
    // print_r("Производим выборку." . PHP_EOL);
    
    //
    $actions = [
        'writeoff' => [
            'action' => '-',
            'type' => 'order_writeoff',
        ],
        'cancel' => [
            'action' => '+',
            'type' => 'order_writeoff',
        ],
        'accrual' => [
            'action' => '+',
            'type' => 'order_accrual',
        ],
        'refund' => [
            'action' => '-',
            'type' => 'order_accrual',
        ],
    ];
    
    //
    $q = $modx->newQuery('msCustomerProfile')
        ->select($modx->getSelectColumns('msCustomerProfile'))
        ->sortby('createdon', 'ASC')
        ->limit($limit, $offset)
        ;
    if ($q->prepare()->execute()) {
        $profiles = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($profiles as $profile) {
            // print_r($profile);
            
            // Get msb2User object
            $msb2User = $manager->getJoinedUser($profile['id']);
            
            //
            $q = $modx->newQuery('msBonusTransaction')
                ->select($modx->getSelectColumns('msBonusTransaction'))
                ->where([
                    'user_id' => $profile['id'],
                ])
                ->sortby('createdon', 'ASC')
                // ->limit(10)
                ;
            if ($q->prepare()->execute()) {
                if ($logs = $q->stmt->fetchAll(PDO::FETCH_ASSOC)) {
                    foreach ($logs as $log) {
                        if (empty($log['amount'])) {
                            continue;
                        }
                        
                        // Get msOrder object
                        if (!$msOrder = $manager->getOrder($log['order_id'])) {
                            continue;
                        }
                        
                        // Get msb2Order object
                        $msb2Order = $manager->getJoinedOrder($log['order_id']);
                        
                        //
                        $modx->newObject('msb2Log', [
                            'user' => $msb2User->get('user'),
                            'order' => $log['order_id'],
                            'action' => $actions[$log['type']]['action'],
                            'type' => $actions[$log['type']]['type'],
                            'amount' => $log['amount'],
                            'createdon' => strtotime($log['createdon']),
                            'createdby' => $log['user_id'],
                            'activatedon' => 0,
                        ])->save();
                        
                        //
                        switch ($log['type']) {
                            case 'writeoff':
                                $msb2Order->set('writeoff', $log['amount']);
                                break;
                                
                            case 'cancel':
                                $msb2Order->set('writeoff', 0);
                                break;
                                
                            case 'accrual':
                                $msb2Order->set('accrual', $log['amount']);
                                $msb2Order->set('cost', $msOrder->get('cost') - $msOrder->get('delivery_cost'));
                                break;
                                
                            case 'refund':
                                $msb2Order->set('accrual', 0);
                                $msb2Order->set('cost', 0);
                                break;
                        }
                        $msb2Order->save();
                    }
                }
            }
            
            // Set actual balance
            $msb2User->set('points', $profile['account']);
            $msb2User->set('paid_points', $profile['spent']);
            $msb2User->save();
        }
        $offset += count($profiles);
    }
}

//
$percent = number_format(100 * $offset / $count, 2, '.', '');
print_r("{$percent}%" . PHP_EOL);

//
if ($_SESSION['Console']['completed'] = $offset >= $count) {
    print_r("Завершено!" . PHP_EOL);
    unset($_SESSION['Console']['msBonusMigration']);
} else {
    print_r("Продолжаем..." . PHP_EOL);
}

Внимание! Данным решением нужно пользоваться только если вы ничего не кастомизировали в работе первой версии. В противном случае может потребоваться писать скрипт миграции под ваши правки.

P.S. За «рождение» решения благодарим Андрея Богданова.
Павел Гвоздь
15 февраля 2020, 10:03
modx.pro
1
821
+9
Поблагодарить автора Отправить деньги

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
0