CaiWuXiTong/app/Console/Commands/ImportServiceCompanyCustomerMapping.php
DoDo 00728c5212 feat: 固定客服公司映射并自动平衡未分配店铺 (#1096)
固定已有映射,收入店铺自动平衡后锁定。
2026-11-11 17:45:18 +08:00

95 lines
3.7 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Business\ServiceCompanyReconciliation\CustomerServiceMappingWorkbookImporter;
use App\Business\ServiceCompanyReconciliation\ServiceCompanyReconciliationRepository;
use Illuminate\Console\Command;
class ImportServiceCompanyCustomerMapping extends Command
{
protected $signature = 'service-company:import-customer-mapping
{file : 客服公司映射 Excel 路径}
{--company-id=1 : 租户公司 ID}
{--effective-from=2026-10-01 : 结算关系生效日期}
{--auto-assign-period= : 未分配店铺按该月收入自动平衡,默认上一个完整月}
{--actor=客服公司映射导入 : 导入操作人}
{--dry-run : 只解析和校验,不写入数据库}';
protected $description = '导入客服公司与店铺公司的配置映射';
public function handle(
CustomerServiceMappingWorkbookImporter $importer,
ServiceCompanyReconciliationRepository $repository,
): int {
$companyId = (int) $this->option('company-id');
$effectiveFrom = trim((string) $this->option('effective-from'));
$autoAssignPeriod = trim((string) $this->option('auto-assign-period'));
if ($autoAssignPeriod === '') {
$autoAssignPeriod = now()->startOfMonth()->subMonthNoOverflow()->format('Y-m');
}
try {
$parsed = $importer->rows((string) $this->argument('file'));
} catch (\Throwable $exception) {
$this->error($exception->getMessage());
return self::FAILURE;
}
$this->table(['指标', '数量'], [
['店铺公司行数', $parsed['total_rows']],
['已分配客服公司', $parsed['assigned_rows']],
['暂不分配', $parsed['unassigned_rows']],
['无效行', count($parsed['invalid_rows'])],
]);
if ($parsed['invalid_rows'] !== []) {
$this->error(implode(PHP_EOL, $parsed['invalid_rows']));
return self::FAILURE;
}
if ((bool) $this->option('dry-run')) {
$this->info('校验通过,未写入数据库。');
return self::SUCCESS;
}
$result = $repository->syncCustomerServiceMappings(
$companyId,
$parsed['rows'],
$effectiveFrom,
trim((string) $this->option('actor')) ?: '客服公司映射导入',
$parsed['unassigned'],
$autoAssignPeriod,
);
if ($result['errors'] !== []) {
$this->error(implode(PHP_EOL, $result['errors']));
return self::FAILURE;
}
$this->table(['结果', '数量'], [
['新增', $result['created']],
['更新', $result['updated']],
['无变化', $result['unchanged']],
['停用', $result['inactive']],
['自动补分配', $result['auto_assigned']],
['有收入但无法分配', count($result['auto_errors'])],
]);
if ($result['auto_totals'] !== []) {
$this->table(
['客服公司', '自动补分配后收入'],
collect($result['auto_totals'])
->map(static fn (float $amount, string $name): array => [$name, number_format($amount, 2, '.', '')])
->values()
->all(),
);
}
if ($result['auto_errors'] !== []) {
$this->warn(implode(PHP_EOL, $result['auto_errors']));
}
$this->info("客服公司映射已同步,生效日期:{$effectiveFrom}");
return self::SUCCESS;
}
}