tane/apps/app_seeds/lib/db/enums.dart
vjrj 6809dc6143 feat(inventory): photo-first drafts + on-device OCR (digitization R2+R4)
Lower the bulk-digitization cliff with two more routes on top of the
already-landed CSV import and "save and add another":

- Photo-first drafts (capture now, catalogue later): burst-capture
  photos (camera or multi-gallery) into unnamed draft varieties, shown
  in a "to catalogue" tray, hidden from the main list until named.
  Adds Variety.isDraft (schema), addDraftVariety/watchDrafts/nameDraft,
  the triage sheet and the inventory banner.
- On-device OCR label suggestion (Tesseract, offline, no Google): a
  "Suggest name from photo" button in the naming dialog behind a
  LabelTextExtractor interface (Tesseract on Android/iOS, no-op
  elsewhere). Reads the largest print via hOCR bounding boxes, drops
  boilerplate/low-confidence noise, preprocesses (grayscale, contrast,
  upscale) and sweeps rotations (0-315 deg) so tilted packets still
  read. Bundles tessdata_fast eng+spa; validated on-device against real
  packets. The photo is written to a temp file deleted immediately in a
  finally block (the plugin needs a path) - a bounded, documented
  exception to no-plaintext-at-rest.

This commit also carries the co-developed schema evolution v5 to v8 that
shares these files (organic flag, species viability years, crop
calendar, lot provenance/abundance/preservation format, condition
checks) plus their exports/migrations and i18n.

Tests: CSV/draft/OCR unit + widget + migration green in isolation.
Note: the full widget suite currently hangs (>10 min) - under investigation.
2026-07-09 21:23:46 +02:00

88 lines
3.8 KiB
Dart

// Domain enums stored by **name** (never by index) via Drift `textEnum`, so
// the stored keys are stable across migrations. Per data-model §5.2, values
// may only be appended, never renumbered or reused; when sync arrives, readers
// must tolerate unknown values (map to a safe default). No sync yet in Block 1.
/// The form in which a lot is held. `seed` is dry seed (the only form
/// germination tests apply to); the rest are living/vegetative material. Values
/// are stored by name and append-only (data-model §5): never renamed/reordered.
///
/// - `seedling` — a young plant grown from seed, to transplant (plantón).
/// - `plant` — an established plant (potted or bare-root).
/// - `tree` — a woody plant: tree or shrub.
/// - `bulb` — a storage organ: bulb, corm, tuber or rhizome.
/// - `cutting` — vegetative propagation material (cutting, scion).
enum LotType { seed, plant, seedling, tree, bulb, cutting }
/// How living plant material is packaged/supplied — an optional attribute of a
/// non-seed [Lot], kept separate from the amount. Append-only by name.
///
/// - `pot` — in a pot/container (maceta/contenedor).
/// - `tray` — in a plug/cell tray (bandeja de alvéolos).
/// - `plug` — a single plug/cell.
/// - `bareRoot` — dormant, roots exposed, no soil (raíz desnuda).
/// - `rootBall` — dug with an intact soil ball (cepellón).
enum Presentation { pot, tray, plug, bareRoot, rootBall }
/// Per-lot visibility (data-model §2.3). Used by the future sharing layer.
enum OfferStatus { private, shared, exchange, sell }
/// A coarse, offline-friendly "how much do I have" that fuses amount with
/// shareability — the way a seed saver actually thinks, without weighing or
/// counting. Modelled on the qualitative scale a real seed bank used
/// (mucha/bastante/suficiente/poca), where each level is defined by what you
/// can do with it. Optional alternative to a precise Quantity. Append-only by
/// name.
///
/// - `plentyToShare` — surplus, free to give away (mucha).
/// - `enoughToShare` — can share a little, sparingly (bastante).
/// - `enoughForMe` — enough for my own use, not to share (suficiente).
/// - `runningLow` — only enough to keep the variety alive (poca).
enum Abundance { plentyToShare, enoughToShare, enoughForMe, runningLow }
/// How dry seed is physically conserved — affects longevity, kept separate from
/// *where* it is stored. Optional attribute of a seed [Lot]. Append-only by name.
///
/// - `jarWithDesiccant` — sealed jar with a drying agent (bote con sílice).
/// - `glassJar` — plain glass jar (bote de cristal).
/// - `paperEnvelope` — paper envelope (sobre de papel).
/// - `paperBag` — paper bag (bolsa de papel).
/// - `plasticBag` — plastic bag (bolsa de plástico).
enum PreservationFormat {
jarWithDesiccant,
glassJar,
paperEnvelope,
paperBag,
plasticBag,
}
/// State of the drying agent (silica gel) in a stored seed container, recorded
/// at a periodic condition check. The colour is a proxy for moisture: a
/// saturated agent means the seed is at risk. Append-only by name.
///
/// - `none` — no drying agent present (no tiene).
/// - `add` — should add some (se pone).
/// - `replace` — saturated, replace it (se cambia).
/// - `dry` — indicating dry (azul/blue).
/// - `fresh` — just renewed (lila/violet).
enum DesiccantState { none, add, replace, dry, fresh }
/// Append-only event kinds on a Lot (data-model §2.4).
enum MovementType {
received,
given,
sown,
harvested,
germinationTest,
split,
discarded,
}
/// A counterparty is a person or a collective (data-model §2.5).
enum PartyKind { person, collective }
/// Attachment media kind (data-model §2.1).
enum AttachmentKind { photo, doc }
/// Polymorphic parent of an Attachment / ExternalLink.
enum ParentType { variety, lot, movement }