Zweiteinheit am Artikel: Bruecke zwischen Stueck, Gramm und Milliliter
Die drei Einheiten-Arten waren bisher strikt getrennt: BASE_OF_KIND bildet count/weight/volume 1:1 auf Stueck/Gramm/Milliliter ab, ohne jeden Faktor dazwischen. Zwei Stellen setzten das durch - to_base lehnte artfremde Einheiten beim Ein-/Auslagern ab, und group_min_context filterte stueckweise gefuehrte Artikel aus einer Kilogramm-Gruppe stillschweigend heraus. Letzteres war der Anlass: eine Gruppe "Wurst" in kg sah Bratwuerste in Stueck gar nicht. Ein Artikel darf jetzt eine Zweiteinheit tragen: "3 Stueck ≙ 250 g". Gespeichert wird das eingegebene PAAR, nicht der Faktor - wer 3 und 250 eintippt, sieht beim naechsten Oeffnen genau das wieder. Das hat auch einen rechnerischen Grund: 250 * 3 / 250 ist exakt 3, der Umweg ueber 250/3 ergibt 3,0000000000000004 und liefe damit gegen die Bestandspruefung beim Auslagern. Der Artikel bleibt in seiner Basiseinheit gefuehrt; die Bruecke ist reine Rechnung. Gruppen zaehlen artfremde Artikel jetzt mit ihrem Faktor mit (GroupMinContext.faktoren), Bestandssummen laufen dafuer je Artikel gewichtet - weiterhin zwei Abfragen, nur mit GROUP BY. Ein-/Auslagern in der Fremdeinheit geht, krumme Mengen werden bewusst gebucht statt gerundet: 100 g sind 1,2 Stueck, und Runden wuerde stumm etwas anderes buchen als angegeben. WICHTIGE KORREKTUR am urspruenglichen Plan: die Teilmengen-Bedingung in _gruppen_bedarfe konnte NICHT bleiben. Sie war bisher zugleich ein Einheiten-Schutz, weil Artikel verschiedener Arten zwangslaeufig disjunkt waren. Mit der Bruecke gilt sie ploetzlich auch zwischen einer Stueck- und einer Gramm-Gruppe - und _netted_topups haette einen Bedarf in Stueck von einem in Gramm abgezogen. Jetzt wird nur noch zwischen Gruppen derselben Basiseinheit verrechnet. Open Food Facts: "3 x 80 g" verlor bisher den Multiplikator, weil der Regex den ersten Zahl-Einheit-Treffer nahm. parse_gebinde liefert jetzt Gesamtmenge UND Stueckzahl und belegt die Zweiteinheit vor; parse_quantity behaelt seinen schmalen Vertrag. 18 neue Tests. Dass test_wrong_kind_rejected und test_einheitenfilter_gilt_auch_fuer_untergruppen unveraendert gruen bleiben, ist selbst der Beleg: ohne Bruecke aendert sich nichts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -315,6 +315,12 @@ class ProductBase(BaseModel):
|
||||
package_size: float | None = Field(default=None, gt=0)
|
||||
# Bezeichnung eines Gebindes ("Packung", "Glas", "Tüte", …)
|
||||
package_label: str | None = Field(default=None, max_length=32)
|
||||
# Zweiteinheit: Bruecke zwischen den Einheiten-Arten („3 Stück ≙ 250 g").
|
||||
# ``secondary_count`` zaehlt in der Basiseinheit des Artikels,
|
||||
# ``secondary_amount`` in ``secondary_base``. Alle drei oder keines.
|
||||
secondary_base: BaseUnit | None = None
|
||||
secondary_count: float | None = Field(default=None, gt=0)
|
||||
secondary_amount: float | None = Field(default=None, gt=0)
|
||||
# Voreingestellte MHD-Genauigkeit dieses Produkts (z.B. Konserven: nur Monat).
|
||||
date_precision: DatePrecision = DatePrecision.day
|
||||
group_id: int | None = None
|
||||
@@ -348,6 +354,12 @@ class ProductUpdate(BaseModel):
|
||||
unit_id: int | None = None
|
||||
package_size: float | None = Field(default=None, gt=0)
|
||||
package_label: str | None = Field(default=None, max_length=32)
|
||||
# Zweiteinheit: Bruecke zwischen den Einheiten-Arten („3 Stück ≙ 250 g").
|
||||
# ``secondary_count`` zaehlt in der Basiseinheit des Artikels,
|
||||
# ``secondary_amount`` in ``secondary_base``. Alle drei oder keines.
|
||||
secondary_base: BaseUnit | None = None
|
||||
secondary_count: float | None = Field(default=None, gt=0)
|
||||
secondary_amount: float | None = Field(default=None, gt=0)
|
||||
date_precision: DatePrecision | None = None
|
||||
group_id: int | None = None
|
||||
category_id: int | None = None
|
||||
@@ -372,6 +384,13 @@ class ProductOut(BaseModel):
|
||||
display_unit_id: int | None = None
|
||||
package_size: float | None
|
||||
package_label: str | None = None
|
||||
# Zweiteinheit-Brücke, so wie eingegeben („3 Stück ≙ 250 g").
|
||||
secondary_base: BaseUnit | None = None
|
||||
secondary_count: float | None = None
|
||||
secondary_amount: float | None = None
|
||||
# Abgeleitet: Zweit-Basiseinheiten je EINER Basiseinheit des Artikels –
|
||||
# damit die Oberflächen nicht selbst dividieren müssen.
|
||||
secondary_factor: float | None = None
|
||||
date_precision: DatePrecision = DatePrecision.day
|
||||
group_id: int | None
|
||||
category_id: int | None = None
|
||||
|
||||
Reference in New Issue
Block a user