8385c23c40
- number_rules 新增 mode(date_seq 日期+序号3位按周期重置 / seq 连续6位)与 seq_period 列 - 单号生成按 mode + date_format 拼接,跨日期周期自动重置;启动回填 product→seq - 商品建号接入 number_rules(seq 模式、前缀可配、从现有最大序列号播种,续发连续编号) - 设置屏:加「模式」列、当前序号按周期显示(未开单显0);编辑弹窗前缀所有类型可改, 有日期的序号系统自动(只读置灰)、可改日期格式,商品编码序号可调大不可调小 - 桌面原型 settings 补「编号规则」面板+编辑弹窗、m-settings 改准;atoms 去数字框原生箭头 - 同步 CONTRACT / screens.mjs / db-schema.html 与 settings fidelity 基准 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bupi8Kdqkfx2N5acFsHTx5
90 lines
2.9 KiB
Dart
90 lines
2.9 KiB
Dart
class NumberRule {
|
||
final int id;
|
||
final String type;
|
||
final String prefix;
|
||
|
||
/// 编号模式:date_seq=日期+序号(3 位,按 dateFormat 周期重置)| seq=连续序号(6 位,不重置)
|
||
final String mode;
|
||
final int currentNo;
|
||
final String dateFormat;
|
||
|
||
/// date_seq 当前序号所属的日期串(如 "20260902"),用于示例的跨周期重置判断;seq 模式为空。
|
||
final String seqPeriod;
|
||
|
||
const NumberRule({
|
||
required this.id,
|
||
required this.type,
|
||
required this.prefix,
|
||
required this.mode,
|
||
required this.currentNo,
|
||
required this.dateFormat,
|
||
required this.seqPeriod,
|
||
});
|
||
|
||
String get typeLabel {
|
||
switch (type) {
|
||
case 'stock_in':
|
||
return '入库单';
|
||
case 'stock_out':
|
||
return '出库单';
|
||
case 'inventory_check':
|
||
return '盘点单';
|
||
case 'product':
|
||
return '商品编码';
|
||
default:
|
||
return type;
|
||
}
|
||
}
|
||
|
||
bool get isSeq => mode == 'seq';
|
||
|
||
String get modeLabel => isSeq ? '连续序号' : '日期 + 序号';
|
||
|
||
/// 展示用「当前序号」:
|
||
/// seq → 原值(连续累计)。
|
||
/// date_seq → 本周期已开始(seqPeriod==今天) 显示本周期计数,否则显示 0
|
||
/// (今天还没生成过,下一张就是 001,故当前=0)。
|
||
int get effectiveCurrentNo {
|
||
if (isSeq) return currentNo;
|
||
return dateStr(dateFormat, DateTime.now()) == seqPeriod ? currentNo : 0;
|
||
}
|
||
|
||
/// 按 dateFormat 生成当天日期串(与后端 formatByRule 一致)。
|
||
static String dateStr(String fmt, DateTime now) {
|
||
final y4 = now.year.toString().padLeft(4, '0');
|
||
final y2 = (now.year % 100).toString().padLeft(2, '0');
|
||
final mo = now.month.toString().padLeft(2, '0');
|
||
final d = now.day.toString().padLeft(2, '0');
|
||
switch (fmt) {
|
||
case 'YYYYMM':
|
||
return '$y4$mo';
|
||
case 'YYMMDD':
|
||
return '$y2$mo$d';
|
||
default: // YYYYMMDD 及未知
|
||
return '$y4$mo$d';
|
||
}
|
||
}
|
||
|
||
/// 下一编号示例(与后端 advanceNumberRule 口径一致):
|
||
/// seq → 前缀 + 6 位连续序号(如 DS031115)
|
||
/// date_seq → 前缀 + 日期串 + 3 位序号;跨日期周期时序号从 001 起
|
||
String get exampleNo {
|
||
if (isSeq) {
|
||
return '$prefix${(currentNo + 1).toString().padLeft(6, '0')}';
|
||
}
|
||
final ds = dateStr(dateFormat, DateTime.now());
|
||
final next = (ds == seqPeriod) ? currentNo + 1 : 1;
|
||
return '$prefix$ds${next.toString().padLeft(3, '0')}';
|
||
}
|
||
|
||
factory NumberRule.fromJson(Map<String, dynamic> json) => NumberRule(
|
||
id: (json['id'] as num).toInt(),
|
||
type: json['type'] as String,
|
||
prefix: json['prefix'] as String? ?? '',
|
||
mode: json['mode'] as String? ?? 'date_seq',
|
||
currentNo: (json['current_no'] as num).toInt(),
|
||
dateFormat: json['date_format'] as String? ?? 'YYYYMMDD',
|
||
seqPeriod: json['seq_period'] as String? ?? '',
|
||
);
|
||
}
|