101 lines
3.4 KiB
PHP
101 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\common\service\pharmacy;
|
|
|
|
use DomainException;
|
|
|
|
final class PharmacyHerbIdentityResolver
|
|
{
|
|
/**
|
|
* @param array<int,array<string,mixed>> $herbs
|
|
* @param callable(array<int,int>):array<int,array<string,mixed>> $loadByIds
|
|
* @param callable(array<int,string>):array<int,array<string,mixed>> $loadByNames
|
|
* @return array<int,array<string,mixed>>
|
|
*/
|
|
public static function resolve(array $herbs, callable $loadByIds, callable $loadByNames): array
|
|
{
|
|
$ids = [];
|
|
$names = [];
|
|
foreach ($herbs as $herb) {
|
|
if (!is_array($herb)) {
|
|
continue;
|
|
}
|
|
$id = (int) ($herb['medicine_id'] ?? $herb['id'] ?? 0);
|
|
if ($id > 0) {
|
|
$ids[] = $id;
|
|
continue;
|
|
}
|
|
$name = trim((string) ($herb['name'] ?? $herb['title'] ?? ''));
|
|
if ($name !== '') {
|
|
$names[] = $name;
|
|
}
|
|
}
|
|
|
|
$byId = [];
|
|
foreach ($ids === [] ? [] : $loadByIds(array_values(array_unique($ids))) as $row) {
|
|
if (self::isActive($row)) {
|
|
$byId[(int) $row['id']] = $row;
|
|
}
|
|
}
|
|
$byName = [];
|
|
foreach ($names === [] ? [] : $loadByNames(array_values(array_unique($names))) as $row) {
|
|
if (!self::isActive($row)) {
|
|
continue;
|
|
}
|
|
$name = trim((string) ($row['name'] ?? ''));
|
|
if ($name !== '') {
|
|
$byName[$name][] = $row;
|
|
}
|
|
}
|
|
|
|
$resolved = [];
|
|
foreach ($herbs as $herb) {
|
|
if (!is_array($herb)) {
|
|
continue;
|
|
}
|
|
$name = trim((string) ($herb['name'] ?? $herb['title'] ?? ''));
|
|
$id = (int) ($herb['medicine_id'] ?? $herb['id'] ?? 0);
|
|
if ($id > 0) {
|
|
$row = $byId[$id] ?? null;
|
|
if (!is_array($row)) {
|
|
throw new DomainException('药材“' . ($name !== '' ? $name : (string) $id) . '”对应的本地药材不存在或已停用');
|
|
}
|
|
} else {
|
|
if ($name === '') {
|
|
throw new DomainException('药材名称不能为空');
|
|
}
|
|
$candidates = $byName[$name] ?? [];
|
|
if (count($candidates) === 0) {
|
|
throw new DomainException('药材“' . $name . '”未在本地药材库中找到');
|
|
}
|
|
if (count($candidates) !== 1) {
|
|
throw new DomainException('药材“' . $name . '”存在多个同名记录,请重新选择具体药材');
|
|
}
|
|
$row = $candidates[0];
|
|
$id = (int) $row['id'];
|
|
}
|
|
|
|
$herb['medicine_id'] = $id;
|
|
$herb['name'] = trim((string) ($row['name'] ?? $name));
|
|
unset($herb['id'], $herb['title'], $herb['local_medicine_id']);
|
|
$resolved[] = $herb;
|
|
}
|
|
|
|
if ($resolved === []) {
|
|
throw new DomainException('处方药材不能为空');
|
|
}
|
|
|
|
return $resolved;
|
|
}
|
|
|
|
/** @param array<string,mixed> $row */
|
|
private static function isActive(array $row): bool
|
|
{
|
|
return (int) ($row['id'] ?? 0) > 0
|
|
&& (int) ($row['status'] ?? 0) === 1
|
|
&& ($row['delete_time'] ?? null) === null;
|
|
}
|
|
}
|