feat: add non-destructive EJ medicine sync

This commit is contained in:
2026-09-10 11:09:26 +08:00
parent 27fbef9321
commit 17e9e7b6b6
6 changed files with 1087 additions and 0 deletions
@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
namespace app\command;
use app\common\service\pharmacy\EjMedicineIncrementalPushService;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
final class EjPharmacyPushMedicines extends Command
{
protected function configure()
{
$this->setName('ej-pharmacy:push-medicines')
->setDescription('非破坏性增量推送 ZYT 药材到恩济药房;保留双方已有药材')
->addOption('apply', null, Option::VALUE_NONE, '执行远端增量导入;缺省仅做 dry-run')
->addOption('confirm', null, Option::VALUE_OPTIONAL, '增量写入确认令牌:INCREMENTAL_NO_DELETE', '')
->addOption('batch-size', null, Option::VALUE_OPTIONAL, '每批药材数量(1-500', 100)
->addOption('run-id', null, Option::VALUE_OPTIONAL, '幂等运行标识(缺省 zyt-incremental,最长 25 位)', '');
}
protected function execute(Input $input, Output $output)
{
try {
$apply = (bool) $input->getOption('apply');
$confirm = (string) $input->getOption('confirm');
$batchSize = (int) $input->getOption('batch-size');
EjMedicineIncrementalPushService::assertCommandGate($apply, $confirm, $batchSize);
if (!$apply) {
$plan = EjMedicineIncrementalPushService::plan($batchSize);
$output->writeln(sprintf(
'dry-run source=%d candidates=%d batches=%d mapped=%d unmapped=%d '
. 'preserved_inactive=%d remote_delete=0 local_delete=0',
$plan['source_count'],
$plan['candidate_count'],
$plan['batch_count'],
$plan['mapped_count'],
$plan['unmapped_count'],
$plan['preserved_inactive']
));
return 0;
}
$result = EjMedicineIncrementalPushService::execute(
$batchSize,
(string) $input->getOption('run-id')
);
$output->writeln(sprintf(
'incremental 完成 run_id=%s source=%d candidates=%d batches=%d '
. 'remote_created=%d remote_existing=%d preserved_inactive=%d '
. 'catalog_created=%d catalog_updated=%d mapping_created=%d mapping_updated=%d '
. 'mapping_unchanged=%d remote_delete=0 local_delete=0',
$result['run_id'],
$result['source_count'],
$result['candidate_count'],
$result['batch_count'],
$result['remote_created'],
$result['remote_existing'],
$result['preserved_inactive'],
$result['catalog_created'],
$result['catalog_updated'],
$result['mapping_created'],
$result['mapping_updated'],
$result['mapping_unchanged']
));
return 0;
} catch (\Throwable $exception) {
$output->error($exception->getMessage());
return 1;
}
}
}