Add hierarchical invoice position numbering (ADR 0017)
Adds the InvoiceLineNumbering class that InvoiceDraftCalculator.
RecomputePositions, InvoiceSetPricing.AssignPositionLabels and their
callers already depend on (this dependency was pushed in ecc74cf
without the class itself, breaking the build) — position labels are
now hierarchical ("1", "1.1", "1.2", …) matching a line's ADR 0016
nesting level, computed by one pure, shared algorithm for both the
online editor and the PDF so they can never disagree (ADR 0008).
Also fixes an InvoiceDraftServiceTests assertion that still expected
the old flat integer position field; it is a string label now.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
namespace Fuchs.intranet;
|
||||
|
||||
/// <summary>
|
||||
/// Computes hierarchical invoice position labels ("1", "1.1", "1.2", "2", …) from a
|
||||
/// depth-first-ordered sequence of lines (ADR 0017). A set header gets a number at its own
|
||||
/// level; its members get subsidiary numbers one level deeper. Text/Title lines get no label
|
||||
/// and do not consume a counter slot at any level. Callers must supply lines already in final
|
||||
/// document order — <see cref="InvoiceSetStructure.Linearize"/> and
|
||||
/// <see cref="InvoiceSetPricing.Build"/> both already guarantee that.
|
||||
/// </summary>
|
||||
public static class InvoiceLineNumbering
|
||||
{
|
||||
public static IReadOnlyList<string> Compute(IReadOnlyList<(bool Numbered, int Level)> lines)
|
||||
{
|
||||
var result = new List<string>(lines.Count);
|
||||
var counters = new List<int>();
|
||||
foreach (var (numbered, level) in lines)
|
||||
{
|
||||
if (!numbered) { result.Add(""); continue; }
|
||||
int lvl = Math.Max(level, 0);
|
||||
while (counters.Count <= lvl) counters.Add(0);
|
||||
if (counters.Count > lvl + 1) counters.RemoveRange(lvl + 1, counters.Count - lvl - 1);
|
||||
counters[lvl]++;
|
||||
result.Add(string.Join(".", counters));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user