first version

This commit is contained in:
liu
2026-07-23 20:41:25 +08:00
parent 00a0938a1b
commit 10cff754a4
211 changed files with 11577 additions and 842 deletions
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;
/**
* 单号生成服务
*
* 规则:前缀 + yyyyMMdd + 4 位序列,如 PO202607230001
* 按「前缀+当日」已生成的最大序列自增。
*
* 并发安全提示:本服务取当日最大单号 +1,依赖各单号字段的唯一索引兜底,
* 高并发生成场景(如采购单汇总)须在事务内配合行锁调用(见 PurchaseGenerateService)。
*/
class BillNumberService
{
/**
* 前缀 → [表名, 单号字段] 映射
*
* @var array<string, array{0: string, 1: string}>
*/
private const NUMBER_SOURCES = [
'PO' => ['purchase_order', 'purchase_no'],
'SO' => ['store_order', 'order_no'],
'RC' => ['reconciliation', 'recon_no'],
'ST' => ['statement', 'statement_no'],
'JS' => ['settlement', 'settlement_no'],
];
/**
* 生成业务单号
*
* @param string $prefix 业务前缀:PO 采购单 / SO 订货单 / RC 对账 / ST 对账单 / JS 结算
* @return string 如 PO202607230001
*/
public function make(string $prefix): string
{
$prefix = strtoupper($prefix);
$source = self::NUMBER_SOURCES[$prefix]
?? throw new InvalidArgumentException('不支持的单号前缀:' . $prefix);
[$table, $column] = $source;
$datePrefix = $prefix . now()->format('Ymd');
$maxNo = DB::table($table)
->where($column, 'like', $datePrefix . '%')
->lockForUpdate()
->max($column);
$sequence = 1;
if (is_string($maxNo) && $maxNo !== '') {
$sequence = ((int) substr($maxNo, strlen($datePrefix))) + 1;
}
return $datePrefix . str_pad((string) $sequence, 4, '0', STR_PAD_LEFT);
}
}