122 lines
4.3 KiB
PHP
122 lines
4.3 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Business\SupplierSummaryInboundImporter;
|
||
use Illuminate\Console\Command;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Facades\File;
|
||
use Throwable;
|
||
|
||
/**
|
||
* 供应商汇总表月度增量导入:读取已解密工作簿的「明细」子表,仅追加目标月份数据。
|
||
*/
|
||
class ImportSupplierSummaryInbound extends Command
|
||
{
|
||
protected $signature = 'inventory:supplier-summary:import
|
||
{file : 已解密的供应商汇总 XLSX 文件}
|
||
{--month= : 目标月份 YYYY-MM,默认上一个月}
|
||
{--result-json= : 将执行结果写入指定 JSON 文件}';
|
||
|
||
protected $description = '将供应商汇总表「明细」增量导入入库明细数据';
|
||
|
||
public function handle(SupplierSummaryInboundImporter $importer): int
|
||
{
|
||
$month = trim((string) $this->option('month'));
|
||
if ($month === '') {
|
||
$month = now('Asia/Shanghai')->subMonthNoOverflow()->format('Y-m');
|
||
}
|
||
|
||
$lock = Cache::lock('inventory-supplier-summary-inbound-import', 21600);
|
||
if (! $lock->get()) {
|
||
return $this->finish([
|
||
'status' => 'failed',
|
||
'report_month' => $month,
|
||
'source_filename' => basename((string) $this->argument('file')),
|
||
'success' => 0,
|
||
'duplicates' => 0,
|
||
'failed' => 1,
|
||
'mapped' => 0,
|
||
'total_in_table' => 0,
|
||
'failure_reason_count' => 1,
|
||
'failure_reasons' => [[
|
||
'row' => 0,
|
||
'reason' => '已有供应商汇总导入任务正在执行',
|
||
]],
|
||
]);
|
||
}
|
||
|
||
try {
|
||
$result = $importer->import((string) $this->argument('file'), $month);
|
||
} catch (Throwable $exception) {
|
||
report($exception);
|
||
$result = [
|
||
'status' => 'failed',
|
||
'report_month' => $month,
|
||
'source_filename' => basename((string) $this->argument('file')),
|
||
'success' => 0,
|
||
'duplicates' => 0,
|
||
'failed' => 1,
|
||
'mapped' => 0,
|
||
'total_in_table' => 0,
|
||
'failure_reason_count' => 1,
|
||
'failure_reasons' => [[
|
||
'row' => 0,
|
||
'reason' => $exception->getMessage(),
|
||
]],
|
||
];
|
||
} finally {
|
||
$lock->release();
|
||
}
|
||
|
||
return $this->finish($result);
|
||
}
|
||
|
||
/** @param array<string,mixed> $result */
|
||
private function finish(array $result): int
|
||
{
|
||
$reasons = is_array($result['failure_reasons'] ?? null)
|
||
? $result['failure_reasons']
|
||
: [];
|
||
$result['failure_reason_count'] = count($reasons);
|
||
|
||
$json = json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||
if (! is_string($json)) {
|
||
$json = '{"status":"failed","failure_reasons":[{"row":0,"reason":"结果 JSON 编码失败"}]}';
|
||
}
|
||
|
||
$resultPath = trim((string) $this->option('result-json'));
|
||
if ($resultPath !== '') {
|
||
File::ensureDirectoryExists(dirname($resultPath));
|
||
File::put($resultPath, $json . PHP_EOL);
|
||
}
|
||
|
||
$this->line(sprintf(
|
||
'%s 导入状态=%s,成功=%s,重复=%s,失败=%s,目标月份总行数=%s',
|
||
(string) ($result['report_month'] ?? ''),
|
||
(string) ($result['status'] ?? 'failed'),
|
||
number_format((int) ($result['success'] ?? 0)),
|
||
number_format((int) ($result['duplicates'] ?? 0)),
|
||
number_format((int) ($result['failed'] ?? 0)),
|
||
number_format((int) ($result['total_in_table'] ?? 0)),
|
||
));
|
||
foreach (array_slice($reasons, 0, 10) as $reason) {
|
||
$this->warn(sprintf(
|
||
'第 %s 行:%s',
|
||
(string) ($reason['row'] ?? ''),
|
||
(string) ($reason['reason'] ?? '未知错误'),
|
||
));
|
||
}
|
||
if (count($reasons) > 10) {
|
||
$this->line(sprintf(
|
||
'另有 %s 条失败原因,完整清单见结果 JSON。',
|
||
number_format(count($reasons) - 10),
|
||
));
|
||
}
|
||
|
||
return ($result['status'] ?? 'failed') === 'success'
|
||
? self::SUCCESS
|
||
: self::FAILURE;
|
||
}
|
||
}
|