From 3954c62aa6c0a5593d676b17c5289645236367c8 Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 9 Jul 2026 11:51:21 +0200 Subject: [PATCH] =?UTF-8?q?feat(db):=20lot=20presentation=20+=20attachment?= =?UTF-8?q?=20sort=20order=20(schema=20v4=E2=86=92v5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expand LotType from {seed, plant} to six append-only forms (seed, seedling, plant, tree, bulb, cutting) and add an optional Presentation attribute (pot/tray/plug/bareRoot/rootBall) kept separate from quantity so 'how many' and 'in what packaging' never conflate. Add attachments.sortOrder so the cover photo is the lowest-ordered one, enabling reordering from the full-screen viewer. Expand QuantityKind with the new plant-aware forms. Migrations are additive (v1→v5 all covered by migration_test); enum values are stored by name and appended only, keeping CRDT sync safe. --- .../drift_schemas/drift_schema_v4.json | 1495 ++++++++++++++++ .../drift_schemas/drift_schema_v5.json | 1505 +++++++++++++++++ .../lib/data/variety_repository.dart | 62 +- apps/app_seeds/lib/db/database.dart | 12 +- apps/app_seeds/lib/db/database.g.dart | 158 +- apps/app_seeds/lib/db/enums.dart | 23 +- apps/app_seeds/lib/db/tables.dart | 8 + .../lib/state/variety_detail_cubit.dart | 7 + .../test/data/variety_detail_test.dart | 37 + apps/app_seeds/test/db/migration_test.dart | 42 +- apps/app_seeds/test/db/schema/schema.dart | 8 +- apps/app_seeds/test/db/schema/schema_v4.dart | 1408 +++++++++++++++ apps/app_seeds/test/db/schema/schema_v5.dart | 1418 ++++++++++++++++ docs/design/data-model.md | 15 + docs/design/open-decisions.md | 1 + .../commons_core/lib/src/value/quantity.dart | 7 +- 16 files changed, 6174 insertions(+), 32 deletions(-) create mode 100644 apps/app_seeds/drift_schemas/drift_schema_v4.json create mode 100644 apps/app_seeds/drift_schemas/drift_schema_v5.json create mode 100644 apps/app_seeds/test/db/schema/schema_v4.dart create mode 100644 apps/app_seeds/test/db/schema/schema_v5.dart diff --git a/apps/app_seeds/drift_schemas/drift_schema_v4.json b/apps/app_seeds/drift_schemas/drift_schema_v4.json new file mode 100644 index 0000000..2e4f090 --- /dev/null +++ b/apps/app_seeds/drift_schemas/drift_schema_v4.json @@ -0,0 +1,1495 @@ +{ + "_meta": { + "description": "This file contains a serialized version of schema entities for drift.", + "version": "1.3.0" + }, + "options": { + "store_date_time_values_as_text": false + }, + "entities": [ + { + "id": 0, + "references": [], + "type": "table", + "data": { + "name": "varieties", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "label", + "getter_name": "label", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "species_id", + "getter_name": "speciesId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "cultivar_name", + "getter_name": "cultivarName", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "category", + "getter_name": "category", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "notes", + "getter_name": "notes", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 1, + "references": [], + "type": "table", + "data": { + "name": "variety_vernacular_names", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "variety_id", + "getter_name": "varietyId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "language", + "getter_name": "language", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "region", + "getter_name": "region", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 2, + "references": [], + "type": "table", + "data": { + "name": "species", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "scientific_name", + "getter_name": "scientificName", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "wikidata_qid", + "getter_name": "wikidataQid", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "gbif_key", + "getter_name": "gbifKey", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "family", + "getter_name": "family", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_bundled", + "getter_name": "isBundled", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_bundled\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_bundled\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 3, + "references": [], + "type": "table", + "data": { + "name": "species_common_names", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "species_id", + "getter_name": "speciesId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "language", + "getter_name": "language", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 4, + "references": [], + "type": "table", + "data": { + "name": "lots", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "variety_id", + "getter_name": "varietyId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'seed\\'')", + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(LotType.values)", + "dart_type_name": "LotType" + } + }, + { + "name": "harvest_year", + "getter_name": "harvestYear", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "harvest_month", + "getter_name": "harvestMonth", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_kind", + "getter_name": "quantityKind", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_precise", + "getter_name": "quantityPrecise", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_label", + "getter_name": "quantityLabel", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "presentation", + "getter_name": "presentation", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(Presentation.values)", + "dart_type_name": "Presentation" + } + }, + { + "name": "storage_location", + "getter_name": "storageLocation", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "offer_status", + "getter_name": "offerStatus", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'private\\'')", + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(OfferStatus.values)", + "dart_type_name": "OfferStatus" + } + }, + { + "name": "seedbank_id", + "getter_name": "seedbankId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 5, + "references": [], + "type": "table", + "data": { + "name": "germination_tests", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "lot_id", + "getter_name": "lotId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "tested_on", + "getter_name": "testedOn", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "sample_size", + "getter_name": "sampleSize", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "germinated_count", + "getter_name": "germinatedCount", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "notes", + "getter_name": "notes", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 6, + "references": [], + "type": "table", + "data": { + "name": "movements", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "lot_id", + "getter_name": "lotId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(MovementType.values)", + "dart_type_name": "MovementType" + } + }, + { + "name": "occurred_on", + "getter_name": "occurredOn", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "counterparty_id", + "getter_name": "counterpartyId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_kind", + "getter_name": "quantityKind", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_precise", + "getter_name": "quantityPrecise", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_label", + "getter_name": "quantityLabel", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "parent_movement_id", + "getter_name": "parentMovementId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "plantare_id", + "getter_name": "plantareId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "notes", + "getter_name": "notes", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 7, + "references": [], + "type": "table", + "data": { + "name": "parties", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "display_name", + "getter_name": "displayName", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "public_key", + "getter_name": "publicKey", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "kind", + "getter_name": "kind", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'person\\'')", + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(PartyKind.values)", + "dart_type_name": "PartyKind" + } + }, + { + "name": "note", + "getter_name": "note", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 8, + "references": [], + "type": "table", + "data": { + "name": "attachments", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "parent_type", + "getter_name": "parentType", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(ParentType.values)", + "dart_type_name": "ParentType" + } + }, + { + "name": "parent_id", + "getter_name": "parentId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "kind", + "getter_name": "kind", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(AttachmentKind.values)", + "dart_type_name": "AttachmentKind" + } + }, + { + "name": "uri", + "getter_name": "uri", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "bytes", + "getter_name": "bytes", + "moor_type": "blob", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "mime_type", + "getter_name": "mimeType", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 9, + "references": [], + "type": "table", + "data": { + "name": "external_links", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "parent_type", + "getter_name": "parentType", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(ParentType.values)", + "dart_type_name": "ParentType" + } + }, + { + "name": "parent_id", + "getter_name": "parentId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "url", + "getter_name": "url", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "title", + "getter_name": "title", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + } + ], + "fixed_sql": [ + { + "name": "varieties", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"varieties\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"label\" TEXT NOT NULL, \"species_id\" TEXT NULL, \"cultivar_name\" TEXT NULL, \"category\" TEXT NULL, \"notes\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "variety_vernacular_names", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"variety_vernacular_names\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"variety_id\" TEXT NOT NULL, \"name\" TEXT NOT NULL, \"language\" TEXT NULL, \"region\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "species", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"species\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"scientific_name\" TEXT NOT NULL, \"wikidata_qid\" TEXT NULL, \"gbif_key\" INTEGER NULL, \"family\" TEXT NULL, \"is_bundled\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_bundled\" IN (0, 1)), PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "species_common_names", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"species_common_names\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"species_id\" TEXT NOT NULL, \"name\" TEXT NOT NULL, \"language\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "lots", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"lots\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"variety_id\" TEXT NOT NULL, \"type\" TEXT NOT NULL DEFAULT 'seed', \"harvest_year\" INTEGER NULL, \"harvest_month\" INTEGER NULL, \"quantity_kind\" TEXT NULL, \"quantity_precise\" REAL NULL, \"quantity_label\" TEXT NULL, \"presentation\" TEXT NULL, \"storage_location\" TEXT NULL, \"offer_status\" TEXT NOT NULL DEFAULT 'private', \"seedbank_id\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "germination_tests", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"germination_tests\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"lot_id\" TEXT NOT NULL, \"tested_on\" INTEGER NULL, \"sample_size\" INTEGER NULL, \"germinated_count\" INTEGER NULL, \"notes\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "movements", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"movements\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"last_author\" TEXT NOT NULL, \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"lot_id\" TEXT NOT NULL, \"type\" TEXT NOT NULL, \"occurred_on\" INTEGER NULL, \"counterparty_id\" TEXT NULL, \"quantity_kind\" TEXT NULL, \"quantity_precise\" REAL NULL, \"quantity_label\" TEXT NULL, \"parent_movement_id\" TEXT NULL, \"plantare_id\" TEXT NULL, \"notes\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "parties", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"parties\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"display_name\" TEXT NOT NULL, \"public_key\" TEXT NULL, \"kind\" TEXT NOT NULL DEFAULT 'person', \"note\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "attachments", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"attachments\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"parent_type\" TEXT NOT NULL, \"parent_id\" TEXT NOT NULL, \"kind\" TEXT NOT NULL, \"uri\" TEXT NULL, \"bytes\" BLOB NULL, \"mime_type\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "external_links", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"external_links\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"parent_type\" TEXT NOT NULL, \"parent_id\" TEXT NOT NULL, \"url\" TEXT NOT NULL, \"title\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + } + ] +} \ No newline at end of file diff --git a/apps/app_seeds/drift_schemas/drift_schema_v5.json b/apps/app_seeds/drift_schemas/drift_schema_v5.json new file mode 100644 index 0000000..50d4660 --- /dev/null +++ b/apps/app_seeds/drift_schemas/drift_schema_v5.json @@ -0,0 +1,1505 @@ +{ + "_meta": { + "description": "This file contains a serialized version of schema entities for drift.", + "version": "1.3.0" + }, + "options": { + "store_date_time_values_as_text": false + }, + "entities": [ + { + "id": 0, + "references": [], + "type": "table", + "data": { + "name": "varieties", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "label", + "getter_name": "label", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "species_id", + "getter_name": "speciesId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "cultivar_name", + "getter_name": "cultivarName", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "category", + "getter_name": "category", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "notes", + "getter_name": "notes", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 1, + "references": [], + "type": "table", + "data": { + "name": "variety_vernacular_names", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "variety_id", + "getter_name": "varietyId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "language", + "getter_name": "language", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "region", + "getter_name": "region", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 2, + "references": [], + "type": "table", + "data": { + "name": "species", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "scientific_name", + "getter_name": "scientificName", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "wikidata_qid", + "getter_name": "wikidataQid", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "gbif_key", + "getter_name": "gbifKey", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "family", + "getter_name": "family", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_bundled", + "getter_name": "isBundled", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_bundled\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_bundled\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 3, + "references": [], + "type": "table", + "data": { + "name": "species_common_names", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "species_id", + "getter_name": "speciesId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "language", + "getter_name": "language", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 4, + "references": [], + "type": "table", + "data": { + "name": "lots", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "variety_id", + "getter_name": "varietyId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'seed\\'')", + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(LotType.values)", + "dart_type_name": "LotType" + } + }, + { + "name": "harvest_year", + "getter_name": "harvestYear", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "harvest_month", + "getter_name": "harvestMonth", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_kind", + "getter_name": "quantityKind", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_precise", + "getter_name": "quantityPrecise", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_label", + "getter_name": "quantityLabel", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "presentation", + "getter_name": "presentation", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(Presentation.values)", + "dart_type_name": "Presentation" + } + }, + { + "name": "storage_location", + "getter_name": "storageLocation", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "offer_status", + "getter_name": "offerStatus", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'private\\'')", + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(OfferStatus.values)", + "dart_type_name": "OfferStatus" + } + }, + { + "name": "seedbank_id", + "getter_name": "seedbankId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 5, + "references": [], + "type": "table", + "data": { + "name": "germination_tests", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "lot_id", + "getter_name": "lotId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "tested_on", + "getter_name": "testedOn", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "sample_size", + "getter_name": "sampleSize", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "germinated_count", + "getter_name": "germinatedCount", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "notes", + "getter_name": "notes", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 6, + "references": [], + "type": "table", + "data": { + "name": "movements", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "lot_id", + "getter_name": "lotId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(MovementType.values)", + "dart_type_name": "MovementType" + } + }, + { + "name": "occurred_on", + "getter_name": "occurredOn", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "counterparty_id", + "getter_name": "counterpartyId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_kind", + "getter_name": "quantityKind", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_precise", + "getter_name": "quantityPrecise", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quantity_label", + "getter_name": "quantityLabel", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "parent_movement_id", + "getter_name": "parentMovementId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "plantare_id", + "getter_name": "plantareId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "notes", + "getter_name": "notes", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 7, + "references": [], + "type": "table", + "data": { + "name": "parties", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "display_name", + "getter_name": "displayName", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "public_key", + "getter_name": "publicKey", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "kind", + "getter_name": "kind", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'person\\'')", + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(PartyKind.values)", + "dart_type_name": "PartyKind" + } + }, + { + "name": "note", + "getter_name": "note", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 8, + "references": [], + "type": "table", + "data": { + "name": "attachments", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "parent_type", + "getter_name": "parentType", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(ParentType.values)", + "dart_type_name": "ParentType" + } + }, + { + "name": "parent_id", + "getter_name": "parentId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "kind", + "getter_name": "kind", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(AttachmentKind.values)", + "dart_type_name": "AttachmentKind" + } + }, + { + "name": "uri", + "getter_name": "uri", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "bytes", + "getter_name": "bytes", + "moor_type": "blob", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "mime_type", + "getter_name": "mimeType", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "sort_order", + "getter_name": "sortOrder", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + }, + { + "id": 9, + "references": [], + "type": "table", + "data": { + "name": "external_links", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "last_author", + "getter_name": "lastAuthor", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_deleted", + "getter_name": "isDeleted", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_deleted\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_deleted\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "schema_row_version", + "getter_name": "schemaRowVersion", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "parent_type", + "getter_name": "parentType", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumNameConverter(ParentType.values)", + "dart_type_name": "ParentType" + } + }, + { + "name": "parent_id", + "getter_name": "parentId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "url", + "getter_name": "url", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "title", + "getter_name": "title", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": false, + "constraints": [], + "explicit_pk": [ + "id" + ] + } + } + ], + "fixed_sql": [ + { + "name": "varieties", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"varieties\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"label\" TEXT NOT NULL, \"species_id\" TEXT NULL, \"cultivar_name\" TEXT NULL, \"category\" TEXT NULL, \"notes\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "variety_vernacular_names", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"variety_vernacular_names\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"variety_id\" TEXT NOT NULL, \"name\" TEXT NOT NULL, \"language\" TEXT NULL, \"region\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "species", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"species\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"scientific_name\" TEXT NOT NULL, \"wikidata_qid\" TEXT NULL, \"gbif_key\" INTEGER NULL, \"family\" TEXT NULL, \"is_bundled\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_bundled\" IN (0, 1)), PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "species_common_names", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"species_common_names\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"species_id\" TEXT NOT NULL, \"name\" TEXT NOT NULL, \"language\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "lots", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"lots\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"variety_id\" TEXT NOT NULL, \"type\" TEXT NOT NULL DEFAULT 'seed', \"harvest_year\" INTEGER NULL, \"harvest_month\" INTEGER NULL, \"quantity_kind\" TEXT NULL, \"quantity_precise\" REAL NULL, \"quantity_label\" TEXT NULL, \"presentation\" TEXT NULL, \"storage_location\" TEXT NULL, \"offer_status\" TEXT NOT NULL DEFAULT 'private', \"seedbank_id\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "germination_tests", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"germination_tests\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"lot_id\" TEXT NOT NULL, \"tested_on\" INTEGER NULL, \"sample_size\" INTEGER NULL, \"germinated_count\" INTEGER NULL, \"notes\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "movements", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"movements\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"last_author\" TEXT NOT NULL, \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"lot_id\" TEXT NOT NULL, \"type\" TEXT NOT NULL, \"occurred_on\" INTEGER NULL, \"counterparty_id\" TEXT NULL, \"quantity_kind\" TEXT NULL, \"quantity_precise\" REAL NULL, \"quantity_label\" TEXT NULL, \"parent_movement_id\" TEXT NULL, \"plantare_id\" TEXT NULL, \"notes\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "parties", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"parties\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"display_name\" TEXT NOT NULL, \"public_key\" TEXT NULL, \"kind\" TEXT NOT NULL DEFAULT 'person', \"note\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "attachments", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"attachments\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"parent_type\" TEXT NOT NULL, \"parent_id\" TEXT NOT NULL, \"kind\" TEXT NOT NULL, \"uri\" TEXT NULL, \"bytes\" BLOB NULL, \"mime_type\" TEXT NULL, \"sort_order\" INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (\"id\"));" + } + ] + }, + { + "name": "external_links", + "sql": [ + { + "dialect": "sqlite", + "sql": "CREATE TABLE IF NOT EXISTS \"external_links\" (\"id\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" TEXT NOT NULL, \"last_author\" TEXT NOT NULL, \"is_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_deleted\" IN (0, 1)), \"schema_row_version\" INTEGER NOT NULL DEFAULT 1, \"parent_type\" TEXT NOT NULL, \"parent_id\" TEXT NOT NULL, \"url\" TEXT NOT NULL, \"title\" TEXT NULL, PRIMARY KEY (\"id\"));" + } + ] + } + ] +} \ No newline at end of file diff --git a/apps/app_seeds/lib/data/variety_repository.dart b/apps/app_seeds/lib/data/variety_repository.dart index f1d993b..281cd21 100644 --- a/apps/app_seeds/lib/data/variety_repository.dart +++ b/apps/app_seeds/lib/data/variety_repository.dart @@ -67,6 +67,7 @@ class VarietyLot extends Equatable { this.harvestYear, this.harvestMonth, this.quantity, + this.presentation, this.storageLocation, this.germinationTests = const [], }); @@ -78,6 +79,9 @@ class VarietyLot extends Equatable { /// Optional harvest month (1..12). Only meaningful when [harvestYear] is set. final int? harvestMonth; final Quantity? quantity; + + /// How living material is packaged (pot, tray, bare-root…); null for seeds. + final Presentation? presentation; final String? storageLocation; final List germinationTests; @@ -92,6 +96,7 @@ class VarietyLot extends Equatable { harvestYear, harvestMonth, quantity, + presentation, storageLocation, germinationTests, ]; @@ -252,13 +257,18 @@ class VarietyRepository { ) async { if (varietyIds.isEmpty) return const {}; final rows = - await (_db.select(_db.attachments)..where( - (a) => - a.parentId.isIn(varietyIds) & - a.parentType.equalsValue(ParentType.variety) & - a.kind.equalsValue(AttachmentKind.photo) & - a.isDeleted.equals(false), - )) + await (_db.select(_db.attachments) + ..where( + (a) => + a.parentId.isIn(varietyIds) & + a.parentType.equalsValue(ParentType.variety) & + a.kind.equalsValue(AttachmentKind.photo) & + a.isDeleted.equals(false), + ) + ..orderBy([ + (a) => OrderingTerm(expression: a.sortOrder), + (a) => OrderingTerm(expression: a.createdAt), + ])) .get(); final byVariety = {}; for (final row in rows) { @@ -431,7 +441,10 @@ class VarietyRepository { a.kind.equalsValue(AttachmentKind.photo) & a.isDeleted.equals(false), ) - ..orderBy([(a) => OrderingTerm(expression: a.createdAt)])) + ..orderBy([ + (a) => OrderingTerm(expression: a.sortOrder), + (a) => OrderingTerm(expression: a.createdAt), + ])) .get(); final links = @@ -527,6 +540,7 @@ class VarietyRepository { int? harvestYear, int? harvestMonth, Quantity? quantity, + Presentation? presentation, String? storageLocation, }) async { final (created, updated) = _stamp(); @@ -546,6 +560,7 @@ class VarietyRepository { quantityKind: Value(quantity?.kind.name), quantityPrecise: Value(quantity?.count?.toDouble()), quantityLabel: Value(quantity?.label), + presentation: Value(presentation), storageLocation: Value(storageLocation), ), ); @@ -560,6 +575,7 @@ class VarietyRepository { int? harvestYear, int? harvestMonth, Quantity? quantity, + Presentation? presentation, String? storageLocation, }) async { final (_, updated) = _stamp(); @@ -571,6 +587,7 @@ class VarietyRepository { quantityKind: Value(quantity?.kind.name), quantityPrecise: Value(quantity?.count?.toDouble()), quantityLabel: Value(quantity?.label), + presentation: Value(presentation), storageLocation: Value(storageLocation), updatedAt: Value(updated), lastAuthor: Value(nodeId), @@ -666,6 +683,34 @@ class VarietyRepository { ); } + /// Makes [attachmentId] the cover (preferred) attachment of [varietyId] by + /// giving it a [sortOrder] below every current sibling. The cover is what the + /// inventory list shows as the avatar and the detail gallery shows first. + Future setPreferredPhoto(String varietyId, String attachmentId) async { + final siblings = + await (_db.select(_db.attachments)..where( + (a) => + a.parentId.equals(varietyId) & + a.parentType.equalsValue(ParentType.variety) & + a.isDeleted.equals(false), + )) + .get(); + var minOrder = 0; + for (final a in siblings) { + if (a.sortOrder < minOrder) minOrder = a.sortOrder; + } + final (_, updated) = _stamp(); + await (_db.update( + _db.attachments, + )..where((a) => a.id.equals(attachmentId))).write( + AttachmentsCompanion( + sortOrder: Value(minOrder - 1), + updatedAt: Value(updated), + lastAuthor: Value(nodeId), + ), + ); + } + /// Adds an external link (URL, optional title) to a variety. Returns its id. Future addExternalLink( String varietyId, @@ -756,6 +801,7 @@ class VarietyRepository { type: l.type, harvestYear: l.harvestYear, harvestMonth: l.harvestMonth, + presentation: l.presentation, storageLocation: l.storageLocation, germinationTests: germinationTests, quantity: hasQuantity diff --git a/apps/app_seeds/lib/db/database.dart b/apps/app_seeds/lib/db/database.dart index 29b1815..6c475fb 100644 --- a/apps/app_seeds/lib/db/database.dart +++ b/apps/app_seeds/lib/db/database.dart @@ -27,13 +27,13 @@ class AppDatabase extends _$AppDatabase { AppDatabase(super.e); @override - int get schemaVersion => 3; + int get schemaVersion => 5; @override MigrationStrategy get migration => MigrationStrategy( onCreate: (m) async => m.createAll(), onUpgrade: (m, from, to) async { - // v2: lots can hold seeds or plants/seedlings (plantel). + // v2: lots can hold seeds or living plant material. if (from < 2) { await m.addColumn(lots, lots.type); } @@ -41,6 +41,14 @@ class AppDatabase extends _$AppDatabase { if (from < 3) { await m.addColumn(lots, lots.harvestMonth); } + // v4: optional packaging/supply form for living lots. + if (from < 4) { + await m.addColumn(lots, lots.presentation); + } + // v5: display order for attachments (cover photo = lowest sortOrder). + if (from < 5) { + await m.addColumn(attachments, attachments.sortOrder); + } }, ); } diff --git a/apps/app_seeds/lib/db/database.g.dart b/apps/app_seeds/lib/db/database.g.dart index 1e6d62c..fb2d458 100644 --- a/apps/app_seeds/lib/db/database.g.dart +++ b/apps/app_seeds/lib/db/database.g.dart @@ -2675,6 +2675,15 @@ class $LotsTable extends Lots with TableInfo<$LotsTable, Lot> { type: DriftSqlType.string, requiredDuringInsert: false, ); + @override + late final GeneratedColumnWithTypeConverter + presentation = GeneratedColumn( + 'presentation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ).withConverter($LotsTable.$converterpresentationn); static const VerificationMeta _storageLocationMeta = const VerificationMeta( 'storageLocation', ); @@ -2722,6 +2731,7 @@ class $LotsTable extends Lots with TableInfo<$LotsTable, Lot> { quantityKind, quantityPrecise, quantityLabel, + presentation, storageLocation, offerStatus, seedbankId, @@ -2913,6 +2923,12 @@ class $LotsTable extends Lots with TableInfo<$LotsTable, Lot> { DriftSqlType.string, data['${effectivePrefix}quantity_label'], ), + presentation: $LotsTable.$converterpresentationn.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}presentation'], + ), + ), storageLocation: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}storage_location'], @@ -2937,6 +2953,14 @@ class $LotsTable extends Lots with TableInfo<$LotsTable, Lot> { static JsonTypeConverter2 $convertertype = const EnumNameConverter(LotType.values); + static JsonTypeConverter2 + $converterpresentation = const EnumNameConverter( + Presentation.values, + ); + static JsonTypeConverter2 + $converterpresentationn = JsonTypeConverter2.asNullable( + $converterpresentation, + ); static JsonTypeConverter2 $converterofferStatus = const EnumNameConverter(OfferStatus.values); } @@ -2955,6 +2979,7 @@ class Lot extends DataClass implements Insertable { final String? quantityKind; final double? quantityPrecise; final String? quantityLabel; + final Presentation? presentation; final String? storageLocation; final OfferStatus offerStatus; final String? seedbankId; @@ -2972,6 +2997,7 @@ class Lot extends DataClass implements Insertable { this.quantityKind, this.quantityPrecise, this.quantityLabel, + this.presentation, this.storageLocation, required this.offerStatus, this.seedbankId, @@ -3004,6 +3030,11 @@ class Lot extends DataClass implements Insertable { if (!nullToAbsent || quantityLabel != null) { map['quantity_label'] = Variable(quantityLabel); } + if (!nullToAbsent || presentation != null) { + map['presentation'] = Variable( + $LotsTable.$converterpresentationn.toSql(presentation), + ); + } if (!nullToAbsent || storageLocation != null) { map['storage_location'] = Variable(storageLocation); } @@ -3043,6 +3074,9 @@ class Lot extends DataClass implements Insertable { quantityLabel: quantityLabel == null && nullToAbsent ? const Value.absent() : Value(quantityLabel), + presentation: presentation == null && nullToAbsent + ? const Value.absent() + : Value(presentation), storageLocation: storageLocation == null && nullToAbsent ? const Value.absent() : Value(storageLocation), @@ -3074,6 +3108,9 @@ class Lot extends DataClass implements Insertable { quantityKind: serializer.fromJson(json['quantityKind']), quantityPrecise: serializer.fromJson(json['quantityPrecise']), quantityLabel: serializer.fromJson(json['quantityLabel']), + presentation: $LotsTable.$converterpresentationn.fromJson( + serializer.fromJson(json['presentation']), + ), storageLocation: serializer.fromJson(json['storageLocation']), offerStatus: $LotsTable.$converterofferStatus.fromJson( serializer.fromJson(json['offerStatus']), @@ -3098,6 +3135,9 @@ class Lot extends DataClass implements Insertable { 'quantityKind': serializer.toJson(quantityKind), 'quantityPrecise': serializer.toJson(quantityPrecise), 'quantityLabel': serializer.toJson(quantityLabel), + 'presentation': serializer.toJson( + $LotsTable.$converterpresentationn.toJson(presentation), + ), 'storageLocation': serializer.toJson(storageLocation), 'offerStatus': serializer.toJson( $LotsTable.$converterofferStatus.toJson(offerStatus), @@ -3120,6 +3160,7 @@ class Lot extends DataClass implements Insertable { Value quantityKind = const Value.absent(), Value quantityPrecise = const Value.absent(), Value quantityLabel = const Value.absent(), + Value presentation = const Value.absent(), Value storageLocation = const Value.absent(), OfferStatus? offerStatus, Value seedbankId = const Value.absent(), @@ -3141,6 +3182,7 @@ class Lot extends DataClass implements Insertable { quantityLabel: quantityLabel.present ? quantityLabel.value : this.quantityLabel, + presentation: presentation.present ? presentation.value : this.presentation, storageLocation: storageLocation.present ? storageLocation.value : this.storageLocation, @@ -3176,6 +3218,9 @@ class Lot extends DataClass implements Insertable { quantityLabel: data.quantityLabel.present ? data.quantityLabel.value : this.quantityLabel, + presentation: data.presentation.present + ? data.presentation.value + : this.presentation, storageLocation: data.storageLocation.present ? data.storageLocation.value : this.storageLocation, @@ -3204,6 +3249,7 @@ class Lot extends DataClass implements Insertable { ..write('quantityKind: $quantityKind, ') ..write('quantityPrecise: $quantityPrecise, ') ..write('quantityLabel: $quantityLabel, ') + ..write('presentation: $presentation, ') ..write('storageLocation: $storageLocation, ') ..write('offerStatus: $offerStatus, ') ..write('seedbankId: $seedbankId') @@ -3226,6 +3272,7 @@ class Lot extends DataClass implements Insertable { quantityKind, quantityPrecise, quantityLabel, + presentation, storageLocation, offerStatus, seedbankId, @@ -3247,6 +3294,7 @@ class Lot extends DataClass implements Insertable { other.quantityKind == this.quantityKind && other.quantityPrecise == this.quantityPrecise && other.quantityLabel == this.quantityLabel && + other.presentation == this.presentation && other.storageLocation == this.storageLocation && other.offerStatus == this.offerStatus && other.seedbankId == this.seedbankId); @@ -3266,6 +3314,7 @@ class LotsCompanion extends UpdateCompanion { final Value quantityKind; final Value quantityPrecise; final Value quantityLabel; + final Value presentation; final Value storageLocation; final Value offerStatus; final Value seedbankId; @@ -3284,6 +3333,7 @@ class LotsCompanion extends UpdateCompanion { this.quantityKind = const Value.absent(), this.quantityPrecise = const Value.absent(), this.quantityLabel = const Value.absent(), + this.presentation = const Value.absent(), this.storageLocation = const Value.absent(), this.offerStatus = const Value.absent(), this.seedbankId = const Value.absent(), @@ -3303,6 +3353,7 @@ class LotsCompanion extends UpdateCompanion { this.quantityKind = const Value.absent(), this.quantityPrecise = const Value.absent(), this.quantityLabel = const Value.absent(), + this.presentation = const Value.absent(), this.storageLocation = const Value.absent(), this.offerStatus = const Value.absent(), this.seedbankId = const Value.absent(), @@ -3326,6 +3377,7 @@ class LotsCompanion extends UpdateCompanion { Expression? quantityKind, Expression? quantityPrecise, Expression? quantityLabel, + Expression? presentation, Expression? storageLocation, Expression? offerStatus, Expression? seedbankId, @@ -3345,6 +3397,7 @@ class LotsCompanion extends UpdateCompanion { if (quantityKind != null) 'quantity_kind': quantityKind, if (quantityPrecise != null) 'quantity_precise': quantityPrecise, if (quantityLabel != null) 'quantity_label': quantityLabel, + if (presentation != null) 'presentation': presentation, if (storageLocation != null) 'storage_location': storageLocation, if (offerStatus != null) 'offer_status': offerStatus, if (seedbankId != null) 'seedbank_id': seedbankId, @@ -3366,6 +3419,7 @@ class LotsCompanion extends UpdateCompanion { Value? quantityKind, Value? quantityPrecise, Value? quantityLabel, + Value? presentation, Value? storageLocation, Value? offerStatus, Value? seedbankId, @@ -3385,6 +3439,7 @@ class LotsCompanion extends UpdateCompanion { quantityKind: quantityKind ?? this.quantityKind, quantityPrecise: quantityPrecise ?? this.quantityPrecise, quantityLabel: quantityLabel ?? this.quantityLabel, + presentation: presentation ?? this.presentation, storageLocation: storageLocation ?? this.storageLocation, offerStatus: offerStatus ?? this.offerStatus, seedbankId: seedbankId ?? this.seedbankId, @@ -3436,6 +3491,11 @@ class LotsCompanion extends UpdateCompanion { if (quantityLabel.present) { map['quantity_label'] = Variable(quantityLabel.value); } + if (presentation.present) { + map['presentation'] = Variable( + $LotsTable.$converterpresentationn.toSql(presentation.value), + ); + } if (storageLocation.present) { map['storage_location'] = Variable(storageLocation.value); } @@ -3469,6 +3529,7 @@ class LotsCompanion extends UpdateCompanion { ..write('quantityKind: $quantityKind, ') ..write('quantityPrecise: $quantityPrecise, ') ..write('quantityLabel: $quantityLabel, ') + ..write('presentation: $presentation, ') ..write('storageLocation: $storageLocation, ') ..write('offerStatus: $offerStatus, ') ..write('seedbankId: $seedbankId, ') @@ -5752,6 +5813,18 @@ class $AttachmentsTable extends Attachments type: DriftSqlType.string, requiredDuringInsert: false, ); + static const VerificationMeta _sortOrderMeta = const VerificationMeta( + 'sortOrder', + ); + @override + late final GeneratedColumn sortOrder = GeneratedColumn( + 'sort_order', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(0), + ); @override List get $columns => [ id, @@ -5766,6 +5839,7 @@ class $AttachmentsTable extends Attachments uri, bytes, mimeType, + sortOrder, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -5849,6 +5923,12 @@ class $AttachmentsTable extends Attachments mimeType.isAcceptableOrUnknown(data['mime_type']!, _mimeTypeMeta), ); } + if (data.containsKey('sort_order')) { + context.handle( + _sortOrderMeta, + sortOrder.isAcceptableOrUnknown(data['sort_order']!, _sortOrderMeta), + ); + } return context; } @@ -5910,6 +5990,10 @@ class $AttachmentsTable extends Attachments DriftSqlType.string, data['${effectivePrefix}mime_type'], ), + sortOrder: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}sort_order'], + )!, ); } @@ -5937,6 +6021,12 @@ class Attachment extends DataClass implements Insertable { final String? uri; final Uint8List? bytes; final String? mimeType; + + /// Display order among sibling attachments (lower first). The lowest-ordered + /// photo is the "preferred"/cover — used as the variety avatar and shown + /// first. New photos append at the end; "set as cover" moves one to the + /// front. A plain int (not a bool flag) so it generalizes to full reordering. + final int sortOrder; const Attachment({ required this.id, required this.createdAt, @@ -5950,6 +6040,7 @@ class Attachment extends DataClass implements Insertable { this.uri, this.bytes, this.mimeType, + required this.sortOrder, }); @override Map toColumns(bool nullToAbsent) { @@ -5980,6 +6071,7 @@ class Attachment extends DataClass implements Insertable { if (!nullToAbsent || mimeType != null) { map['mime_type'] = Variable(mimeType); } + map['sort_order'] = Variable(sortOrder); return map; } @@ -6001,6 +6093,7 @@ class Attachment extends DataClass implements Insertable { mimeType: mimeType == null && nullToAbsent ? const Value.absent() : Value(mimeType), + sortOrder: Value(sortOrder), ); } @@ -6026,6 +6119,7 @@ class Attachment extends DataClass implements Insertable { uri: serializer.fromJson(json['uri']), bytes: serializer.fromJson(json['bytes']), mimeType: serializer.fromJson(json['mimeType']), + sortOrder: serializer.fromJson(json['sortOrder']), ); } @override @@ -6048,6 +6142,7 @@ class Attachment extends DataClass implements Insertable { 'uri': serializer.toJson(uri), 'bytes': serializer.toJson(bytes), 'mimeType': serializer.toJson(mimeType), + 'sortOrder': serializer.toJson(sortOrder), }; } @@ -6064,6 +6159,7 @@ class Attachment extends DataClass implements Insertable { Value uri = const Value.absent(), Value bytes = const Value.absent(), Value mimeType = const Value.absent(), + int? sortOrder, }) => Attachment( id: id ?? this.id, createdAt: createdAt ?? this.createdAt, @@ -6077,6 +6173,7 @@ class Attachment extends DataClass implements Insertable { uri: uri.present ? uri.value : this.uri, bytes: bytes.present ? bytes.value : this.bytes, mimeType: mimeType.present ? mimeType.value : this.mimeType, + sortOrder: sortOrder ?? this.sortOrder, ); Attachment copyWithCompanion(AttachmentsCompanion data) { return Attachment( @@ -6098,6 +6195,7 @@ class Attachment extends DataClass implements Insertable { uri: data.uri.present ? data.uri.value : this.uri, bytes: data.bytes.present ? data.bytes.value : this.bytes, mimeType: data.mimeType.present ? data.mimeType.value : this.mimeType, + sortOrder: data.sortOrder.present ? data.sortOrder.value : this.sortOrder, ); } @@ -6115,7 +6213,8 @@ class Attachment extends DataClass implements Insertable { ..write('kind: $kind, ') ..write('uri: $uri, ') ..write('bytes: $bytes, ') - ..write('mimeType: $mimeType') + ..write('mimeType: $mimeType, ') + ..write('sortOrder: $sortOrder') ..write(')')) .toString(); } @@ -6134,6 +6233,7 @@ class Attachment extends DataClass implements Insertable { uri, $driftBlobEquality.hash(bytes), mimeType, + sortOrder, ); @override bool operator ==(Object other) => @@ -6150,7 +6250,8 @@ class Attachment extends DataClass implements Insertable { other.kind == this.kind && other.uri == this.uri && $driftBlobEquality.equals(other.bytes, this.bytes) && - other.mimeType == this.mimeType); + other.mimeType == this.mimeType && + other.sortOrder == this.sortOrder); } class AttachmentsCompanion extends UpdateCompanion { @@ -6166,6 +6267,7 @@ class AttachmentsCompanion extends UpdateCompanion { final Value uri; final Value bytes; final Value mimeType; + final Value sortOrder; final Value rowid; const AttachmentsCompanion({ this.id = const Value.absent(), @@ -6180,6 +6282,7 @@ class AttachmentsCompanion extends UpdateCompanion { this.uri = const Value.absent(), this.bytes = const Value.absent(), this.mimeType = const Value.absent(), + this.sortOrder = const Value.absent(), this.rowid = const Value.absent(), }); AttachmentsCompanion.insert({ @@ -6195,6 +6298,7 @@ class AttachmentsCompanion extends UpdateCompanion { this.uri = const Value.absent(), this.bytes = const Value.absent(), this.mimeType = const Value.absent(), + this.sortOrder = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), createdAt = Value(createdAt), @@ -6216,6 +6320,7 @@ class AttachmentsCompanion extends UpdateCompanion { Expression? uri, Expression? bytes, Expression? mimeType, + Expression? sortOrder, Expression? rowid, }) { return RawValuesInsertable({ @@ -6231,6 +6336,7 @@ class AttachmentsCompanion extends UpdateCompanion { if (uri != null) 'uri': uri, if (bytes != null) 'bytes': bytes, if (mimeType != null) 'mime_type': mimeType, + if (sortOrder != null) 'sort_order': sortOrder, if (rowid != null) 'rowid': rowid, }); } @@ -6248,6 +6354,7 @@ class AttachmentsCompanion extends UpdateCompanion { Value? uri, Value? bytes, Value? mimeType, + Value? sortOrder, Value? rowid, }) { return AttachmentsCompanion( @@ -6263,6 +6370,7 @@ class AttachmentsCompanion extends UpdateCompanion { uri: uri ?? this.uri, bytes: bytes ?? this.bytes, mimeType: mimeType ?? this.mimeType, + sortOrder: sortOrder ?? this.sortOrder, rowid: rowid ?? this.rowid, ); } @@ -6310,6 +6418,9 @@ class AttachmentsCompanion extends UpdateCompanion { if (mimeType.present) { map['mime_type'] = Variable(mimeType.value); } + if (sortOrder.present) { + map['sort_order'] = Variable(sortOrder.value); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -6331,6 +6442,7 @@ class AttachmentsCompanion extends UpdateCompanion { ..write('uri: $uri, ') ..write('bytes: $bytes, ') ..write('mimeType: $mimeType, ') + ..write('sortOrder: $sortOrder, ') ..write('rowid: $rowid') ..write(')')) .toString(); @@ -8246,6 +8358,7 @@ typedef $$LotsTableCreateCompanionBuilder = Value quantityKind, Value quantityPrecise, Value quantityLabel, + Value presentation, Value storageLocation, Value offerStatus, Value seedbankId, @@ -8266,6 +8379,7 @@ typedef $$LotsTableUpdateCompanionBuilder = Value quantityKind, Value quantityPrecise, Value quantityLabel, + Value presentation, Value storageLocation, Value offerStatus, Value seedbankId, @@ -8346,6 +8460,12 @@ class $$LotsTableFilterComposer extends Composer<_$AppDatabase, $LotsTable> { builder: (column) => ColumnFilters(column), ); + ColumnWithTypeConverterFilters + get presentation => $composableBuilder( + column: $table.presentation, + builder: (column) => ColumnWithTypeConverterFilters(column), + ); + ColumnFilters get storageLocation => $composableBuilder( column: $table.storageLocation, builder: (column) => ColumnFilters(column), @@ -8436,6 +8556,11 @@ class $$LotsTableOrderingComposer extends Composer<_$AppDatabase, $LotsTable> { builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get presentation => $composableBuilder( + column: $table.presentation, + builder: (column) => ColumnOrderings(column), + ); + ColumnOrderings get storageLocation => $composableBuilder( column: $table.storageLocation, builder: (column) => ColumnOrderings(column), @@ -8514,6 +8639,12 @@ class $$LotsTableAnnotationComposer builder: (column) => column, ); + GeneratedColumnWithTypeConverter get presentation => + $composableBuilder( + column: $table.presentation, + builder: (column) => column, + ); + GeneratedColumn get storageLocation => $composableBuilder( column: $table.storageLocation, builder: (column) => column, @@ -8572,6 +8703,7 @@ class $$LotsTableTableManager Value quantityKind = const Value.absent(), Value quantityPrecise = const Value.absent(), Value quantityLabel = const Value.absent(), + Value presentation = const Value.absent(), Value storageLocation = const Value.absent(), Value offerStatus = const Value.absent(), Value seedbankId = const Value.absent(), @@ -8590,6 +8722,7 @@ class $$LotsTableTableManager quantityKind: quantityKind, quantityPrecise: quantityPrecise, quantityLabel: quantityLabel, + presentation: presentation, storageLocation: storageLocation, offerStatus: offerStatus, seedbankId: seedbankId, @@ -8610,6 +8743,7 @@ class $$LotsTableTableManager Value quantityKind = const Value.absent(), Value quantityPrecise = const Value.absent(), Value quantityLabel = const Value.absent(), + Value presentation = const Value.absent(), Value storageLocation = const Value.absent(), Value offerStatus = const Value.absent(), Value seedbankId = const Value.absent(), @@ -8628,6 +8762,7 @@ class $$LotsTableTableManager quantityKind: quantityKind, quantityPrecise: quantityPrecise, quantityLabel: quantityLabel, + presentation: presentation, storageLocation: storageLocation, offerStatus: offerStatus, seedbankId: seedbankId, @@ -9677,6 +9812,7 @@ typedef $$AttachmentsTableCreateCompanionBuilder = Value uri, Value bytes, Value mimeType, + Value sortOrder, Value rowid, }); typedef $$AttachmentsTableUpdateCompanionBuilder = @@ -9693,6 +9829,7 @@ typedef $$AttachmentsTableUpdateCompanionBuilder = Value uri, Value bytes, Value mimeType, + Value sortOrder, Value rowid, }); @@ -9766,6 +9903,11 @@ class $$AttachmentsTableFilterComposer column: $table.mimeType, builder: (column) => ColumnFilters(column), ); + + ColumnFilters get sortOrder => $composableBuilder( + column: $table.sortOrder, + builder: (column) => ColumnFilters(column), + ); } class $$AttachmentsTableOrderingComposer @@ -9836,6 +9978,11 @@ class $$AttachmentsTableOrderingComposer column: $table.mimeType, builder: (column) => ColumnOrderings(column), ); + + ColumnOrderings get sortOrder => $composableBuilder( + column: $table.sortOrder, + builder: (column) => ColumnOrderings(column), + ); } class $$AttachmentsTableAnnotationComposer @@ -9889,6 +10036,9 @@ class $$AttachmentsTableAnnotationComposer GeneratedColumn get mimeType => $composableBuilder(column: $table.mimeType, builder: (column) => column); + + GeneratedColumn get sortOrder => + $composableBuilder(column: $table.sortOrder, builder: (column) => column); } class $$AttachmentsTableTableManager @@ -9934,6 +10084,7 @@ class $$AttachmentsTableTableManager Value uri = const Value.absent(), Value bytes = const Value.absent(), Value mimeType = const Value.absent(), + Value sortOrder = const Value.absent(), Value rowid = const Value.absent(), }) => AttachmentsCompanion( id: id, @@ -9948,6 +10099,7 @@ class $$AttachmentsTableTableManager uri: uri, bytes: bytes, mimeType: mimeType, + sortOrder: sortOrder, rowid: rowid, ), createCompanionCallback: @@ -9964,6 +10116,7 @@ class $$AttachmentsTableTableManager Value uri = const Value.absent(), Value bytes = const Value.absent(), Value mimeType = const Value.absent(), + Value sortOrder = const Value.absent(), Value rowid = const Value.absent(), }) => AttachmentsCompanion.insert( id: id, @@ -9978,6 +10131,7 @@ class $$AttachmentsTableTableManager uri: uri, bytes: bytes, mimeType: mimeType, + sortOrder: sortOrder, rowid: rowid, ), withReferenceMapper: (p0) => p0 diff --git a/apps/app_seeds/lib/db/enums.dart b/apps/app_seeds/lib/db/enums.dart index d6413f3..965917a 100644 --- a/apps/app_seeds/lib/db/enums.dart +++ b/apps/app_seeds/lib/db/enums.dart @@ -3,9 +3,26 @@ // 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. -/// Whether a lot holds seeds or living plants/seedlings (plantel). Germination -/// tests apply only to seed lots. -enum LotType { seed, plant } +/// 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 } diff --git a/apps/app_seeds/lib/db/tables.dart b/apps/app_seeds/lib/db/tables.dart index 3890992..ca0eeae 100644 --- a/apps/app_seeds/lib/db/tables.dart +++ b/apps/app_seeds/lib/db/tables.dart @@ -50,6 +50,8 @@ class Lots extends Table with SyncColumns { TextColumn get quantityKind => text().nullable()(); // QuantityKind.name RealColumn get quantityPrecise => real().nullable()(); TextColumn get quantityLabel => text().nullable()(); + // How living (non-seed) material is packaged; null for seed lots or unset. + TextColumn get presentation => textEnum().nullable()(); TextColumn get storageLocation => text().nullable()(); TextColumn get offerStatus => textEnum().withDefault(const Constant('private'))(); @@ -99,6 +101,12 @@ class Attachments extends Table with SyncColumns { TextColumn get uri => text().nullable()(); BlobColumn get bytes => blob().nullable()(); TextColumn get mimeType => text().nullable()(); + + /// Display order among sibling attachments (lower first). The lowest-ordered + /// photo is the "preferred"/cover — used as the variety avatar and shown + /// first. New photos append at the end; "set as cover" moves one to the + /// front. A plain int (not a bool flag) so it generalizes to full reordering. + IntColumn get sortOrder => integer().withDefault(const Constant(0))(); } /// Any pasted URL (Wikipedia, forum…). Polymorphic parent. diff --git a/apps/app_seeds/lib/state/variety_detail_cubit.dart b/apps/app_seeds/lib/state/variety_detail_cubit.dart index aeb2189..8a6ed8d 100644 --- a/apps/app_seeds/lib/state/variety_detail_cubit.dart +++ b/apps/app_seeds/lib/state/variety_detail_cubit.dart @@ -57,12 +57,14 @@ class VarietyDetailCubit extends Cubit { int? year, int? month, Quantity? quantity, + Presentation? presentation, }) => _repo.addLot( varietyId: varietyId, type: type, harvestYear: year, harvestMonth: month, quantity: quantity, + presentation: presentation, ); Future updateLot({ @@ -71,12 +73,14 @@ class VarietyDetailCubit extends Cubit { int? year, int? month, Quantity? quantity, + Presentation? presentation, }) => _repo.updateLot( lotId: lotId, type: type, harvestYear: year, harvestMonth: month, quantity: quantity, + presentation: presentation, ); Future deleteLot(String lotId) => _repo.softDeleteLot(lotId); @@ -92,6 +96,9 @@ class VarietyDetailCubit extends Cubit { Future removePhoto(String attachmentId) => _repo.removePhoto(attachmentId); + Future setPreferredPhoto(String attachmentId) => + _repo.setPreferredPhoto(varietyId, attachmentId); + Future addExternalLink(String url, {String? title}) => _repo.addExternalLink(varietyId, url, title: title); diff --git a/apps/app_seeds/test/data/variety_detail_test.dart b/apps/app_seeds/test/data/variety_detail_test.dart index f54a8a6..25ff9ba 100644 --- a/apps/app_seeds/test/data/variety_detail_test.dart +++ b/apps/app_seeds/test/data/variety_detail_test.dart @@ -201,6 +201,43 @@ void main() { ]); }); + test('setPreferredPhoto moves a photo to the front (cover)', () async { + final id = await repo.addQuickVariety(label: 'Maize'); + await repo.addPhoto(id, Uint8List.fromList([1])); + await repo.addPhoto(id, Uint8List.fromList([2])); + final p3 = await repo.addPhoto(id, Uint8List.fromList([3])); + + // Insertion order until a cover is chosen. + expect( + (await repo.watchVariety(id).first)!.photos.map((p) => p.bytes.toList()), + [ + [1], + [2], + [3], + ], + ); + + await repo.setPreferredPhoto(id, p3); + + final photos = (await repo.watchVariety(id).first)!.photos; + expect(photos.map((p) => p.bytes.toList()), [ + [3], + [1], + [2], + ]); + }); + + test('setPreferredPhoto changes the inventory avatar to the cover', () async { + final id = await repo.addQuickVariety(label: 'Maize'); + await repo.addPhoto(id, Uint8List.fromList([1])); + final p2 = await repo.addPhoto(id, Uint8List.fromList([2])); + + expect((await repo.watchInventory().first).single.photo!.toList(), [1]); + + await repo.setPreferredPhoto(id, p2); + expect((await repo.watchInventory().first).single.photo!.toList(), [2]); + }); + test('watchInventory avatar refreshes when a photo is added later', () async { final id = await repo.addQuickVariety(label: 'Maize'); final queue = StreamQueue(repo.watchInventory()); diff --git a/apps/app_seeds/test/db/migration_test.dart b/apps/app_seeds/test/db/migration_test.dart index 29621b6..019a98b 100644 --- a/apps/app_seeds/test/db/migration_test.dart +++ b/apps/app_seeds/test/db/migration_test.dart @@ -11,28 +11,40 @@ void main() { verifier = SchemaVerifier(GeneratedHelper()); }); - test('freshly created database matches the exported schema v3', () async { - final schema = await verifier.schemaAt(3); + test('freshly created database matches the exported schema v5', () async { + final schema = await verifier.schemaAt(5); final db = AppDatabase(schema.newConnection()); - await verifier.migrateAndValidate(db, 3); + await verifier.migrateAndValidate(db, 5); await db.close(); }); - test('upgrades v1 → v3 (adds Lot.type, then harvestMonth) and matches the ' - 'fresh schema', () async { + test('upgrades v1 → v5 (Lot.type, harvestMonth, presentation, ' + 'Attachment.sortOrder) and matches the fresh schema', () async { final connection = await verifier.startAt(1); final db = AppDatabase(connection); - await verifier.migrateAndValidate(db, 3); + await verifier.migrateAndValidate(db, 5); await db.close(); }); - test( - 'upgrades v2 → v3 (adds Lot.harvestMonth) and matches the fresh schema', - () async { - final connection = await verifier.startAt(2); - final db = AppDatabase(connection); - await verifier.migrateAndValidate(db, 3); - await db.close(); - }, - ); + test('upgrades v2 → v5 and matches the fresh schema', () async { + final connection = await verifier.startAt(2); + final db = AppDatabase(connection); + await verifier.migrateAndValidate(db, 5); + await db.close(); + }); + + test('upgrades v3 → v5 and matches the fresh schema', () async { + final connection = await verifier.startAt(3); + final db = AppDatabase(connection); + await verifier.migrateAndValidate(db, 5); + await db.close(); + }); + + test('upgrades v4 → v5 (adds Attachment.sortOrder) and matches the fresh ' + 'schema', () async { + final connection = await verifier.startAt(4); + final db = AppDatabase(connection); + await verifier.migrateAndValidate(db, 5); + await db.close(); + }); } diff --git a/apps/app_seeds/test/db/schema/schema.dart b/apps/app_seeds/test/db/schema/schema.dart index f7feae4..9dccfb2 100644 --- a/apps/app_seeds/test/db/schema/schema.dart +++ b/apps/app_seeds/test/db/schema/schema.dart @@ -7,6 +7,8 @@ import 'package:drift/internal/migrations.dart'; import 'schema_v1.dart' as v1; import 'schema_v2.dart' as v2; import 'schema_v3.dart' as v3; +import 'schema_v4.dart' as v4; +import 'schema_v5.dart' as v5; class GeneratedHelper implements SchemaInstantiationHelper { @override @@ -18,10 +20,14 @@ class GeneratedHelper implements SchemaInstantiationHelper { return v2.DatabaseAtV2(db); case 3: return v3.DatabaseAtV3(db); + case 4: + return v4.DatabaseAtV4(db); + case 5: + return v5.DatabaseAtV5(db); default: throw MissingSchemaException(version, versions); } } - static const versions = const [1, 2, 3]; + static const versions = const [1, 2, 3, 4, 5]; } diff --git a/apps/app_seeds/test/db/schema/schema_v4.dart b/apps/app_seeds/test/db/schema/schema_v4.dart new file mode 100644 index 0000000..f51cb30 --- /dev/null +++ b/apps/app_seeds/test/db/schema/schema_v4.dart @@ -0,0 +1,1408 @@ +// dart format width=80 +import 'dart:typed_data' as i2; +// GENERATED BY drift_dev, DO NOT MODIFY. +// ignore_for_file: type=lint,unused_import +// +import 'package:drift/drift.dart'; + +class Varieties extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Varieties(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn label = GeneratedColumn( + 'label', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn speciesId = GeneratedColumn( + 'species_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn cultivarName = GeneratedColumn( + 'cultivar_name', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn category = GeneratedColumn( + 'category', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn notes = GeneratedColumn( + 'notes', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + label, + speciesId, + cultivarName, + category, + notes, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'varieties'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Varieties createAlias(String alias) { + return Varieties(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class VarietyVernacularNames extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + VarietyVernacularNames(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn varietyId = GeneratedColumn( + 'variety_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn language = GeneratedColumn( + 'language', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn region = GeneratedColumn( + 'region', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + varietyId, + name, + language, + region, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'variety_vernacular_names'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + VarietyVernacularNames createAlias(String alias) { + return VarietyVernacularNames(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Species extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Species(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn scientificName = GeneratedColumn( + 'scientific_name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn wikidataQid = GeneratedColumn( + 'wikidata_qid', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn gbifKey = GeneratedColumn( + 'gbif_key', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn family = GeneratedColumn( + 'family', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn isBundled = GeneratedColumn( + 'is_bundled', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_bundled IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + scientificName, + wikidataQid, + gbifKey, + family, + isBundled, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'species'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Species createAlias(String alias) { + return Species(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class SpeciesCommonNames extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SpeciesCommonNames(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn speciesId = GeneratedColumn( + 'species_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn language = GeneratedColumn( + 'language', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + speciesId, + name, + language, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'species_common_names'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + SpeciesCommonNames createAlias(String alias) { + return SpeciesCommonNames(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Lots extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Lots(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn varietyId = GeneratedColumn( + 'variety_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT \'seed\'', + defaultValue: const CustomExpression('\'seed\''), + ); + late final GeneratedColumn harvestYear = GeneratedColumn( + 'harvest_year', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn harvestMonth = GeneratedColumn( + 'harvest_month', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityKind = GeneratedColumn( + 'quantity_kind', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityPrecise = GeneratedColumn( + 'quantity_precise', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityLabel = GeneratedColumn( + 'quantity_label', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn presentation = GeneratedColumn( + 'presentation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn storageLocation = GeneratedColumn( + 'storage_location', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn offerStatus = GeneratedColumn( + 'offer_status', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT \'private\'', + defaultValue: const CustomExpression('\'private\''), + ); + late final GeneratedColumn seedbankId = GeneratedColumn( + 'seedbank_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + varietyId, + type, + harvestYear, + harvestMonth, + quantityKind, + quantityPrecise, + quantityLabel, + presentation, + storageLocation, + offerStatus, + seedbankId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'lots'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Lots createAlias(String alias) { + return Lots(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class GerminationTests extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + GerminationTests(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn lotId = GeneratedColumn( + 'lot_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn testedOn = GeneratedColumn( + 'tested_on', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn sampleSize = GeneratedColumn( + 'sample_size', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn germinatedCount = GeneratedColumn( + 'germinated_count', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn notes = GeneratedColumn( + 'notes', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + lotId, + testedOn, + sampleSize, + germinatedCount, + notes, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'germination_tests'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + GerminationTests createAlias(String alias) { + return GerminationTests(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Movements extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Movements(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn lotId = GeneratedColumn( + 'lot_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn occurredOn = GeneratedColumn( + 'occurred_on', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn counterpartyId = GeneratedColumn( + 'counterparty_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityKind = GeneratedColumn( + 'quantity_kind', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityPrecise = GeneratedColumn( + 'quantity_precise', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityLabel = GeneratedColumn( + 'quantity_label', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn parentMovementId = GeneratedColumn( + 'parent_movement_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn plantareId = GeneratedColumn( + 'plantare_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn notes = GeneratedColumn( + 'notes', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + lastAuthor, + schemaRowVersion, + lotId, + type, + occurredOn, + counterpartyId, + quantityKind, + quantityPrecise, + quantityLabel, + parentMovementId, + plantareId, + notes, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'movements'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Movements createAlias(String alias) { + return Movements(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Parties extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Parties(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn displayName = GeneratedColumn( + 'display_name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn publicKey = GeneratedColumn( + 'public_key', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn kind = GeneratedColumn( + 'kind', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT \'person\'', + defaultValue: const CustomExpression('\'person\''), + ); + late final GeneratedColumn note = GeneratedColumn( + 'note', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + displayName, + publicKey, + kind, + note, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'parties'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Parties createAlias(String alias) { + return Parties(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Attachments extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Attachments(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn parentType = GeneratedColumn( + 'parent_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn parentId = GeneratedColumn( + 'parent_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn kind = GeneratedColumn( + 'kind', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn uri = GeneratedColumn( + 'uri', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn bytes = + GeneratedColumn( + 'bytes', + aliasedName, + true, + type: DriftSqlType.blob, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn mimeType = GeneratedColumn( + 'mime_type', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + parentType, + parentId, + kind, + uri, + bytes, + mimeType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'attachments'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Attachments createAlias(String alias) { + return Attachments(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class ExternalLinks extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + ExternalLinks(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn parentType = GeneratedColumn( + 'parent_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn parentId = GeneratedColumn( + 'parent_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn url = GeneratedColumn( + 'url', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn title = GeneratedColumn( + 'title', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + parentType, + parentId, + url, + title, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'external_links'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + ExternalLinks createAlias(String alias) { + return ExternalLinks(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class DatabaseAtV4 extends GeneratedDatabase { + DatabaseAtV4(QueryExecutor e) : super(e); + late final Varieties varieties = Varieties(this); + late final VarietyVernacularNames varietyVernacularNames = + VarietyVernacularNames(this); + late final Species species = Species(this); + late final SpeciesCommonNames speciesCommonNames = SpeciesCommonNames(this); + late final Lots lots = Lots(this); + late final GerminationTests germinationTests = GerminationTests(this); + late final Movements movements = Movements(this); + late final Parties parties = Parties(this); + late final Attachments attachments = Attachments(this); + late final ExternalLinks externalLinks = ExternalLinks(this); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + varieties, + varietyVernacularNames, + species, + speciesCommonNames, + lots, + germinationTests, + movements, + parties, + attachments, + externalLinks, + ]; + @override + int get schemaVersion => 4; +} diff --git a/apps/app_seeds/test/db/schema/schema_v5.dart b/apps/app_seeds/test/db/schema/schema_v5.dart new file mode 100644 index 0000000..733b319 --- /dev/null +++ b/apps/app_seeds/test/db/schema/schema_v5.dart @@ -0,0 +1,1418 @@ +// dart format width=80 +import 'dart:typed_data' as i2; +// GENERATED BY drift_dev, DO NOT MODIFY. +// ignore_for_file: type=lint,unused_import +// +import 'package:drift/drift.dart'; + +class Varieties extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Varieties(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn label = GeneratedColumn( + 'label', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn speciesId = GeneratedColumn( + 'species_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn cultivarName = GeneratedColumn( + 'cultivar_name', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn category = GeneratedColumn( + 'category', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn notes = GeneratedColumn( + 'notes', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + label, + speciesId, + cultivarName, + category, + notes, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'varieties'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Varieties createAlias(String alias) { + return Varieties(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class VarietyVernacularNames extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + VarietyVernacularNames(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn varietyId = GeneratedColumn( + 'variety_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn language = GeneratedColumn( + 'language', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn region = GeneratedColumn( + 'region', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + varietyId, + name, + language, + region, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'variety_vernacular_names'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + VarietyVernacularNames createAlias(String alias) { + return VarietyVernacularNames(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Species extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Species(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn scientificName = GeneratedColumn( + 'scientific_name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn wikidataQid = GeneratedColumn( + 'wikidata_qid', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn gbifKey = GeneratedColumn( + 'gbif_key', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn family = GeneratedColumn( + 'family', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn isBundled = GeneratedColumn( + 'is_bundled', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_bundled IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + scientificName, + wikidataQid, + gbifKey, + family, + isBundled, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'species'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Species createAlias(String alias) { + return Species(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class SpeciesCommonNames extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SpeciesCommonNames(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn speciesId = GeneratedColumn( + 'species_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn language = GeneratedColumn( + 'language', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + speciesId, + name, + language, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'species_common_names'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + SpeciesCommonNames createAlias(String alias) { + return SpeciesCommonNames(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Lots extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Lots(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn varietyId = GeneratedColumn( + 'variety_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT \'seed\'', + defaultValue: const CustomExpression('\'seed\''), + ); + late final GeneratedColumn harvestYear = GeneratedColumn( + 'harvest_year', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn harvestMonth = GeneratedColumn( + 'harvest_month', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityKind = GeneratedColumn( + 'quantity_kind', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityPrecise = GeneratedColumn( + 'quantity_precise', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityLabel = GeneratedColumn( + 'quantity_label', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn presentation = GeneratedColumn( + 'presentation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn storageLocation = GeneratedColumn( + 'storage_location', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn offerStatus = GeneratedColumn( + 'offer_status', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT \'private\'', + defaultValue: const CustomExpression('\'private\''), + ); + late final GeneratedColumn seedbankId = GeneratedColumn( + 'seedbank_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + varietyId, + type, + harvestYear, + harvestMonth, + quantityKind, + quantityPrecise, + quantityLabel, + presentation, + storageLocation, + offerStatus, + seedbankId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'lots'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Lots createAlias(String alias) { + return Lots(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class GerminationTests extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + GerminationTests(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn lotId = GeneratedColumn( + 'lot_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn testedOn = GeneratedColumn( + 'tested_on', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn sampleSize = GeneratedColumn( + 'sample_size', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn germinatedCount = GeneratedColumn( + 'germinated_count', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn notes = GeneratedColumn( + 'notes', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + lotId, + testedOn, + sampleSize, + germinatedCount, + notes, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'germination_tests'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + GerminationTests createAlias(String alias) { + return GerminationTests(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Movements extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Movements(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn lotId = GeneratedColumn( + 'lot_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn occurredOn = GeneratedColumn( + 'occurred_on', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn counterpartyId = GeneratedColumn( + 'counterparty_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityKind = GeneratedColumn( + 'quantity_kind', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityPrecise = GeneratedColumn( + 'quantity_precise', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn quantityLabel = GeneratedColumn( + 'quantity_label', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn parentMovementId = GeneratedColumn( + 'parent_movement_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn plantareId = GeneratedColumn( + 'plantare_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn notes = GeneratedColumn( + 'notes', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + lastAuthor, + schemaRowVersion, + lotId, + type, + occurredOn, + counterpartyId, + quantityKind, + quantityPrecise, + quantityLabel, + parentMovementId, + plantareId, + notes, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'movements'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Movements createAlias(String alias) { + return Movements(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Parties extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Parties(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn displayName = GeneratedColumn( + 'display_name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn publicKey = GeneratedColumn( + 'public_key', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn kind = GeneratedColumn( + 'kind', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT \'person\'', + defaultValue: const CustomExpression('\'person\''), + ); + late final GeneratedColumn note = GeneratedColumn( + 'note', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + displayName, + publicKey, + kind, + note, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'parties'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Parties createAlias(String alias) { + return Parties(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class Attachments extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Attachments(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn parentType = GeneratedColumn( + 'parent_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn parentId = GeneratedColumn( + 'parent_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn kind = GeneratedColumn( + 'kind', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn uri = GeneratedColumn( + 'uri', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn bytes = + GeneratedColumn( + 'bytes', + aliasedName, + true, + type: DriftSqlType.blob, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn mimeType = GeneratedColumn( + 'mime_type', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + late final GeneratedColumn sortOrder = GeneratedColumn( + 'sort_order', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0', + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + parentType, + parentId, + kind, + uri, + bytes, + mimeType, + sortOrder, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'attachments'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Attachments createAlias(String alias) { + return Attachments(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class ExternalLinks extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + ExternalLinks(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn lastAuthor = GeneratedColumn( + 'last_author', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn isDeleted = GeneratedColumn( + 'is_deleted', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_deleted IN (0, 1))', + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn schemaRowVersion = GeneratedColumn( + 'schema_row_version', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL DEFAULT 1', + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn parentType = GeneratedColumn( + 'parent_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn parentId = GeneratedColumn( + 'parent_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn url = GeneratedColumn( + 'url', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final GeneratedColumn title = GeneratedColumn( + 'title', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: 'NULL', + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + lastAuthor, + isDeleted, + schemaRowVersion, + parentType, + parentId, + url, + title, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'external_links'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + ExternalLinks createAlias(String alias) { + return ExternalLinks(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY(id)']; + @override + bool get dontWriteConstraints => true; +} + +class DatabaseAtV5 extends GeneratedDatabase { + DatabaseAtV5(QueryExecutor e) : super(e); + late final Varieties varieties = Varieties(this); + late final VarietyVernacularNames varietyVernacularNames = + VarietyVernacularNames(this); + late final Species species = Species(this); + late final SpeciesCommonNames speciesCommonNames = SpeciesCommonNames(this); + late final Lots lots = Lots(this); + late final GerminationTests germinationTests = GerminationTests(this); + late final Movements movements = Movements(this); + late final Parties parties = Parties(this); + late final Attachments attachments = Attachments(this); + late final ExternalLinks externalLinks = ExternalLinks(this); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + varieties, + varietyVernacularNames, + species, + speciesCommonNames, + lots, + germinationTests, + movements, + parties, + attachments, + externalLinks, + ]; + @override + int get schemaVersion => 5; +} diff --git a/docs/design/data-model.md b/docs/design/data-model.md index b349970..6340348 100644 --- a/docs/design/data-model.md +++ b/docs/design/data-model.md @@ -71,8 +71,10 @@ Zero or more per `Variety`, each with its **own year and its own unit** — and | `id` | UUID | | | `variety_id` | UUID → `Variety` | | | `harvest_year` | INTEGER | Nullable. **This is where "year" lives** (germination decays with lot age). | +| `type` | enum `LotType` | The **form** held — see §2.3.2. | | `quantity_label` | TEXT + `quantity_kind` | Qualitative by default. **Not only kitchen units** — see §2.3.1. | | `quantity_precise` | REAL + `quantity_unit` | Optional precise amount (grams / seed count). | +| `presentation` | enum `Presentation` | Nullable. How living material is packaged — see §2.3.2. | | `storage_location` | TEXT | Nullable. Free text with suggestions ("fridge", "village bank"). | | `offer_status` | enum | `private` / `shared` / `exchange` / `sell` — the visibility from PLAN §3 Layer 2. Per lot. | | `seedbank_id` | UUID → `SeedBank` | Nullable. If this lot belongs to a collective bank. | @@ -90,6 +92,19 @@ Quantity is deliberately *rough and human*, not precise. But the informal vocabu Modelling: store `quantity_kind` (a stable enum key like `pod`, `cob`, `head`, `packet`, `handful`, `grams`, `count`) + an optional numeric `quantity_precise` (and a free-text `quantity_label` for a rough amount when no key fits). The **display label is localized** from the key, so "pod"→"vaina"/"beina"… Units are *labels for a rough amount*, generally **not convertible** between each other or to grams — and that's fine. Suggestion logic (e.g. Poaceae → ear/cob, Fabaceae → pod, Helianthus → flower head) lives in the catalog mapping, not hardcoded, so it stays extensible and translatable. **To think through further:** the full starter list per family, and whether users can add their own unit keys (probably yes, as free `quantity_label` text when no key fits). +#### 2.3.2 Lot form (`LotType`) and packaging (`Presentation`) — design note + +A lot isn't always dry seed. Reviewing the vocabulary of real seed shops and nurseries (viveros) — where "plantel" is only the *seedbed/batch*, not a unit — the **form** a lot is held in is a small, append-only enum `LotType` (stored by name, data-model §5): + +- `seed` — dry seed. **The only form germination tests apply to.** +- `seedling` — a young plant grown from seed, to transplant (*plantón* / plug). +- `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). + +**Form drives the offered units**, and only `seed` gets the rich plant-form scale of §2.3.1; living forms are counted as **whole individuals** (`seedling`, `plant`, `tree`, `cutting`; `bulb` also allows grams). The *packaging* is deliberately a **separate optional attribute** `Presentation` (`pot`, `tray`, `plug`, `bareRoot`, `rootBall`) so "how many" is never conflated with "in what format" — that conflation was the original flaw (the old `pot`/`tray` "amounts", now retained only for old rows). Presentation is offered only for `seedling`/`plant`/`tree`. **Left open:** grafts/divisions/forestry seedlings (nicho) fold into `cutting`/`plant` for now, or a free note; revisit if real exchanges demand their own key. + ### 2.4 `Movement` — the append-only event log Immutable events on a `Lot`. Entries/exits are just types. This *is* the history tab and the provenance chain. diff --git a/docs/design/open-decisions.md b/docs/design/open-decisions.md index dba7da2..9b7f532 100644 --- a/docs/design/open-decisions.md +++ b/docs/design/open-decisions.md @@ -10,6 +10,7 @@ Estas fijan `schemaVersion = 1` y el arranque técnico: - **Cifrado en reposo (el "cómo" técnico):** SQLCipher + llave aleatoria en el almacén del sistema + QR de recuperación. Conceptualmente decidido; falta bajar el mecanismo. → [security-privacy.md](security-privacy.md) - **Identidad → ✅ una sola clave** raíz (Duniter/Ğ1), de la que se deriva la secp256k1 para Nostr. La clave simétrica que cifra la BD en reposo es un **detalle interno aparte** (no es una identidad), así que no contradice el "una sola identidad". → [g1-integration.md](g1-integration.md), [security-privacy.md](security-privacy.md) - **Detalles de modelo que fijan el esquema → ✅** `Quantity` como **tipo compartido** (Lot y Movement); `offer_status` **solo en Lot**; `category` **texto libre** prerrellenado desde `Species.family`. → [data-model.md](data-model.md) §6 +- **Forma del lote (`LotType`) y envase (`Presentation`) → ✅** (schema v4). `LotType` pasa de `{seed, plant}` a **6 formas** append-only: `seed, seedling(plantón), plant, tree, bulb, cutting` — tras repasar el vocabulario de viveros/tiendas ("plantel" era mal nombre: es el semillero, no una unidad). El **envase** (`pot/tray/plug/bareRoot/rootBall`) es un **atributo opcional aparte**, no una cantidad, para no mezclar "cuántas" con "en qué formato". Germinación sigue siendo solo-`seed`. → [data-model.md](data-model.md) §2.3.2 - **Licencia** del código → ✅ **AGPL-3.0** (GPLv3 + cláusula de red; compatible con GPLv3 y con Duniter/Ğ1nkgo). Falta añadir el fichero `LICENSE` al abrir el repo. - **Varilla v1 → ✅ viable** con datos abiertos: nombres/identificación (Wikidata+GBIF, fácil), **conservación desde Kew SID** (dominio público, ~52k taxones), cuidados enlazados de Permapeople. Falta: confirmar acceso/descarga de Kew SID y el subconjunto curado a empaquetar. → [data-notes.md](data-notes.md) §3-ter - **Estructura del workspace** (`commons_core` + `app_seeds`, pub workspaces) — decidido; falta materializarlo. diff --git a/packages/commons_core/lib/src/value/quantity.dart b/packages/commons_core/lib/src/value/quantity.dart index 3be1234..b2445c2 100644 --- a/packages/commons_core/lib/src/value/quantity.dart +++ b/packages/commons_core/lib/src/value/quantity.dart @@ -33,10 +33,15 @@ enum QuantityKind { tuber(QuantityGroup.seedForm, countable: true), seedHead(QuantityGroup.seedForm, countable: true), bunch(QuantityGroup.seedForm, countable: true), - // Seedlings / plants (for a plant lot). + // Living material counted as whole individuals (seedling / plant / tree / + // bulb / cutting lots). [pot] and [tray] are retained for old rows but are no + // longer offered as amounts — packaging now lives in [Presentation] instead. plant(QuantityGroup.plant, countable: true), pot(QuantityGroup.plant, countable: true), tray(QuantityGroup.plant, countable: true), + seedling(QuantityGroup.plant, countable: true), + tree(QuantityGroup.plant, countable: true), + cutting(QuantityGroup.plant, countable: true), // Precise (optional). grams(QuantityGroup.precise, countable: true), count(QuantityGroup.precise, countable: true);