feat(automation): separate lot number counters per raw material kind
With {ART} in the raw material number format (default {ART}-{YYYY}-{SEQ:4}),
beeswax and propolis each count on their own: WA-2026-0001, PR-2026-0001.
Counters live in the new AutomationSequence table (one row per rule and
scope). Without {ART} the rule keeps its single shared counter, since
separate counters behind one prefix would hand out duplicate numbers.
Resetting a rule clears all of its counters.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
5408711b2d
commit
cfd3a187af
9 files changed
+252
-24
No files matched your search
@@ -74,7 +74,13 @@ const MIN_GRAMS_FIELDS: { kind: "BEESWAX" | "PROPOLIS"; label: string }[] = [
|
||||
{ kind: "PROPOLIS", label: "Mindestmenge Propolis (g)" },
|
||||
];
|
||||
|
||||
type MinGrams = Partial<Record<"BEESWAX" | "PROPOLIS", string>>;
|
||||
// Same codes as RAW_MATERIAL_KIND_CODES in the backend.
|
||||
const RAW_KIND_CODES: { kind: "BEESWAX" | "PROPOLIS"; code: string; label: string }[] = [
|
||||
{ kind: "BEESWAX", code: "WA", label: "Bienenwachs" },
|
||||
{ kind: "PROPOLIS", code: "PR", label: "Propolis" },
|
||||
];
|
||||
|
||||
type MinGrams =Partial<Record<"BEESWAX" | "PROPOLIS", string>>;
|
||||
|
||||
function ruleMinGrams(rule: AutomationRule): MinGrams {
|
||||
const config = rule.config as { minGrams?: Record<string, unknown> } | null;
|
||||
@@ -126,6 +132,11 @@ function RuleCard({ rule }: { rule: AutomationRule }) {
|
||||
const [dueInDays, setDueInDays] = useState(ruleDueInDays(rule));
|
||||
const [minGrams, setMinGrams] = useState<MinGrams>(ruleMinGrams(rule));
|
||||
const numberFormatRule = isNumberFormatRule(rule);
|
||||
const rawFormatRule = rule.triggerType === "RAW_MATERIAL_LOT_NUMBER_FORMAT";
|
||||
// Mirrors the backend: separate counters only while {ART} is in the format.
|
||||
const perKind = rawFormatRule && format.includes("{ART}");
|
||||
const kindSequence = (kind: string) =>
|
||||
rule.sequences?.find((sequence) => sequence.scope === kind)?.value ?? 0;
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: (input: { active?: boolean; config?: Record<string, unknown>; actionTemplate?: string }) =>
|
||||
@@ -194,18 +205,43 @@ function RuleCard({ rule }: { rule: AutomationRule }) {
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Platzhalter: {"{YYYY}"} Jahr, {"{MM}"} Monat, {"{DD}"} Tag, {"{SEQ}"} laufende
|
||||
Nummer, {"{SEQ:4}"} mit führenden Nullen auf 4 Stellen.
|
||||
{rawFormatRule
|
||||
? ` ${"{ART}"} Kürzel der Art (WA = Bienenwachs, PR = Propolis) – mit ${"{ART}"} zählt jede Art für sich, ohne gibt es einen gemeinsamen Zähler.`
|
||||
: null}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Aktueller Zähler: {rule.sequenceValue}
|
||||
</p>
|
||||
{rule.active ? (
|
||||
<p className="text-sm font-medium">
|
||||
Beispiel für die nächste Nummer:{" "}
|
||||
<span className="font-mono">
|
||||
{formatGeneratedNumber(format, rule.sequenceValue + 1, new Date())}
|
||||
</span>
|
||||
</p>
|
||||
) : null}
|
||||
{perKind ? (
|
||||
<ul className="flex flex-col gap-1 text-xs text-muted-foreground">
|
||||
{RAW_KIND_CODES.map(({ kind, code, label }) => (
|
||||
<li key={kind}>
|
||||
Zähler {label}: {kindSequence(kind)}
|
||||
{rule.active ? (
|
||||
<>
|
||||
{" "}– nächste Nummer{" "}
|
||||
<span className="font-mono text-foreground">
|
||||
{formatGeneratedNumber(format, kindSequence(kind) + 1, new Date(), {
|
||||
ART: code,
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
) : null}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Aktueller Zähler: {rule.sequenceValue}
|
||||
</p>
|
||||
{rule.active ? (
|
||||
<p className="text-sm font-medium">
|
||||
Beispiel für die nächste Nummer:{" "}
|
||||
<span className="font-mono">
|
||||
{formatGeneratedNumber(format, rule.sequenceValue + 1, new Date())}
|
||||
</span>
|
||||
</p>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-2">
|
||||
|
||||
Reference in new issue
Block a user