feat(billing): model invoice payment balances and settlement

Persist amounts due and paid, derive partial and full settlement, and protect balances during command updates. Add migration, focused tests and invoicing documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Paul Schneider 2026-10-19 19:32:22 +01:00
commit 5d03b2e477
Signed by: notazof
GPG key ID: AD4B9B545FBD7D12
13 changed files with 5434 additions and 2 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class InvoicePaymentAmounts : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<decimal>(
name: "AmountDue",
table: "NominativeServiceCommands",
type: "numeric",
nullable: true);
migrationBuilder.AddColumn<decimal>(
name: "AmountPaid",
table: "NominativeServiceCommands",
type: "numeric",
nullable: false,
defaultValue: 0m);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AmountDue",
table: "NominativeServiceCommands");
migrationBuilder.DropColumn(
name: "AmountPaid",
table: "NominativeServiceCommands");
}
}
}

View file

@ -17,7 +17,7 @@ namespace Yavsc.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.12")
.HasAnnotation("ProductVersion", "10.0.13")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@ -1454,6 +1454,14 @@ namespace Yavsc.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<decimal?>("AmountDue")
.HasColumnType("numeric");
b.Property<decimal>("AmountPaid")
.ValueGeneratedOnAdd()
.HasColumnType("numeric")
.HasDefaultValue(0m);
b.Property<string>("ClientId")
.IsRequired()
.HasColumnType("text");