feat(98-order-imported-first-only): gate order.imported na pierwszy import + backfill statusow
- AllegroOrderImportService / ShopproOrdersSyncService: trigger order.imported tylko gdy $wasCreated - bin/backfill_shipped_status_98.php: jednorazowy CLI, w_realizacji + shipment -> wyslane (przez OrdersRepository::updateOrderStatus) - backfill: 4 zamowienia naprawione (#275, #340, #396, #422), idempotentny Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
94
bin/backfill_shipped_status_98.php
Normal file
94
bin/backfill_shipped_status_98.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Backfill (Phase 98): zamowienia w statusie "W realizacji" (w_realizacji),
|
||||
* ktore maja juz utworzona przesylke w shipment_packages, zostaja przestawione
|
||||
* na status "Wyslane" (wyslane). Zmiana idzie przez OrdersRepository::updateOrderStatus,
|
||||
* dzieki czemu powstaje wpis w order_status_history i order_activity_log.
|
||||
*
|
||||
* Idempotentny: drugie uruchomienie na czystej bazie nie zrobi nic.
|
||||
*
|
||||
* Flagi:
|
||||
* --dry-run pokaz tylko liste kandydatow, bez zmian
|
||||
* --use-remote uzyj DB_HOST_REMOTE zamiast DB_HOST (dla operacji recznych agenta)
|
||||
*/
|
||||
|
||||
use App\Core\Database\ConnectionFactory;
|
||||
use App\Core\Support\Env;
|
||||
use App\Modules\Orders\OrdersRepository;
|
||||
|
||||
$basePath = dirname(__DIR__);
|
||||
require $basePath . '/vendor/autoload.php';
|
||||
|
||||
Env::load($basePath . '/.env');
|
||||
|
||||
/** @var array<string, mixed> $dbConfig */
|
||||
$dbConfig = require $basePath . '/config/database.php';
|
||||
|
||||
$dryRun = in_array('--dry-run', $argv, true);
|
||||
$useRemote = in_array('--use-remote', $argv, true);
|
||||
|
||||
if ($useRemote) {
|
||||
$remoteHost = (string) Env::get('DB_HOST_REMOTE', '');
|
||||
if ($remoteHost !== '') {
|
||||
$dbConfig['host'] = $remoteHost;
|
||||
echo '[db] using DB_HOST_REMOTE for this run' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
$pdo = ConnectionFactory::make($dbConfig);
|
||||
|
||||
echo 'Backfill 98: orders w_realizacji + shipment -> wyslane' . PHP_EOL;
|
||||
echo $dryRun ? '[mode] dry-run' . PHP_EOL : '[mode] apply' . PHP_EOL;
|
||||
|
||||
const SOURCE_CODE = 'w_realizacji';
|
||||
const TARGET_CODE = 'wyslane';
|
||||
|
||||
$repository = new OrdersRepository($pdo);
|
||||
|
||||
$sql = 'SELECT o.id FROM orders o '
|
||||
. 'WHERE o.status_code = :source '
|
||||
. 'AND EXISTS (SELECT 1 FROM shipment_packages sp WHERE sp.order_id = o.id) '
|
||||
. 'ORDER BY o.id ASC';
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute(['source' => SOURCE_CODE]);
|
||||
$ids = array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN) ?: []);
|
||||
|
||||
$total = count($ids);
|
||||
$updated = 0;
|
||||
$skipped = 0;
|
||||
|
||||
echo '[scan] candidates: ' . $total . PHP_EOL;
|
||||
|
||||
foreach ($ids as $orderId) {
|
||||
if ($dryRun) {
|
||||
echo ' [dry-run] order #' . $orderId . ' -> ' . TARGET_CODE . PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$ok = $repository->updateOrderStatus(
|
||||
$orderId,
|
||||
TARGET_CODE,
|
||||
'system',
|
||||
'backfill-98'
|
||||
);
|
||||
|
||||
if ($ok) {
|
||||
$updated++;
|
||||
echo ' [ok] order #' . $orderId . ' -> ' . TARGET_CODE . PHP_EOL;
|
||||
} else {
|
||||
$skipped++;
|
||||
echo ' [skip] order #' . $orderId . ' (updateOrderStatus returned false)' . PHP_EOL;
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
$skipped++;
|
||||
fwrite(STDERR, ' [err] order #' . $orderId . ': ' . $exception->getMessage() . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
echo PHP_EOL;
|
||||
echo 'Backfill 98: total=' . $total . ' updated=' . $updated . ' skipped=' . $skipped . PHP_EOL;
|
||||
echo 'Done.' . PHP_EOL;
|
||||
Reference in New Issue
Block a user