CaiWuXiTong/modules/EcommerceFinance/Services/AccessoryReshipCourierImporter.php

81 lines
4.5 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 Modules\EcommerceFinance\Services;
use Illuminate\Validation\ValidationException;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
class AccessoryReshipCourierImporter
{
public function read(string $path): array
{
$reader = IOFactory::createReader('Xlsx');
$info = $reader->listWorksheetInfo($path);
if (count($info) !== 1 || $info[0]['totalRows'] > 5001 || $info[0]['totalColumns'] > 20) {
throw ValidationException::withMessages(['file' => '请使用单工作表、最多5000条配置的Excel文件。']);
}
$book = $reader->load($path);
try {
$sheet = $book->getSheet(0);
$headers = [];
for ($column = 1; $column <= $info[0]['totalColumns']; $column++) {
$label = trim((string) $sheet->getCell([$column, 1])->getValue());
$label = str_replace(['(', ')', '%', ' '], ['(', ')', '%', ''], $label);
$headers[$label] = $column;
}
$rateColumn = $headers['扣款比率(%)'] ?? $headers['扣款比例(%)'] ?? null;
foreach (['快递代码', '快递公司', '创建时间', '创建人'] as $header) {
if (!isset($headers[$header])) {
throw ValidationException::withMessages(['file' => '缺少列:' . $header]);
}
}
if ($rateColumn === null) {
throw ValidationException::withMessages(['file' => '缺少列:扣款比率(%)']);
}
$rows = [];
$codes = [];
$names = [];
for ($number = 2; $number <= $sheet->getHighestDataRow(); $number++) {
$values = [];
foreach (['courier_code' => $headers['快递代码'], 'courier_name' => $headers['快递公司'], 'source_created_at' => $headers['创建时间'], 'creator' => $headers['创建人'], 'rate' => $rateColumn] as $key => $column) {
$cell = $sheet->getCell([$column, $number]);
if ($cell->getDataType() === 'f') {
throw ValidationException::withMessages(['file' => "第{$number}行含公式,请使用实际配置值。"]);
}
$values[$key] = trim((string) $cell->getFormattedValue());
if ($key === 'source_created_at' && is_numeric($cell->getValue()) && ExcelDate::isDateTime($cell)) {
$values[$key] = ExcelDate::excelToDateTimeObject($cell->getValue())->format('Y-m-d H:i:s');
}
}
if (implode('', $values) === '') {
continue;
}
if ($values['courier_code'] === '' || mb_strlen($values['courier_code']) > 64 || $values['courier_name'] === '' || mb_strlen($values['courier_name']) > 191 || $values['creator'] === '' || mb_strlen($values['creator']) > 191) {
throw ValidationException::withMessages(['file' => "第{$number}行快递代码、名称或创建人为空或超长。"]);
}
if (isset($codes[mb_strtolower($values['courier_code'])]) || isset($names[mb_strtolower($values['courier_name'])])) {
throw ValidationException::withMessages(['file' => "第{$number}行快递代码或名称重复。"]);
}
$codes[mb_strtolower($values['courier_code'])] = true;
$names[mb_strtolower($values['courier_name'])] = true;
$rate = AccessoryReshipRateCalculator::basisPoints($values['rate']);
$date = $values['source_created_at'];
if ($date !== '' && (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $date) || !checkdate((int) substr($date, 5, 2), (int) substr($date, 8, 2), (int) substr($date, 0, 4)) || substr($date, 11, 2) > '23' || substr($date, 14, 2) > '59' || substr($date, 17, 2) > '59')) {
throw ValidationException::withMessages(['file' => "第{$number}行创建时间无效。"]);
}
unset($values['rate']);
$values['source_created_at'] = $date === '' ? null : $date;
$values['rate_basis_points'] = $rate;
$rows[] = $values;
}
if ($rows === []) {
throw ValidationException::withMessages(['file' => '配置表没有有效记录。']);
}
return $rows;
} finally {
$book->disconnectWorksheets();
}
}
}