[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. За «рождение» решения благодарим Андрея Богданова.
Поблагодарить автора
Отправить деньги