Files
tcpserver-flow/app/flow/context/bean/BatchNo.php
T
zimoyin f2ff4ae123 ai-chore(config): 调整流程配置及改进测试代码
- 将 FLOW_USE_CUSTOM_PROCESS 从 true 改为 false,禁用自定义流程
- 在 BlockTest 测试用例中改用 setBlockMode 方法设置阻断模式
- 设置统一的错误处理,将错误转为异常抛出
- 重命名 BlockTest 测试文件路径,优化测试组织结构
- 更新 IDE php include paths,调整依赖包引用顺序
- 删除无用的 tests/flow/Test.php 测试文件
- 微调 start.php、webman、windows.php 配置或代码模块
2026-03-11 13:48:40 +08:00

197 lines
4.4 KiB
PHP

<?php
namespace app\flow\context\bean;
use app\config\Config;
use app\repository\EctActionsRepository;
/**
* 批次号值对象
* 封装批次号相关操作(不可变)
*/
readonly class BatchNo
{
public function __construct(
/** 批次号值 */
public string $value = '',
)
{
}
/**
* 创建空批次号
*/
public static function empty(): self
{
return new self(value: '');
}
/**
* 从字符串创建
*/
public static function fromString(string $value): self
{
return new self(value: $value);
}
/**
* 生成新批次号
*/
public static function generate(?string $machineId = null): self
{
$config = Config::getInstance();
$machineId = $machineId ?? $config->machineId;
$existingBatchNo = EctActionsRepository::new()->findTodayActiveBatchNo($machineId);
$datePart = date('Ymd');
$sequence = 1;
if (!empty($existingBatchNo)) {
$existingDatePart = substr($existingBatchNo, 0, 8);
$existingSequence = substr($existingBatchNo, 10, 4);
if ($existingDatePart === $datePart && is_numeric($existingSequence)) {
$sequence = (int)$existingSequence + 1;
}
}
$sequencePart = str_pad($sequence, 4, '0', STR_PAD_LEFT);
return new self(value: $datePart . $machineId . $sequencePart);
}
/**
* 解析批次号结构
*
* @return array{date: string, machineId: string, sequence: int, dateFormatted: string}
*/
public function parse(): array
{
if (!$this->isValid()) {
return [
'date' => '',
'machineId' => '',
'sequence' => 0,
'dateFormatted' => '',
];
}
$datePart = substr($this->value, 0, 8);
$machineId = substr($this->value, 8, 2);
$sequence = (int)substr($this->value, 10, 4);
return [
'date' => $datePart,
'machineId' => $machineId,
'sequence' => $sequence,
'dateFormatted' => substr($datePart, 0, 4) . '-' . substr($datePart, 4, 2) . '-' . substr($datePart, 6, 2),
];
}
/**
* 解析批次号结构
* @deprecated
* @return array{date: string, machineId: string, sequence: int, dateFormatted: string}
*/
public static function parseBatchNo(string $batchNo): array
{
$batch = BatchNo::fromString($batchNo);
if (!$batch->isValid()) {
throw new \InvalidArgumentException('Invalid batch string: ' . $batchNo);
}
return $batch->parse();
}
/**
* 验证批次号格式是否有效
*/
public function isValid(): bool
{
// 批次号格式: YYYYMMDD + 机器ID(2位) + 序号(4位) = 14位
if (strlen($this->value) !== 14) {
return false;
}
$datePart = substr($this->value, 0, 8);
$sequencePart = substr($this->value, 10, 4);
// 验证日期部分
if (!is_numeric($datePart)) {
return false;
}
// 验证序号部分
if (!is_numeric($sequencePart)) {
return false;
}
return true;
}
/**
* 是否为空批次号
*/
public function isEmpty(): bool
{
return empty($this->value);
}
/**
* 获取日期部分
*/
public function getDateStr(): string
{
$parsed = $this->parse();
return $parsed['dateFormatted'];
}
/**
* 获取时间戳
* @return int|false
*/
public function getTimestamp(): int|false
{
$parsed = $this->parse();
return strtotime($parsed['dateFormatted']);
}
/**
* 获取机器ID
*/
public function getMachineId(): string
{
$parsed = $this->parse();
return $parsed['machineId'];
}
/**
* 获取序号
*/
public function getSequence(): int
{
$parsed = $this->parse();
return $parsed['sequence'];
}
/**
* 是否是今天的批次号
*/
public function isToday(): bool
{
if (!$this->isValid()) {
return false;
}
$datePart = substr($this->value, 0, 8);
return $datePart === date('Ymd');
}
/**
* 转换为字符串
*/
public function __toString(): string
{
return $this->value;
}
}