Add unit-of-measure catalog foundation
Phase 1 of structured quantities + UoM. Introduces a global UnitOfMeasure catalog (Code-keyed for stable backend lookup of canonical units like "each") and FamilyUnitOfMeasure for family-scoped customs, mirroring the product-catalog pattern. Endpoints expose the merged effective catalog plus CRUD for family customs. Abbreviation uniqueness is enforced per table at the DB layer and across tables at the API layer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,49 @@ namespace YesChef.Api.Migrations
|
||||
b.ToTable("FamilyProductOverrides");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("YesChef.Api.Entities.FamilyUnitOfMeasure", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Abbreviation")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<int>("Category")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("FamilyId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("PluralName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("SingularName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FamilyId", "Abbreviation")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("FamilyUnitsOfMeasure");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("YesChef.Api.Entities.Invite", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -566,6 +609,57 @@ namespace YesChef.Api.Migrations
|
||||
b.ToTable("StoreSections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("YesChef.Api.Entities.UnitOfMeasure", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Abbreviation")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<int>("Category")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<bool>("IsBase")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("PluralName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("SingularName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Abbreviation")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Code")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("UnitsOfMeasure");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("YesChef.Api.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -654,6 +748,17 @@ namespace YesChef.Api.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("YesChef.Api.Entities.FamilyUnitOfMeasure", b =>
|
||||
{
|
||||
b.HasOne("YesChef.Api.Entities.Family", "Family")
|
||||
.WithMany()
|
||||
.HasForeignKey("FamilyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Family");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("YesChef.Api.Entities.Invite", b =>
|
||||
{
|
||||
b.HasOne("YesChef.Api.Entities.User", "ConsumedByUser")
|
||||
|
||||
Reference in New Issue
Block a user