CaiWuXiTong/app/Console/Commands/ImportJstOrderLabelPlantingRules.php
qiuxiang d877735507 聚水潭订单标签明细:新增「是否种菜订单」列
下单时间后面新增「是否种菜订单」列,逐行按(公司 + 标签)匹配财务维护的映射表:命中为是、未命中为否。
- 新表 jst_order_label_planting_rules + 模型 + 缓存服务,导入命令 jst-order-labels:import-planting-rules(读「判断种菜单.xlsx」)
- 导出 CSV 同步新增该列,页面/导出同口径
- 本地构建通过;改动/新增 PHP 文件 php -l 通过
2026-10-07 11:14:04 +08:00

147 lines
5.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Console\Commands;
use App\Business\JstOrderLabelPlantingRules;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Throwable;
/**
* 导入「标签 | 是否种菜订单」映射表,供聚水潭订单标签明细的「是否种菜订单」列使用。
*/
class ImportJstOrderLabelPlantingRules extends Command
{
protected $signature = 'jst-order-labels:import-planting-rules
{path : xlsx/csv 文件}
{--company= : 公司ID(默认使用当前公司或 1)}
{--sheet=1 : 工作表序号(从 1 开始)或名称}
{--replace : 先清空该公司已有映射再导入(默认按标签覆盖)}';
protected $description = '导入聚水潭订单标签明细的「是否种菜订单」映射表';
public function handle(JstOrderLabelPlantingRules $rules): int
{
$path = (string) $this->argument('path');
if (! is_file($path)) {
$this->error('文件不存在:' . $path);
return self::FAILURE;
}
$companyId = (int) ($this->option('company') ?: (function_exists('company_id') && company_id() ? company_id() : 1));
if ($companyId <= 0) {
$this->error('公司ID无效,请用 --company 指定。');
return self::FAILURE;
}
try {
$rows = $this->readRows($path);
} catch (Throwable $e) {
$this->error('读取失败:' . $e->getMessage());
return self::FAILURE;
}
if ($rows === []) {
$this->error('没有解析到有效数据(需要表头:标签 / 是否种菜订单)。');
return self::FAILURE;
}
$now = now();
DB::transaction(function () use ($rows, $now, $companyId): void {
if ($this->option('replace')) {
DB::table('jst_order_label_planting_rules')->where('company_id', $companyId)->delete();
}
foreach (array_chunk($rows, 500) as $chunk) {
DB::table('jst_order_label_planting_rules')->upsert(
array_map(static fn (array $row): array => $row + [
'company_id' => $companyId,
'created_at' => $now,
'updated_at' => $now,
], $chunk),
['company_id', 'label'],
['is_planting', 'updated_at'],
);
}
});
$rules->forget($companyId);
$planting = count(array_filter($rows, static fn (array $row): bool => $row['is_planting'] === '是'));
$this->info(sprintf('已导入 %d 条「是否种菜订单」映射(公司 %d):种菜 %d 条,非种菜 %d 条。', count($rows), $companyId, $planting, count($rows) - $planting));
return self::SUCCESS;
}
/**
* @return list<array{label:string,is_planting:string}>
*/
private function readRows(string $path): array
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$readerType = match ($extension) {
'xlsx' => 'Xlsx',
'xls' => 'Xls',
'csv' => 'Csv',
default => throw new \InvalidArgumentException('只支持 xlsx / xls / csv 文件。'),
};
$reader = IOFactory::createReader($readerType);
$reader->setReadDataOnly(true);
if ($readerType === 'Csv') {
$reader->setInputEncoding('UTF-8');
}
$book = $reader->load($path);
$sheetOption = trim((string) $this->option('sheet'));
if ($sheetOption !== '' && ctype_digit($sheetOption)) {
$index = (int) $sheetOption - 1;
if ($index < 0 || $index >= $book->getSheetCount()) {
throw new \InvalidArgumentException('工作表序号超出范围:' . $sheetOption);
}
$sheet = $book->getSheet($index);
} else {
$sheet = $sheetOption === '' ? $book->getActiveSheet() : $book->getSheetByName($sheetOption);
if ($sheet === null) {
throw new \InvalidArgumentException('找不到工作表:' . $sheetOption);
}
}
$rows = [];
$header = null;
foreach ($sheet->getRowIterator() as $row) {
$cells = [];
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(false);
foreach ($cellIterator as $cell) {
$cells[] = trim((string) $cell->getValue());
}
if ($header === null) {
$cells[0] = preg_replace('/^\xEF\xBB\xBF/', '', $cells[0] ?? '');
$header = $cells;
continue;
}
$label = trim($cells[0] ?? '');
$flag = trim($cells[1] ?? '');
if ($label === '') {
continue;
}
$rows[] = [
'label' => mb_substr($label, 0, 191),
'is_planting' => in_array(mb_strtolower($flag), ['否', 'n', 'no', '0', 'false'], true) ? '否' : '是',
];
}
return $rows;
}
}