From bc4e75fa3c91edea6ad69d6d12c57b5a1afaedec Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:09:21 +0100 Subject: [PATCH 01/65] Rename `p_date_acquiring` to `p_acquiring_date` anc convert type from timestamp to date --- .changeset/gorgeous-beans-help.md | 5 +++++ ...edy_thena.sql => 0001_eager_bill_hollister.sql} | 2 +- fdm-core/src/db/migrations/meta/0001_snapshot.json | 8 ++++---- fdm-core/src/db/migrations/meta/_journal.json | 4 ++-- fdm-core/src/db/schema.ts | 2 +- fdm-core/src/fertilizer.test.ts | 14 +++++++------- fdm-core/src/fertilizer.ts | 8 ++++---- 7 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 .changeset/gorgeous-beans-help.md rename fdm-core/src/db/migrations/{0001_needy_thena.sql => 0001_eager_bill_hollister.sql} (99%) diff --git a/.changeset/gorgeous-beans-help.md b/.changeset/gorgeous-beans-help.md new file mode 100644 index 000000000..49c9e50c1 --- /dev/null +++ b/.changeset/gorgeous-beans-help.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Rename `p_date_acquiring` to `p_acquiring_date` anc convert type from timestamp to date diff --git a/fdm-core/src/db/migrations/0001_needy_thena.sql b/fdm-core/src/db/migrations/0001_eager_bill_hollister.sql similarity index 99% rename from fdm-core/src/db/migrations/0001_needy_thena.sql rename to fdm-core/src/db/migrations/0001_eager_bill_hollister.sql index 926df34b5..30d1c1d87 100644 --- a/fdm-core/src/db/migrations/0001_needy_thena.sql +++ b/fdm-core/src/db/migrations/0001_eager_bill_hollister.sql @@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_aquiring" ( "b_id_farm" text NOT NULL, "p_id" text NOT NULL, "p_amount" numeric, - "p_date_acquiring" timestamp with time zone, + "p_acquiring_date" date, "created" timestamp with time zone DEFAULT now() NOT NULL, "updated" timestamp with time zone ); diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 2ebb62e65..9b3040271 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "3e245459-8868-4bb8-916c-287ad9d0b80a", + "id": "8cdcc8c2-e03e-48d7-b7b4-c78810a9c0e1", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -307,9 +307,9 @@ "primaryKey": false, "notNull": false }, - "p_date_acquiring": { - "name": "p_date_acquiring", - "type": "timestamp with time zone", + "p_acquiring_date": { + "name": "p_acquiring_date", + "type": "date", "primaryKey": false, "notNull": false }, diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index f7a5efd12..ee74041a2 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1732783245788, - "tag": "0001_needy_thena", + "when": 1733389313841, + "tag": "0001_eager_bill_hollister", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index 3166cc4da..625899f75 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -80,7 +80,7 @@ export const fertilizerAcquiring = fdmSchema.table('fertilizer_aquiring', { b_id_farm: text().notNull().references(() => farms.b_id_farm), p_id: text().notNull().references(() => fertilizers.p_id), p_amount: numericCasted(), //kg - p_date_acquiring: timestamp({ withTimezone: true }), + p_acquiring_date: date({ mode: 'string' }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), updated: timestamp({ withTimezone: true }) }) diff --git a/fdm-core/src/fertilizer.test.ts b/fdm-core/src/fertilizer.test.ts index 988b5c0f8..a8748bf9a 100644 --- a/fdm-core/src/fertilizer.test.ts +++ b/fdm-core/src/fertilizer.test.ts @@ -180,13 +180,13 @@ describe('Fertilizer Data Model', () => { ) const p_amount = 1000 - const p_date_acquiring = new Date() + const p_acquiring_date = new Date().toISOString().split('T')[0] const p_id = await addFertilizer( fdm, p_id_catalogue, b_id_farm, p_amount, - p_date_acquiring + p_acquiring_date ) expect(p_id).toBeDefined() @@ -259,11 +259,11 @@ describe('Fertilizer Data Model', () => { ) const p_amount = 1000 - const p_date_acquiring = new Date() + const p_acquiring_date = new Date().toISOString().split('T')[0] // Add two fertilizers to the farm - await addFertilizer(fdm, p_id_catalogue, b_id_farm, p_amount, p_date_acquiring) - await addFertilizer(fdm, p_id_catalogue, b_id_farm, 1500, p_date_acquiring) + await addFertilizer(fdm, p_id_catalogue, b_id_farm, p_amount, p_acquiring_date) + await addFertilizer(fdm, p_id_catalogue, b_id_farm, 1500, p_acquiring_date) const fertilizers = await getFertilizers(fdm, b_id_farm) expect(fertilizers.length).toBe(2) @@ -334,13 +334,13 @@ describe('Fertilizer Data Model', () => { ) const p_amount = 1000 - const p_date_acquiring = new Date() + const p_acquiring_date = new Date().toISOString().split('T')[0] const p_id = await addFertilizer( fdm, p_id_catalogue, b_id_farm, p_amount, - p_date_acquiring + p_acquiring_date ) expect(p_id).toBeDefined() diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index 3830043a9..8ddc183e6 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -95,7 +95,7 @@ export async function addFertilizerToCatalogue( * @param p_id_catalogue - Catalogue id of the fertilizer * @param b_id_farm - ID of the farm * @param p_amount - Amount of product that is acquired for this field - * @param p_date_acquiring - Date on which the fertilizer is acquired + * @param p_acquiring_date - Date on which the fertilizer is acquired * @returns A Promise that resolves with the if of the fertilizer * @alpha */ @@ -104,7 +104,7 @@ export async function addFertilizer( p_id_catalogue: schema.fertilizersCatalogueTypeInsert['p_id_catalogue'], b_id_farm: schema.fertilizerAcquiringTypeInsert['b_id_farm'], p_amount: schema.fertilizerAcquiringTypeInsert['p_amount'], - p_date_acquiring: schema.fertilizerAcquiringTypeInsert['p_date_acquiring'] + p_acquiring_date: schema.fertilizerAcquiringTypeInsert['p_acquiring_date'] ): Promise { // Generate an ID for the fertilizer @@ -115,7 +115,7 @@ export async function addFertilizer( b_id_farm: b_id_farm, p_id: p_id, p_amount: p_amount, - p_date_acquiring: p_date_acquiring + p_acquiring_date: p_acquiring_date } const fertilizerPickingData = { @@ -166,7 +166,7 @@ export async function getFertilizer(fdm: FdmType, p_id: schema.fertilizersTypeSe p_name_en: schema.fertilizersCatalogue.p_name_en, p_description: schema.fertilizersCatalogue.p_description, p_amount: schema.fertilizerAcquiring.p_amount, - p_date_acquiring: schema.fertilizerAcquiring.p_date_acquiring, + p_acquiring_date: schema.fertilizerAcquiring.p_acquiring_date, p_picking_date: schema.fertilizerPicking.p_picking_date, p_n_rt: schema.fertilizersCatalogue.p_n_rt, p_n_if: schema.fertilizersCatalogue.p_n_if, From 320e55d0f6064a883a80b3121f3e7bcfb59692ba Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:14:35 +0100 Subject: [PATCH 02/65] Improve and extend documentation for fertilizers --- fdm-core/src/fertilizer.ts | 58 +++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index 8ddc183e6..129221e9e 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -6,10 +6,10 @@ import { type FdmType } from './fdm' import { getFertilizersType, getFertilizerType } from './fertilizer.d' /** - * Get fertilizers available in catalogue + * Retrieves all fertilizers from the catalogue. * - * @param fdm - - * @returns A Promise that resolves with an array of fertilizers and the details. + * @param fdm The FDM instance. + * @returns A Promise that resolves with an array of fertilizer catalogue entries. * @alpha */ export async function getFertilizersFromCatalogue(fdm: FdmType): Promise { @@ -22,10 +22,12 @@ export async function getFertilizersFromCatalogue(fdm: FdmType): Promise { @@ -207,6 +212,14 @@ export async function getFertilizer(fdm: FdmType, p_id: schema.fertilizersTypeSe return fertilizer[0] } +/** + * Retrieves all fertilizer available for a given farm. + * + * @param fdm The FDM instance. + * @param b_id_farm The ID of the farm. + * @returns A Promise that resolves with an array of fertilizer IDs. + * @alpha + */ export async function getFertilizers(fdm: FdmType, b_id_farm: schema.fertilizerAcquiringTypeSelect['b_id_farm']): Promise { const fertilizers = await fdm @@ -222,11 +235,12 @@ export async function getFertilizers(fdm: FdmType, b_id_farm: schema.fertilizerA } /** - * Remove fertilizer from farm + * Removes a fertilizer from a farm. * - * @param fdm - - * @param p_id - ID of the fertilizer to be remove - * @returns A Promise that resolves when the fertilizer is removed from the farm + * @param fdm The FDM instance. + * @param p_id The ID of the fertilizer to remove. + * @returns A Promise that resolves when the fertilizer has been removed. + * @throws If removing the fertilizer fails. * @alpha */ export async function removeFertilizer( From 4189f5de69d6f83995e58b7d80fec3b2d7013810 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:39:02 +0100 Subject: [PATCH 03/65] Add `fertilizer_application` table --- .changeset/tricky-spiders-accept.md | 5 + ...ll_hollister.sql => 0001_gray_lockjaw.sql} | 24 ++++ .../src/db/migrations/meta/0001_snapshot.json | 108 +++++++++++++++++- fdm-core/src/db/migrations/meta/_journal.json | 4 +- fdm-core/src/db/schema.ts | 22 +++- 5 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 .changeset/tricky-spiders-accept.md rename fdm-core/src/db/migrations/{0001_eager_bill_hollister.sql => 0001_gray_lockjaw.sql} (89%) diff --git a/.changeset/tricky-spiders-accept.md b/.changeset/tricky-spiders-accept.md new file mode 100644 index 000000000..483856d0a --- /dev/null +++ b/.changeset/tricky-spiders-accept.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Add `fertilizer_application` table diff --git a/fdm-core/src/db/migrations/0001_eager_bill_hollister.sql b/fdm-core/src/db/migrations/0001_gray_lockjaw.sql similarity index 89% rename from fdm-core/src/db/migrations/0001_eager_bill_hollister.sql rename to fdm-core/src/db/migrations/0001_gray_lockjaw.sql index 30d1c1d87..6bab2bced 100644 --- a/fdm-core/src/db/migrations/0001_eager_bill_hollister.sql +++ b/fdm-core/src/db/migrations/0001_gray_lockjaw.sql @@ -46,6 +46,17 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_aquiring" ( "updated" timestamp with time zone ); --> statement-breakpoint +CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_applying" ( + "p_app_id" text PRIMARY KEY NOT NULL, + "b_id" text NOT NULL, + "p_id" text NOT NULL, + "p_amount" numeric, + "p_app_method" "p_app_method", + "p_app_date" date, + "created" timestamp with time zone DEFAULT now() NOT NULL, + "updated" timestamp with time zone +); +--> statement-breakpoint CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_picking" ( "p_id" text NOT NULL, "p_id_catalogue" text NOT NULL, @@ -186,6 +197,18 @@ EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "fdm-dev"."fertilizer_applying" ADD CONSTRAINT "fertilizer_applying_b_id_fields_b_id_fk" FOREIGN KEY ("b_id") REFERENCES "fdm-dev"."fields"("b_id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "fdm-dev"."fertilizer_applying" ADD CONSTRAINT "fertilizer_applying_p_id_fertilizers_p_id_fk" FOREIGN KEY ("p_id") REFERENCES "fdm-dev"."fertilizers"("p_id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint DO $$ BEGIN ALTER TABLE "fdm-dev"."fertilizer_picking" ADD CONSTRAINT "fertilizer_picking_p_id_fertilizers_p_id_fk" FOREIGN KEY ("p_id") REFERENCES "fdm-dev"."fertilizers"("p_id") ON DELETE no action ON UPDATE no action; EXCEPTION @@ -231,6 +254,7 @@ END $$; CREATE UNIQUE INDEX IF NOT EXISTS "b_lu_idx" ON "fdm-dev"."cultivations" USING btree ("b_lu");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "b_lu_catalogue_idx" ON "fdm-dev"."cultivations_catalogue" USING btree ("b_lu_catalogue");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "b_id_farm_idx" ON "fdm-dev"."farms" USING btree ("b_id_farm");--> statement-breakpoint +CREATE UNIQUE INDEX IF NOT EXISTS "p_app_idx" ON "fdm-dev"."fertilizer_applying" USING btree ("p_app_id");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "p_id_idx" ON "fdm-dev"."fertilizers" USING btree ("p_id");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "p_id_catalogue_idx" ON "fdm-dev"."fertilizers_catalogue" USING btree ("p_id_catalogue");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "b_id_idx" ON "fdm-dev"."fields" USING btree ("b_id");--> statement-breakpoint diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 9b3040271..3225c649b 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "8cdcc8c2-e03e-48d7-b7b4-c78810a9c0e1", + "id": "babd366d-a6e5-4b0e-8093-6c8ddd5134c3", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -362,6 +362,112 @@ "uniqueConstraints": {}, "checkConstraints": {} }, + "fdm-dev.fertilizer_applying": { + "name": "fertilizer_applying", + "schema": "fdm-dev", + "columns": { + "p_app_id": { + "name": "p_app_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "b_id": { + "name": "b_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_id": { + "name": "p_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_amount": { + "name": "p_amount", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_app_method": { + "name": "p_app_method", + "type": "p_app_method", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "p_app_date": { + "name": "p_app_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "p_app_idx": { + "name": "p_app_idx", + "columns": [ + { + "expression": "p_app_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "fertilizer_applying_b_id_fields_b_id_fk": { + "name": "fertilizer_applying_b_id_fields_b_id_fk", + "tableFrom": "fertilizer_applying", + "tableTo": "fields", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_id" + ], + "columnsTo": [ + "b_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "fertilizer_applying_p_id_fertilizers_p_id_fk": { + "name": "fertilizer_applying_p_id_fertilizers_p_id_fk", + "tableFrom": "fertilizer_applying", + "tableTo": "fertilizers", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "p_id" + ], + "columnsTo": [ + "p_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, "fdm-dev.fertilizer_picking": { "name": "fertilizer_picking", "schema": "fdm-dev", diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index ee74041a2..56d845d2b 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733389313841, - "tag": "0001_eager_bill_hollister", + "when": 1733391484165, + "tag": "0001_gray_lockjaw", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index 625899f75..f028ef0be 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -1,4 +1,4 @@ -import { pgSchema, text, date, timestamp, boolean, primaryKey, uniqueIndex, index} from 'drizzle-orm/pg-core' +import { pgSchema, text, date, timestamp, boolean, primaryKey, uniqueIndex, index, pgEnum} from 'drizzle-orm/pg-core' import { geometryPolygon, numericCasted } from './schema-custom-types' // Define postgres schema @@ -88,6 +88,26 @@ export const fertilizerAcquiring = fdmSchema.table('fertilizer_aquiring', { export type fertilizerAcquiringTypeSelect = typeof fertilizerAcquiring.$inferSelect export type fertilizerAcquiringTypeInsert = typeof fertilizerAcquiring.$inferInsert +// Define fertilizers application table +const applicationMethodEnum = pgEnum("p_app_method", ["slotted coulter", "incorporation", "injection", "spraying", "broadcasting","spoke wheel", "pocket placement"]) +export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { + p_app_id: text().primaryKey(), + b_id: text().notNull().references(() => fields.b_id), + p_id: text().notNull().references(() => fertilizers.p_id), + p_amount: numericCasted(), // kg / ha + p_app_method: applicationMethodEnum(), + p_app_date: date({ mode: 'string' }), + created: timestamp({ withTimezone: true }).notNull().defaultNow(), + updated: timestamp({ withTimezone: true }) +}, (table) => { + return { + p_app_idx: uniqueIndex('p_app_idx').on(table.p_app_id) + } +}) + +export type fertilizerApplicationTypeSelect = typeof fertilizerApplication.$inferSelect +export type fertilizerApplicationTypeInsert = typeof fertilizerApplication.$inferInsert + // Define fertilizers_catalogue table export const fertilizersCatalogue = fdmSchema.table('fertilizers_catalogue', { p_id_catalogue: text().primaryKey(), From f64d75f2b00ded893901f274277d67e7cb1b1710 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:20:22 +0100 Subject: [PATCH 04/65] Rename p_amount to p_app_amount --- ...1_gray_lockjaw.sql => 0001_previous_william_stryker.sql} | 2 +- fdm-core/src/db/migrations/meta/0001_snapshot.json | 6 +++--- fdm-core/src/db/migrations/meta/_journal.json | 4 ++-- fdm-core/src/db/schema.ts | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) rename fdm-core/src/db/migrations/{0001_gray_lockjaw.sql => 0001_previous_william_stryker.sql} (99%) diff --git a/fdm-core/src/db/migrations/0001_gray_lockjaw.sql b/fdm-core/src/db/migrations/0001_previous_william_stryker.sql similarity index 99% rename from fdm-core/src/db/migrations/0001_gray_lockjaw.sql rename to fdm-core/src/db/migrations/0001_previous_william_stryker.sql index 6bab2bced..dddfd1b99 100644 --- a/fdm-core/src/db/migrations/0001_gray_lockjaw.sql +++ b/fdm-core/src/db/migrations/0001_previous_william_stryker.sql @@ -50,7 +50,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_applying" ( "p_app_id" text PRIMARY KEY NOT NULL, "b_id" text NOT NULL, "p_id" text NOT NULL, - "p_amount" numeric, + "p_app_amount" numeric, "p_app_method" "p_app_method", "p_app_date" date, "created" timestamp with time zone DEFAULT now() NOT NULL, diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 3225c649b..b8cede9e8 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "babd366d-a6e5-4b0e-8093-6c8ddd5134c3", + "id": "d025e16a-fb80-4728-af02-63a43308f2ac", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -384,8 +384,8 @@ "primaryKey": false, "notNull": true }, - "p_amount": { - "name": "p_amount", + "p_app_amount": { + "name": "p_app_amount", "type": "numeric", "primaryKey": false, "notNull": false diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index 56d845d2b..ec5c254f3 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733391484165, - "tag": "0001_gray_lockjaw", + "when": 1733401195129, + "tag": "0001_previous_william_stryker", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index f028ef0be..2df9bfa1e 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -94,7 +94,7 @@ export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { p_app_id: text().primaryKey(), b_id: text().notNull().references(() => fields.b_id), p_id: text().notNull().references(() => fertilizers.p_id), - p_amount: numericCasted(), // kg / ha + p_app_amount: numericCasted(), // kg / ha p_app_method: applicationMethodEnum(), p_app_date: date({ mode: 'string' }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), From b0c001e330b0e084bb222399a92a6f7c290c62b6 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:22:39 +0100 Subject: [PATCH 05/65] Add functions `addFertilizerApplication`, `updateFertilizerApplication`, `removeFertilizerApplication`, `getFertilizerApplication` and `getFertilizerApplications` --- .changeset/proud-files-film.md | 5 ++ fdm-core/src/fertilizer.ts | 160 +++++++++++++++++++++++++++++++-- 2 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 .changeset/proud-files-film.md diff --git a/.changeset/proud-files-film.md b/.changeset/proud-files-film.md new file mode 100644 index 000000000..ca71f38a7 --- /dev/null +++ b/.changeset/proud-files-film.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Add functions `addFertilizerApplication`, `updateFertilizerApplication`, `removeFertilizerApplication`, `getFertilizerApplication` and `getFertilizerApplications` diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index 129221e9e..f15cf108d 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -1,4 +1,4 @@ -import { eq } from 'drizzle-orm' +import { and, eq } from 'drizzle-orm' import { nanoid } from 'nanoid' import * as schema from './db/schema' @@ -96,7 +96,7 @@ export async function addFertilizerToCatalogue( * @param fdm The FDM instance. * @param p_id_catalogue The catalogue ID of the fertilizer. * @param b_id_farm The ID of the farm. - * @param p_amount The amount of fertilizer applied. + * @param p_app_amount The amount of fertilizer applied. * @param p_acquiring_date The date the fertilizer was acquired. * @returns A Promise that resolves with the ID of the fertilizer application record. * @throws If adding the fertilizer application record fails. @@ -106,7 +106,7 @@ export async function addFertilizer( fdm: FdmType, p_id_catalogue: schema.fertilizersCatalogueTypeInsert['p_id_catalogue'], b_id_farm: schema.fertilizerAcquiringTypeInsert['b_id_farm'], - p_amount: schema.fertilizerAcquiringTypeInsert['p_amount'], + p_app_amount: schema.fertilizerAcquiringTypeInsert['p_app_amount'], p_acquiring_date: schema.fertilizerAcquiringTypeInsert['p_acquiring_date'] ): Promise { @@ -117,7 +117,7 @@ export async function addFertilizer( const fertilizerAcquiringData = { b_id_farm: b_id_farm, p_id: p_id, - p_amount: p_amount, + p_app_amount: p_app_amount, p_acquiring_date: p_acquiring_date } @@ -144,7 +144,7 @@ export async function addFertilizer( .insert(schema.fertilizerPicking) .values(fertilizerPickingData) - } catch (error) { + } catch (error) { throw new Error('Add fertilizer failed with error ' + error) } }) @@ -170,7 +170,7 @@ export async function getFertilizer(fdm: FdmType, p_id: schema.fertilizersTypeSe p_name_nl: schema.fertilizersCatalogue.p_name_nl, p_name_en: schema.fertilizersCatalogue.p_name_en, p_description: schema.fertilizersCatalogue.p_description, - p_amount: schema.fertilizerAcquiring.p_amount, + p_app_amount: schema.fertilizerAcquiring.p_app_amount, p_acquiring_date: schema.fertilizerAcquiring.p_acquiring_date, p_picking_date: schema.fertilizerPicking.p_picking_date, p_n_rt: schema.fertilizersCatalogue.p_n_rt, @@ -262,8 +262,154 @@ export async function removeFertilizer( .delete(schema.fertilizers) .where(eq(schema.fertilizers.p_id, p_id)) } - catch (error) { + catch (error) { throw new Error('Remove fertilizer failed with error ' + error) } }) +} + +export type FertilizerApplicationType = schema.fertilizerApplicationTypeSelect; + +/** + * Adds a fertilizer application record. + * + * @param fdm The FDM instance. + * @param b_id The ID of the field. + * @param p_id The ID of the fertilizer. + * @param p_app_amount The amount of fertilizer applied. + * @param p_app_method The method of fertilizer application. + * @param p_app_date The date of fertilizer application. + * @returns A Promise that resolves with the ID of the fertilizer application record. + * @throws If adding the fertilizer application record fails. + */ +export async function addFertilizerApplication( + fdm: FdmType, + b_id: schema.fertilizerApplicationTypeInsert['b_id'], + p_id: schema.fertilizerApplicationTypeInsert['p_id'], + p_app_amount: schema.fertilizerApplicationTypeInsert['p_app_amount'], + p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], + p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] +): Promise { + const p_app_id = nanoid(); + + try { + await fdm.insert(schema.fertilizerApplication).values({ + p_app_id, + b_id, + p_id, + p_app_amount, + p_app_method, + p_app_date, + }); + } catch (error) { + throw new Error(`Failed to add fertilizer application: ${error}`); + } + + return p_app_id; +} + + + +/** + * Updates a fertilizer application record. + * + * @param fdm The FDM instance. + * @param p_app_id The ID of the fertilizer application record to update. + * @param b_id The ID of the field. + * @param p_id The ID of the fertilizer. + * @param p_app_amount The amount of fertilizer applied. + * @param p_app_method The method of fertilizer application. + * @param p_app_date The date of fertilizer application. + * @returns A Promise that resolves when the record has been updated. + * @throws If updating the record fails. + */ +export async function updateFertilizerApplication( + fdm: FdmType, + p_app_id: schema.fertilizerApplicationTypeInsert['p_app_id'], + b_id: schema.fertilizerApplicationTypeInsert['b_id'], + p_id: schema.fertilizerApplicationTypeInsert['p_id'], + p_app_amount: schema.fertilizerApplicationTypeInsert['p_app_amount'], + p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], + p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] +): Promise { + try { + await fdm + .update(schema.fertilizerApplication) + .set({b_id, p_id, p_app_amount, p_app_method, p_app_date}) + .where(eq(schema.fertilizerApplication.p_app_id, p_app_id)); + } catch (error) { + throw new Error(`Failed to update fertilizer application: ${error}`); + } +} + +/** + * Removes a fertilizer application record. + * + * @param fdm The FDM instance. + * @param p_app_id The ID of the fertilizer application record to remove. + * @returns A Promise that resolves when the record has been removed. + * @throws If removing the record fails. + */ +export async function removeFertilizerApplication( + fdm: FdmType, + p_app_id: schema.fertilizerApplicationTypeInsert['p_app_id'] +): Promise { + try { + await fdm + .delete(schema.fertilizerApplication) + .where(eq(schema.fertilizerApplication.p_app_id, p_app_id)); + } catch (error) { + throw new Error(`Failed to remove fertilizer application: ${error}`); + } +} + + +/** + * Retrieves a fertilizer application record. + * + * @param fdm The FDM instance. + * @param p_app_id The ID of the fertilizer application record to retrieve. + * @returns A Promise that resolves with the fertilizer application record, or null if not found. + * @throws If retrieving the record fails. + */ +export async function getFertilizerApplication( + fdm: FdmType, + p_app_id: schema.fertilizerApplicationTypeSelect['p_app_id'] +): Promise { + try { + const result = await fdm + .select() + .from(schema.fertilizerApplication) + .where(eq(schema.fertilizerApplication.p_app_id, p_app_id)); + + return result[0] || null; + } catch (error) { + throw new Error(`Failed to get fertilizer application: ${error}`); + } +} + + + +/** + * Retrieves all fertilizer applications for a given field + * + * @param fdm The FDM instance. + * @param b_id The ID of the field. + * @returns A Promise that resolves with an array of fertilizer application records. + * @throws If retrieving the records fails. + */ +export async function getFertilizerApplications( + fdm: FdmType, + b_id: schema.fertilizerApplicationTypeSelect['b_id'], +): Promise { + + try { + const fertilizerApplications = await fdm + .select() + .from(schema.fertilizerApplication) + .where(eq(schema.fertilizerApplication.b_id, b_id)); + return fertilizerApplications; + } catch (error) { + throw new Error(`Failed to get fertilizer applications: ${error}`); + } } \ No newline at end of file From e13e826a0d0275374970b06faa2f0149f32f1b17 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:23:22 +0100 Subject: [PATCH 06/65] Fixes --- fdm-core/src/fertilizer.d.ts | 2 +- fdm-core/src/fertilizer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fdm-core/src/fertilizer.d.ts b/fdm-core/src/fertilizer.d.ts index a0611f919..c831e5dd8 100644 --- a/fdm-core/src/fertilizer.d.ts +++ b/fdm-core/src/fertilizer.d.ts @@ -3,7 +3,7 @@ export interface getFertilizerType { p_name_nl: string | null p_name_en: string | null p_description: string | null - p_amount: number | null + p_app_amount: number | null p_date_acquiring: Date | null p_picking_date: Date | null p_n_rt: number | null diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index f15cf108d..5743289be 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -1,4 +1,4 @@ -import { and, eq } from 'drizzle-orm' +import { eq } from 'drizzle-orm' import { nanoid } from 'nanoid' import * as schema from './db/schema' From b8469968ae461ee76ab503aed23e63db5c4f1d18 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:42:04 +0100 Subject: [PATCH 07/65] Export the new functions --- fdm-core/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdm-core/src/index.ts b/fdm-core/src/index.ts index 681188cd2..eeaa24477 100644 --- a/fdm-core/src/index.ts +++ b/fdm-core/src/index.ts @@ -21,6 +21,6 @@ export { createFdmServer, migrateFdmServer } from './fdm-server' // export { createFdmLocal, migrateFdmLocal } from './fdm-local' export { addFarm, getFarm, updateFarm, } from './farm' export { addField, getField, getFields, updateField } from './field' -export { addFertilizerToCatalogue, getFertilizersFromCatalogue, addFertilizer, removeFertilizer } from './fertilizer' +export { addFertilizerToCatalogue, getFertilizersFromCatalogue, addFertilizer, removeFertilizer, addFertilizerApplication, updateFertilizerApplication, removeFertilizerApplication, getFertilizerApplication, getFertilizerApplications} from './fertilizer' export { addCultivationToCatalogue, getCultivationsFromCatalogue, addCultivation, removeCultivation, getCultivation, getCultivations, getCultivationPlan } from './cultivation' export { signUpUser, getUserFromSession} from './iam' \ No newline at end of file From 81caa2e8aab528a71bf3cf60086fab307fe88113 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:46:04 +0100 Subject: [PATCH 08/65] Fix enum --- ...0001_previous_william_stryker.sql => 0001_cool_mentor.sql} | 2 +- fdm-core/src/db/migrations/meta/0001_snapshot.json | 4 ++-- fdm-core/src/db/migrations/meta/_journal.json | 4 ++-- fdm-core/src/db/schema.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename fdm-core/src/db/migrations/{0001_previous_william_stryker.sql => 0001_cool_mentor.sql} (99%) diff --git a/fdm-core/src/db/migrations/0001_previous_william_stryker.sql b/fdm-core/src/db/migrations/0001_cool_mentor.sql similarity index 99% rename from fdm-core/src/db/migrations/0001_previous_william_stryker.sql rename to fdm-core/src/db/migrations/0001_cool_mentor.sql index dddfd1b99..22121f3e0 100644 --- a/fdm-core/src/db/migrations/0001_previous_william_stryker.sql +++ b/fdm-core/src/db/migrations/0001_cool_mentor.sql @@ -51,7 +51,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_applying" ( "b_id" text NOT NULL, "p_id" text NOT NULL, "p_app_amount" numeric, - "p_app_method" "p_app_method", + "p_app_method" "fdm-dev"."p_app_method", "p_app_date" date, "created" timestamp with time zone DEFAULT now() NOT NULL, "updated" timestamp with time zone diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index b8cede9e8..3ba30ef2d 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "d025e16a-fb80-4728-af02-63a43308f2ac", + "id": "24be8121-2571-46e8-b311-aad926511dfb", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -393,7 +393,7 @@ "p_app_method": { "name": "p_app_method", "type": "p_app_method", - "typeSchema": "public", + "typeSchema": "fdm-dev", "primaryKey": false, "notNull": false }, diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index ec5c254f3..e77fc1ecf 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733401195129, - "tag": "0001_previous_william_stryker", + "when": 1733402736282, + "tag": "0001_cool_mentor", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index 2df9bfa1e..2120e3df7 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -1,4 +1,4 @@ -import { pgSchema, text, date, timestamp, boolean, primaryKey, uniqueIndex, index, pgEnum} from 'drizzle-orm/pg-core' +import { pgSchema, text, date, timestamp, boolean, primaryKey, uniqueIndex, index} from 'drizzle-orm/pg-core' import { geometryPolygon, numericCasted } from './schema-custom-types' // Define postgres schema @@ -89,7 +89,7 @@ export type fertilizerAcquiringTypeSelect = typeof fertilizerAcquiring.$inferSel export type fertilizerAcquiringTypeInsert = typeof fertilizerAcquiring.$inferInsert // Define fertilizers application table -const applicationMethodEnum = pgEnum("p_app_method", ["slotted coulter", "incorporation", "injection", "spraying", "broadcasting","spoke wheel", "pocket placement"]) +const applicationMethodEnum = fdmSchema.enum("p_app_method", ["slotted coulter", "incorporation", "injection", "spraying", "broadcasting","spoke wheel", "pocket placement"]) export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { p_app_id: text().primaryKey(), b_id: text().notNull().references(() => fields.b_id), From 9525388f43a48cce894a974660208832f66333fc Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:48:51 +0100 Subject: [PATCH 09/65] Fix --- ...1_cool_mentor.sql => 0001_complete_dagger.sql} | 1 + .../src/db/migrations/meta/0001_snapshot.json | 15 ++++++++++++++- fdm-core/src/db/migrations/meta/_journal.json | 4 ++-- fdm-core/src/db/schema.ts | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) rename fdm-core/src/db/migrations/{0001_cool_mentor.sql => 0001_complete_dagger.sql} (98%) diff --git a/fdm-core/src/db/migrations/0001_cool_mentor.sql b/fdm-core/src/db/migrations/0001_complete_dagger.sql similarity index 98% rename from fdm-core/src/db/migrations/0001_cool_mentor.sql rename to fdm-core/src/db/migrations/0001_complete_dagger.sql index 22121f3e0..fdb54df2c 100644 --- a/fdm-core/src/db/migrations/0001_cool_mentor.sql +++ b/fdm-core/src/db/migrations/0001_complete_dagger.sql @@ -1,5 +1,6 @@ CREATE SCHEMA "fdm-dev"; --> statement-breakpoint +CREATE TYPE "fdm-dev"."p_app_method" AS ENUM('slotted coulter', 'incorporation', 'injection', 'spraying', 'broadcasting', 'spoke wheel', 'pocket placement');--> statement-breakpoint CREATE TYPE "fdm-dev"."b_manage_type" AS ENUM('owner', 'lease');--> statement-breakpoint CREATE TYPE "fdm-dev"."b_sector" AS ENUM('diary', 'arable', 'tree_nursery', 'bulbs');--> statement-breakpoint CREATE TABLE IF NOT EXISTS "fdm-dev"."cultivations" ( diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 3ba30ef2d..2a135e5b7 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "24be8121-2571-46e8-b311-aad926511dfb", + "id": "f721777c-941f-4d87-ac67-a74751a9c313", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -1281,6 +1281,19 @@ } }, "enums": { + "fdm-dev.p_app_method": { + "name": "p_app_method", + "schema": "fdm-dev", + "values": [ + "slotted coulter", + "incorporation", + "injection", + "spraying", + "broadcasting", + "spoke wheel", + "pocket placement" + ] + }, "fdm-dev.b_manage_type": { "name": "b_manage_type", "schema": "fdm-dev", diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index e77fc1ecf..ce61cc281 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733402736282, - "tag": "0001_cool_mentor", + "when": 1733402909477, + "tag": "0001_complete_dagger", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index 2120e3df7..84b53a455 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -89,7 +89,7 @@ export type fertilizerAcquiringTypeSelect = typeof fertilizerAcquiring.$inferSel export type fertilizerAcquiringTypeInsert = typeof fertilizerAcquiring.$inferInsert // Define fertilizers application table -const applicationMethodEnum = fdmSchema.enum("p_app_method", ["slotted coulter", "incorporation", "injection", "spraying", "broadcasting","spoke wheel", "pocket placement"]) +export const applicationMethodEnum = fdmSchema.enum("p_app_method", ["slotted coulter", "incorporation", "injection", "spraying", "broadcasting","spoke wheel", "pocket placement"]) export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { p_app_id: text().primaryKey(), b_id: text().notNull().references(() => fields.b_id), From 6e0b6be7b961cfdb09fc53b5e45fcb7ddc86055a Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:43:36 +0100 Subject: [PATCH 10/65] Fix renaming --- fdm-core/src/fertilizer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index 5743289be..cd1fc6629 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -106,7 +106,7 @@ export async function addFertilizer( fdm: FdmType, p_id_catalogue: schema.fertilizersCatalogueTypeInsert['p_id_catalogue'], b_id_farm: schema.fertilizerAcquiringTypeInsert['b_id_farm'], - p_app_amount: schema.fertilizerAcquiringTypeInsert['p_app_amount'], + p_amount: schema.fertilizerAcquiringTypeInsert['p_amount'], p_acquiring_date: schema.fertilizerAcquiringTypeInsert['p_acquiring_date'] ): Promise { @@ -117,7 +117,7 @@ export async function addFertilizer( const fertilizerAcquiringData = { b_id_farm: b_id_farm, p_id: p_id, - p_app_amount: p_app_amount, + p_amount: p_amount, p_acquiring_date: p_acquiring_date } @@ -170,7 +170,7 @@ export async function getFertilizer(fdm: FdmType, p_id: schema.fertilizersTypeSe p_name_nl: schema.fertilizersCatalogue.p_name_nl, p_name_en: schema.fertilizersCatalogue.p_name_en, p_description: schema.fertilizersCatalogue.p_description, - p_app_amount: schema.fertilizerAcquiring.p_app_amount, + p_amount: schema.fertilizerAcquiring.p_amount, p_acquiring_date: schema.fertilizerAcquiring.p_acquiring_date, p_picking_date: schema.fertilizerPicking.p_picking_date, p_n_rt: schema.fertilizersCatalogue.p_n_rt, From 31476c3be667d75b41c57af13b2567d3ad9e3351 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:44:17 +0100 Subject: [PATCH 11/65] Expand tests for fertilizer applications --- fdm-core/src/fertilizer.test.ts | 170 +++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) diff --git a/fdm-core/src/fertilizer.test.ts b/fdm-core/src/fertilizer.test.ts index a8748bf9a..cd13fdc14 100644 --- a/fdm-core/src/fertilizer.test.ts +++ b/fdm-core/src/fertilizer.test.ts @@ -1,9 +1,10 @@ -import { describe, expect, it, afterAll, beforeEach } from 'vitest' +import { describe, expect, it, afterAll, beforeEach, beforeAll } from 'vitest' import { createFdmServer, migrateFdmServer } from './fdm-server' import { type FdmServerType } from './fdm-server.d' -import { addFertilizerToCatalogue, getFertilizersFromCatalogue, addFertilizer, removeFertilizer, getFertilizer, getFertilizers } from './fertilizer' +import { addFertilizerToCatalogue, getFertilizersFromCatalogue, addFertilizer, removeFertilizer, getFertilizer, getFertilizers, removeFertilizerApplication, addFertilizerApplication, getFertilizerApplication, updateFertilizerApplication, getFertilizerApplications } from './fertilizer' import { addFarm } from './farm' import { nanoid } from 'nanoid' +import { addField } from './field' describe('Fertilizer Data Model', () => { let fdm: FdmServerType @@ -33,6 +34,7 @@ describe('Fertilizer Data Model', () => { afterAll(async () => { // Clean up the database after each test // await fdm.execute(sql`TRUNCATE TABLE fertilizers_catalogue CASCADE`) + // await fdm.execute(sql`TRUNCATE TABLE fertilizer_picking CASCADE`) // await fdm.execute(sql`TRUNCATE TABLE fertilizers CASCADE`) // await fdm.execute(sql`TRUNCATE TABLE farms CASCADE`) }) @@ -350,4 +352,168 @@ describe('Fertilizer Data Model', () => { expect(fertilizer).toBeUndefined() }) }) + + describe('Fertilizer Application', () => { + let b_id: string; + let p_id: string; + let p_id_catalogue: string; + + beforeAll(async () => { + + const b_id_farm = await addFarm(fdm, 'test farm', 'arable'); + + b_id = await addField( + fdm, + b_id_farm, + 'test field', + 'test source', + 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))', + '2023-01-01', + '2024-01-01', + 'owner', + ); + + // Add fertilizer to catalogue + p_id_catalogue = nanoid() + const p_source = 'custom' + const p_name_nl = 'Test Fertilizer' + const p_name_en = 'Test Fertilizer (EN)' + const p_description = 'This is a test fertilizer' + await addFertilizerToCatalogue( + fdm, + { + p_id_catalogue, + p_source, + p_name_nl, + p_name_en, + p_description, + p_dm: 37, + p_density: 20, + p_om: 20, + p_a: 30, + p_hc: 40, + p_eom: 50, + p_eoc: 60, + p_c_rt: 70, + p_c_of: 80, + p_c_if: 90, + p_c_fr: 100, + p_cn_of: 110, + p_n_rt: 120, + p_n_if: 130, + p_n_of: 140, + p_n_wc: 150, + p_p_rt: 160, + p_k_rt: 170, + p_mg_rt: 180, + p_ca_rt: 190, + p_ne: 200, + p_s_rt: 210, + p_s_wc: 220, + p_cu_rt: 230, + p_zn_rt: 240, + p_na_rt: 250, + p_si_rt: 260, + p_b_rt: 270, + p_mn_rt: 280, + p_ni_rt: 290, + p_fe_rt: 300, + p_mo_rt: 310, + p_co_rt: 320, + p_as_rt: 330, + p_cd_rt: 340, + pr_cr_rt: 350, + p_cr_vi: 360, + p_pb_rt: 370, + p_hg_rt: 380, + p_cl_rt: 390, + p_type_manure: true, + p_type_mineral: false, + p_type_compost: false + } + ) + + const p_amount = 1000 + const p_acquiring_date = new Date().toISOString().split('T')[0] + p_id = await addFertilizer( + fdm, + p_id_catalogue, + b_id_farm, + p_amount, + p_acquiring_date + ) + + }); + + afterAll(async () => { + // Clean up the database after each test (optional) + }); + + it('should add a new fertilizer application', async () => { + const new_p_app_id = await addFertilizerApplication( + fdm, + b_id, + p_id, + 100, + 'broadcasting', + '2024-03-15', + ); + expect(new_p_app_id).toBeDefined(); + + const fertilizerApplication = await getFertilizerApplication(fdm, new_p_app_id); + expect(fertilizerApplication).toBeDefined(); + expect(fertilizerApplication?.b_id).toBe(b_id); + expect(fertilizerApplication?.p_id).toBe(p_id); + expect(fertilizerApplication?.p_app_amount).toBe(100); + expect(fertilizerApplication?.p_app_method).toBe('broadcasting'); + expect(fertilizerApplication?.p_app_date).toEqual('2024-03-15'); + }); + + + it('should update a fertilizer application', async () => { + const p_app_id = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); + + await updateFertilizerApplication(fdm, p_app_id, b_id, p_id, 200, 'injection', '2024-04-20'); + + const updatedApplication = await getFertilizerApplication(fdm, p_app_id); + expect(updatedApplication?.p_app_amount).toBe(200); + expect(updatedApplication?.p_app_method).toBe('injection'); + expect(updatedApplication?.p_app_date).toEqual('2024-04-20'); + + }); + + + it('should remove a fertilizer application', async () => { + const new_p_app_id = await addFertilizerApplication( + fdm, + b_id, + p_id, + 100, + 'broadcasting', + '2024-03-15', + ); + + await removeFertilizerApplication(fdm, new_p_app_id); + + const deletedApplication = await getFertilizerApplication(fdm, new_p_app_id); + expect(deletedApplication).toBeNull(); + }); + + it('should get a fertilizer application', async () => { + const p_app_id = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); + const fertilizerApplication = await getFertilizerApplication(fdm, p_app_id); + expect(fertilizerApplication).toBeDefined(); + expect(fertilizerApplication?.p_app_id).toBe(p_app_id); + }); + + it('should get fertilizer applications for a field', async () => { + await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); + await addFertilizerApplication(fdm, b_id, p_id, 150, 'injection', '2024-04-18'); + + + const fertilizerApplications = await getFertilizerApplications(fdm, b_id); + expect(fertilizerApplications.length).toBeGreaterThanOrEqual(2); + }); + + }); }) From 7af3fdad37d21e4a782756a72dee094c233f33e8 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:46:36 +0100 Subject: [PATCH 12/65] Rename `p_amount` at `fertilizer_acquiring` to `p_acquiring_amount` --- .changeset/empty-insects-look.md | 5 +++++ ...lete_dagger.sql => 0001_elite_reavers.sql} | 4 ++-- .../src/db/migrations/meta/0001_snapshot.json | 10 +++++----- fdm-core/src/db/migrations/meta/_journal.json | 4 ++-- fdm-core/src/db/schema.ts | 4 ++-- fdm-core/src/fertilizer.test.ts | 20 +++++++++---------- fdm-core/src/fertilizer.ts | 20 +++++++++---------- 7 files changed, 36 insertions(+), 31 deletions(-) create mode 100644 .changeset/empty-insects-look.md rename fdm-core/src/db/migrations/{0001_complete_dagger.sql => 0001_elite_reavers.sql} (99%) diff --git a/.changeset/empty-insects-look.md b/.changeset/empty-insects-look.md new file mode 100644 index 000000000..c1dcb611b --- /dev/null +++ b/.changeset/empty-insects-look.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Rename `p_amount` at `fertilizer_acquiring` to `p_acquiring_amount` diff --git a/fdm-core/src/db/migrations/0001_complete_dagger.sql b/fdm-core/src/db/migrations/0001_elite_reavers.sql similarity index 99% rename from fdm-core/src/db/migrations/0001_complete_dagger.sql rename to fdm-core/src/db/migrations/0001_elite_reavers.sql index fdb54df2c..be72f68c0 100644 --- a/fdm-core/src/db/migrations/0001_complete_dagger.sql +++ b/fdm-core/src/db/migrations/0001_elite_reavers.sql @@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."farms" ( CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_aquiring" ( "b_id_farm" text NOT NULL, "p_id" text NOT NULL, - "p_amount" numeric, + "p_acquiring_amount" numeric, "p_acquiring_date" date, "created" timestamp with time zone DEFAULT now() NOT NULL, "updated" timestamp with time zone @@ -51,7 +51,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_applying" ( "p_app_id" text PRIMARY KEY NOT NULL, "b_id" text NOT NULL, "p_id" text NOT NULL, - "p_app_amount" numeric, + "p_app_acquiring_amount" numeric, "p_app_method" "fdm-dev"."p_app_method", "p_app_date" date, "created" timestamp with time zone DEFAULT now() NOT NULL, diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 2a135e5b7..1300bf440 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "f721777c-941f-4d87-ac67-a74751a9c313", + "id": "fc19cc8e-a8b5-41a4-8439-1d7d77bc1a1f", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -301,8 +301,8 @@ "primaryKey": false, "notNull": true }, - "p_amount": { - "name": "p_amount", + "p_acquiring_amount": { + "name": "p_acquiring_amount", "type": "numeric", "primaryKey": false, "notNull": false @@ -384,8 +384,8 @@ "primaryKey": false, "notNull": true }, - "p_app_amount": { - "name": "p_app_amount", + "p_app_acquiring_amount": { + "name": "p_app_acquiring_amount", "type": "numeric", "primaryKey": false, "notNull": false diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index ce61cc281..6a024b79b 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733402909477, - "tag": "0001_complete_dagger", + "when": 1733406327600, + "tag": "0001_elite_reavers", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index 84b53a455..d97755629 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -79,7 +79,7 @@ export type fertilizersTypeInsert = typeof fertilizers.$inferInsert export const fertilizerAcquiring = fdmSchema.table('fertilizer_aquiring', { b_id_farm: text().notNull().references(() => farms.b_id_farm), p_id: text().notNull().references(() => fertilizers.p_id), - p_amount: numericCasted(), //kg + p_acquiring_amount: numericCasted(), //kg p_acquiring_date: date({ mode: 'string' }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), updated: timestamp({ withTimezone: true }) @@ -94,7 +94,7 @@ export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { p_app_id: text().primaryKey(), b_id: text().notNull().references(() => fields.b_id), p_id: text().notNull().references(() => fertilizers.p_id), - p_app_amount: numericCasted(), // kg / ha + p_app_acquiring_amount: numericCasted(), // kg / ha p_app_method: applicationMethodEnum(), p_app_date: date({ mode: 'string' }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), diff --git a/fdm-core/src/fertilizer.test.ts b/fdm-core/src/fertilizer.test.ts index cd13fdc14..a3233716b 100644 --- a/fdm-core/src/fertilizer.test.ts +++ b/fdm-core/src/fertilizer.test.ts @@ -181,13 +181,13 @@ describe('Fertilizer Data Model', () => { } ) - const p_amount = 1000 + const p_acquiring_amount = 1000 const p_acquiring_date = new Date().toISOString().split('T')[0] const p_id = await addFertilizer( fdm, p_id_catalogue, b_id_farm, - p_amount, + p_acquiring_amount, p_acquiring_date ) expect(p_id).toBeDefined() @@ -260,11 +260,11 @@ describe('Fertilizer Data Model', () => { } ) - const p_amount = 1000 + const p_acquiring_amount = 1000 const p_acquiring_date = new Date().toISOString().split('T')[0] // Add two fertilizers to the farm - await addFertilizer(fdm, p_id_catalogue, b_id_farm, p_amount, p_acquiring_date) + await addFertilizer(fdm, p_id_catalogue, b_id_farm, p_acquiring_amount, p_acquiring_date) await addFertilizer(fdm, p_id_catalogue, b_id_farm, 1500, p_acquiring_date) const fertilizers = await getFertilizers(fdm, b_id_farm) @@ -335,13 +335,13 @@ describe('Fertilizer Data Model', () => { } ) - const p_amount = 1000 + const p_acquiring_amount = 1000 const p_acquiring_date = new Date().toISOString().split('T')[0] const p_id = await addFertilizer( fdm, p_id_catalogue, b_id_farm, - p_amount, + p_acquiring_amount, p_acquiring_date ) expect(p_id).toBeDefined() @@ -433,13 +433,13 @@ describe('Fertilizer Data Model', () => { } ) - const p_amount = 1000 + const p_acquiring_amount = 1000 const p_acquiring_date = new Date().toISOString().split('T')[0] p_id = await addFertilizer( fdm, p_id_catalogue, b_id_farm, - p_amount, + p_acquiring_amount, p_acquiring_date ) @@ -464,7 +464,7 @@ describe('Fertilizer Data Model', () => { expect(fertilizerApplication).toBeDefined(); expect(fertilizerApplication?.b_id).toBe(b_id); expect(fertilizerApplication?.p_id).toBe(p_id); - expect(fertilizerApplication?.p_app_amount).toBe(100); + expect(fertilizerApplication?.p_app_acquiring_amount).toBe(100); expect(fertilizerApplication?.p_app_method).toBe('broadcasting'); expect(fertilizerApplication?.p_app_date).toEqual('2024-03-15'); }); @@ -476,7 +476,7 @@ describe('Fertilizer Data Model', () => { await updateFertilizerApplication(fdm, p_app_id, b_id, p_id, 200, 'injection', '2024-04-20'); const updatedApplication = await getFertilizerApplication(fdm, p_app_id); - expect(updatedApplication?.p_app_amount).toBe(200); + expect(updatedApplication?.p_app_acquiring_amount).toBe(200); expect(updatedApplication?.p_app_method).toBe('injection'); expect(updatedApplication?.p_app_date).toEqual('2024-04-20'); diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index cd1fc6629..c1dc2fef9 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -96,7 +96,7 @@ export async function addFertilizerToCatalogue( * @param fdm The FDM instance. * @param p_id_catalogue The catalogue ID of the fertilizer. * @param b_id_farm The ID of the farm. - * @param p_app_amount The amount of fertilizer applied. + * @param p_app_acquiring_amount The amount of fertilizer applied. * @param p_acquiring_date The date the fertilizer was acquired. * @returns A Promise that resolves with the ID of the fertilizer application record. * @throws If adding the fertilizer application record fails. @@ -106,7 +106,7 @@ export async function addFertilizer( fdm: FdmType, p_id_catalogue: schema.fertilizersCatalogueTypeInsert['p_id_catalogue'], b_id_farm: schema.fertilizerAcquiringTypeInsert['b_id_farm'], - p_amount: schema.fertilizerAcquiringTypeInsert['p_amount'], + p_acquiring_amount: schema.fertilizerAcquiringTypeInsert['p_acquiring_amount'], p_acquiring_date: schema.fertilizerAcquiringTypeInsert['p_acquiring_date'] ): Promise { @@ -117,7 +117,7 @@ export async function addFertilizer( const fertilizerAcquiringData = { b_id_farm: b_id_farm, p_id: p_id, - p_amount: p_amount, + p_acquiring_amount: p_acquiring_amount, p_acquiring_date: p_acquiring_date } @@ -170,7 +170,7 @@ export async function getFertilizer(fdm: FdmType, p_id: schema.fertilizersTypeSe p_name_nl: schema.fertilizersCatalogue.p_name_nl, p_name_en: schema.fertilizersCatalogue.p_name_en, p_description: schema.fertilizersCatalogue.p_description, - p_amount: schema.fertilizerAcquiring.p_amount, + p_acquiring_amount: schema.fertilizerAcquiring.p_acquiring_amount, p_acquiring_date: schema.fertilizerAcquiring.p_acquiring_date, p_picking_date: schema.fertilizerPicking.p_picking_date, p_n_rt: schema.fertilizersCatalogue.p_n_rt, @@ -276,7 +276,7 @@ export type FertilizerApplicationType = schema.fertilizerApplicationTypeSelect; * @param fdm The FDM instance. * @param b_id The ID of the field. * @param p_id The ID of the fertilizer. - * @param p_app_amount The amount of fertilizer applied. + * @param p_app_acquiring_amount The amount of fertilizer applied. * @param p_app_method The method of fertilizer application. * @param p_app_date The date of fertilizer application. * @returns A Promise that resolves with the ID of the fertilizer application record. @@ -286,7 +286,7 @@ export async function addFertilizerApplication( fdm: FdmType, b_id: schema.fertilizerApplicationTypeInsert['b_id'], p_id: schema.fertilizerApplicationTypeInsert['p_id'], - p_app_amount: schema.fertilizerApplicationTypeInsert['p_app_amount'], + p_app_acquiring_amount: schema.fertilizerApplicationTypeInsert['p_app_acquiring_amount'], p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] ): Promise { @@ -297,7 +297,7 @@ export async function addFertilizerApplication( p_app_id, b_id, p_id, - p_app_amount, + p_app_acquiring_amount, p_app_method, p_app_date, }); @@ -317,7 +317,7 @@ export async function addFertilizerApplication( * @param p_app_id The ID of the fertilizer application record to update. * @param b_id The ID of the field. * @param p_id The ID of the fertilizer. - * @param p_app_amount The amount of fertilizer applied. + * @param p_app_acquiring_amount The amount of fertilizer applied. * @param p_app_method The method of fertilizer application. * @param p_app_date The date of fertilizer application. * @returns A Promise that resolves when the record has been updated. @@ -328,14 +328,14 @@ export async function updateFertilizerApplication( p_app_id: schema.fertilizerApplicationTypeInsert['p_app_id'], b_id: schema.fertilizerApplicationTypeInsert['b_id'], p_id: schema.fertilizerApplicationTypeInsert['p_id'], - p_app_amount: schema.fertilizerApplicationTypeInsert['p_app_amount'], + p_app_acquiring_amount: schema.fertilizerApplicationTypeInsert['p_app_acquiring_amount'], p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] ): Promise { try { await fdm .update(schema.fertilizerApplication) - .set({b_id, p_id, p_app_amount, p_app_method, p_app_date}) + .set({b_id, p_id, p_app_acquiring_amount, p_app_method, p_app_date}) .where(eq(schema.fertilizerApplication.p_app_id, p_app_id)); } catch (error) { throw new Error(`Failed to update fertilizer application: ${error}`); From a948c6162a0c80e50f669e2bba0a4ecf3fb94ea9 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:51:17 +0100 Subject: [PATCH 13/65] Fix by adding `b_name` to output type of `getCultivationPlan` --- .changeset/lovely-buses-marry.md | 5 +++++ fdm-core/src/cultivation.ts | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/lovely-buses-marry.md diff --git a/.changeset/lovely-buses-marry.md b/.changeset/lovely-buses-marry.md new file mode 100644 index 000000000..471b409f8 --- /dev/null +++ b/.changeset/lovely-buses-marry.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": patch +--- + +Fix by adding `b_name` to output type of `getCultivationPlan` diff --git a/fdm-core/src/cultivation.ts b/fdm-core/src/cultivation.ts index b4c742d9c..71fa239e1 100644 --- a/fdm-core/src/cultivation.ts +++ b/fdm-core/src/cultivation.ts @@ -261,6 +261,7 @@ export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTy fields: Array<{ b_lu: string; b_id: string; + b_name: string; }>; }>> { if (!b_id_farm) { From 4460722b73189e5f213cbccaa1b54109a82b2666 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:02:41 +0100 Subject: [PATCH 14/65] Fix naming of p_app_amount --- ...1_elite_reavers.sql => 0001_hesitant_brood.sql} | 2 +- fdm-core/src/db/migrations/meta/0001_snapshot.json | 6 +++--- fdm-core/src/db/migrations/meta/_journal.json | 4 ++-- fdm-core/src/db/schema.ts | 2 +- fdm-core/src/fertilizer.test.ts | 4 ++-- fdm-core/src/fertilizer.ts | 14 +++++++------- 6 files changed, 16 insertions(+), 16 deletions(-) rename fdm-core/src/db/migrations/{0001_elite_reavers.sql => 0001_hesitant_brood.sql} (99%) diff --git a/fdm-core/src/db/migrations/0001_elite_reavers.sql b/fdm-core/src/db/migrations/0001_hesitant_brood.sql similarity index 99% rename from fdm-core/src/db/migrations/0001_elite_reavers.sql rename to fdm-core/src/db/migrations/0001_hesitant_brood.sql index be72f68c0..a33af4c68 100644 --- a/fdm-core/src/db/migrations/0001_elite_reavers.sql +++ b/fdm-core/src/db/migrations/0001_hesitant_brood.sql @@ -51,7 +51,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_applying" ( "p_app_id" text PRIMARY KEY NOT NULL, "b_id" text NOT NULL, "p_id" text NOT NULL, - "p_app_acquiring_amount" numeric, + "p_app_amount" numeric, "p_app_method" "fdm-dev"."p_app_method", "p_app_date" date, "created" timestamp with time zone DEFAULT now() NOT NULL, diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 1300bf440..9f446ab75 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "fc19cc8e-a8b5-41a4-8439-1d7d77bc1a1f", + "id": "cba31a98-d13f-4d32-a439-66560f9ab977", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -384,8 +384,8 @@ "primaryKey": false, "notNull": true }, - "p_app_acquiring_amount": { - "name": "p_app_acquiring_amount", + "p_app_amount": { + "name": "p_app_amount", "type": "numeric", "primaryKey": false, "notNull": false diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index 6a024b79b..46258a4fa 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,8 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733406327600, - "tag": "0001_elite_reavers", + "when": 1733407330727, + "tag": "0001_hesitant_brood", "breakpoints": true } ] diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index d97755629..64c6931b7 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -94,7 +94,7 @@ export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { p_app_id: text().primaryKey(), b_id: text().notNull().references(() => fields.b_id), p_id: text().notNull().references(() => fertilizers.p_id), - p_app_acquiring_amount: numericCasted(), // kg / ha + p_app_amount: numericCasted(), // kg / ha p_app_method: applicationMethodEnum(), p_app_date: date({ mode: 'string' }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), diff --git a/fdm-core/src/fertilizer.test.ts b/fdm-core/src/fertilizer.test.ts index a3233716b..73baea291 100644 --- a/fdm-core/src/fertilizer.test.ts +++ b/fdm-core/src/fertilizer.test.ts @@ -464,7 +464,7 @@ describe('Fertilizer Data Model', () => { expect(fertilizerApplication).toBeDefined(); expect(fertilizerApplication?.b_id).toBe(b_id); expect(fertilizerApplication?.p_id).toBe(p_id); - expect(fertilizerApplication?.p_app_acquiring_amount).toBe(100); + expect(fertilizerApplication?.p_app_amount).toBe(100); expect(fertilizerApplication?.p_app_method).toBe('broadcasting'); expect(fertilizerApplication?.p_app_date).toEqual('2024-03-15'); }); @@ -476,7 +476,7 @@ describe('Fertilizer Data Model', () => { await updateFertilizerApplication(fdm, p_app_id, b_id, p_id, 200, 'injection', '2024-04-20'); const updatedApplication = await getFertilizerApplication(fdm, p_app_id); - expect(updatedApplication?.p_app_acquiring_amount).toBe(200); + expect(updatedApplication?.p_app_amount).toBe(200); expect(updatedApplication?.p_app_method).toBe('injection'); expect(updatedApplication?.p_app_date).toEqual('2024-04-20'); diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index c1dc2fef9..e89636daa 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -96,7 +96,7 @@ export async function addFertilizerToCatalogue( * @param fdm The FDM instance. * @param p_id_catalogue The catalogue ID of the fertilizer. * @param b_id_farm The ID of the farm. - * @param p_app_acquiring_amount The amount of fertilizer applied. + * @param p_app_amount The amount of fertilizer applied. * @param p_acquiring_date The date the fertilizer was acquired. * @returns A Promise that resolves with the ID of the fertilizer application record. * @throws If adding the fertilizer application record fails. @@ -276,7 +276,7 @@ export type FertilizerApplicationType = schema.fertilizerApplicationTypeSelect; * @param fdm The FDM instance. * @param b_id The ID of the field. * @param p_id The ID of the fertilizer. - * @param p_app_acquiring_amount The amount of fertilizer applied. + * @param p_app_amount The amount of fertilizer applied. * @param p_app_method The method of fertilizer application. * @param p_app_date The date of fertilizer application. * @returns A Promise that resolves with the ID of the fertilizer application record. @@ -286,7 +286,7 @@ export async function addFertilizerApplication( fdm: FdmType, b_id: schema.fertilizerApplicationTypeInsert['b_id'], p_id: schema.fertilizerApplicationTypeInsert['p_id'], - p_app_acquiring_amount: schema.fertilizerApplicationTypeInsert['p_app_acquiring_amount'], + p_app_amount: schema.fertilizerApplicationTypeInsert['p_app_amount'], p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] ): Promise { @@ -297,7 +297,7 @@ export async function addFertilizerApplication( p_app_id, b_id, p_id, - p_app_acquiring_amount, + p_app_amount, p_app_method, p_app_date, }); @@ -317,7 +317,7 @@ export async function addFertilizerApplication( * @param p_app_id The ID of the fertilizer application record to update. * @param b_id The ID of the field. * @param p_id The ID of the fertilizer. - * @param p_app_acquiring_amount The amount of fertilizer applied. + * @param p_app_amount The amount of fertilizer applied. * @param p_app_method The method of fertilizer application. * @param p_app_date The date of fertilizer application. * @returns A Promise that resolves when the record has been updated. @@ -328,14 +328,14 @@ export async function updateFertilizerApplication( p_app_id: schema.fertilizerApplicationTypeInsert['p_app_id'], b_id: schema.fertilizerApplicationTypeInsert['b_id'], p_id: schema.fertilizerApplicationTypeInsert['p_id'], - p_app_acquiring_amount: schema.fertilizerApplicationTypeInsert['p_app_acquiring_amount'], + p_app_amount: schema.fertilizerApplicationTypeInsert['p_app_amount'], p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] ): Promise { try { await fdm .update(schema.fertilizerApplication) - .set({b_id, p_id, p_app_acquiring_amount, p_app_method, p_app_date}) + .set({b_id, p_id, p_app_amount, p_app_method, p_app_date}) .where(eq(schema.fertilizerApplication.p_app_id, p_app_id)); } catch (error) { throw new Error(`Failed to update fertilizer application: ${error}`); From 61da12f16da77e1e0198b4ca3e665ae90de7dc48 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:58:00 +0100 Subject: [PATCH 15/65] Add to output of `getCultivationPlan` the `fertilizer_applications` --- .changeset/sweet-spoons-try.md | 5 + fdm-core/src/cultivation.d.ts | 18 ++++ fdm-core/src/cultivation.test.ts | 179 ++++++++++++++++++++++--------- fdm-core/src/cultivation.ts | 95 ++++++++++++---- 4 files changed, 224 insertions(+), 73 deletions(-) create mode 100644 .changeset/sweet-spoons-try.md diff --git a/.changeset/sweet-spoons-try.md b/.changeset/sweet-spoons-try.md new file mode 100644 index 000000000..83f527465 --- /dev/null +++ b/.changeset/sweet-spoons-try.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Add to output of `getCultivationPlan` the `fertilizer_applications` diff --git a/fdm-core/src/cultivation.d.ts b/fdm-core/src/cultivation.d.ts index 6b6c19d91..2c5a20ac4 100644 --- a/fdm-core/src/cultivation.d.ts +++ b/fdm-core/src/cultivation.d.ts @@ -11,3 +11,21 @@ export interface getCultivationType { b_sowing_date: schema.fieldSowingTypeSelect['b_sowing_date'], b_id: schema.fieldSowingTypeSelect['b_id'], } + +export interface cultivationPlanType { + b_lu_catalogue: schema.cultivationsCatalogueTypeSelect['b_lu_catalogue'] + b_lu_name: schema.cultivationsCatalogueTypeSelect['b_lu_name'] + fields: Array<{ + b_lu: schema.cultivationsTypeSelect['b_lu'] + b_id: schema.fieldsTypeSelect['b_id'] + b_name: schema.fieldsTypeSelect['b_name'] + fertilizer_applications: Array<{ + p_id_catalogue: schema.fertilizersCatalogueTypeSelect['p_id_catalogue'] + p_name_nl: schema.fertilizersCatalogueTypeSelect['p_name_nl'] + p_app_amount: schema.fertilizerApplicationTypeSelect['p_app_amount'] + p_app_method: schema.fertilizerApplicationTypeSelect['p_app_method'] + p_app_date: schema.fertilizerApplicationTypeSelect['p_app_date'] + p_app_id: schema.fertilizerApplicationTypeSelect['p_app_id'] + }>; + }>; +} \ No newline at end of file diff --git a/fdm-core/src/cultivation.test.ts b/fdm-core/src/cultivation.test.ts index 057ca1a31..8c873623d 100644 --- a/fdm-core/src/cultivation.test.ts +++ b/fdm-core/src/cultivation.test.ts @@ -1,10 +1,11 @@ -import { describe, expect, it, afterAll, beforeEach } from 'vitest' +import { describe, expect, it, afterAll, beforeEach, beforeAll } from 'vitest' import { createFdmServer, migrateFdmServer } from './fdm-server' import { type FdmServerType } from './fdm-server.d' import { addCultivationToCatalogue, getCultivationsFromCatalogue, addCultivation, removeCultivation, getCultivation, getCultivations, getCultivationPlan } from './cultivation' import { addFarm } from './farm' import { addField } from './field' import { nanoid } from 'nanoid' +import { addFertilizer, addFertilizerApplication, addFertilizerToCatalogue } from './fertilizer' describe('Cultivation Data Model', () => { let fdm: FdmServerType @@ -83,7 +84,7 @@ describe('Cultivation Data Model', () => { it('should throw an error when adding a cultivation with an invalid catalogue ID', async () => { const invalid_b_lu_catalogue = 'invalid-catalogue-id'; const b_sowing_date = '2024-01-01'; - + await expect( addCultivation(fdm, invalid_b_lu_catalogue, b_id, b_sowing_date) ).rejects.toThrow('Cultivation in catalogue does not exist'); @@ -118,10 +119,10 @@ describe('Cultivation Data Model', () => { b_lu_hcat3: 'test-hcat3', b_lu_hcat3_name: 'test-hcat3-name' }); - + const b_sowing_date = '2024-01-01'; await addCultivation(fdm, b_lu_catalogue, b_id, b_sowing_date); - + // Attempt to add the same cultivation again await expect( addCultivation(fdm, b_lu_catalogue, b_id, b_sowing_date) @@ -137,10 +138,10 @@ describe('Cultivation Data Model', () => { b_lu_hcat3: 'test-hcat3', b_lu_hcat3_name: 'test-hcat3-name' }); - + const b_sowing_date = '2024-01-01'; const invalid_b_id = 'invalid-field-id'; - + await expect( addCultivation(fdm, b_lu_catalogue, invalid_b_id, b_sowing_date) ).rejects.toThrow('Field does not exist'); @@ -155,9 +156,9 @@ describe('Cultivation Data Model', () => { b_lu_hcat3: 'test-hcat3', b_lu_hcat3_name: 'test-hcat3-name' }); - + const invalid_b_sowing_date = 'invalid-date'; - + await expect( addCultivation(fdm, b_lu_catalogue, b_id, invalid_b_sowing_date) ).rejects.toThrow('Invalid sowing date'); @@ -203,64 +204,142 @@ describe('Cultivation Data Model', () => { }) - describe('getCultivationPlan', () => { - it('should return an empty array if no cultivations are found', async () => { - const cultivationPlan = await getCultivationPlan(fdm, b_id_farm); - expect(cultivationPlan).toEqual([]); - }); - - it('should return a cultivation plan with unique cultivations and their fields', async () => { - const catalogueItem1 = nanoid() - const catalogueItem2 = nanoid() + describe('Cultivation Plan', () => { + let b_id_farm: string; + let b_id: string; + let b_lu_catalogue: string; + let b_lu: string; + let p_id: string; + beforeEach(async () => { + b_id_farm = await addFarm(fdm, 'test farm', 'arable'); + b_id = await addField( + fdm, + b_id_farm, + 'test field', + 'test source', + 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))', + '2023-01-01', + '2024-01-01', + 'owner', + ); + b_lu_catalogue = nanoid() await addCultivationToCatalogue(fdm, { - b_lu_catalogue: catalogueItem1, - b_lu_source: 'test-source-1', - b_lu_name: 'test-name-1', - b_lu_name_en: 'test-name-en-1', - b_lu_hcat3: 'test-hcat3-1', - b_lu_hcat3_name: 'test-hcat3-name-1' - }) - await addCultivationToCatalogue(fdm, { - b_lu_catalogue: catalogueItem2, - b_lu_source: 'test-source-2', - b_lu_name: 'test-name-2', - b_lu_name_en: 'test-name-en-2', - b_lu_hcat3: 'test-hcat3-2', - b_lu_hcat3_name: 'test-hcat3-name-2' + b_lu_catalogue: b_lu_catalogue, + b_lu_source: 'test', + b_lu_name: 'Wheat', + b_lu_name_en: 'Wheat', + b_lu_hcat3: '1', + b_lu_hcat3_name: "test" }) + b_lu = await addCultivation(fdm, 'wheat', b_id, '2024-03-01') + + // Add fertilizer to catalogue (needed for fertilizer application) + const p_id_catalogue = nanoid(); + const p_source = 'custom'; + const p_name_nl = 'Test Fertilizer'; + const p_name_en = 'Test Fertilizer (EN)'; + const p_description = 'This is a test fertilizer'; + const p_acquiring_amount = 1000; + const p_acquiring_date = new Date().toISOString().split('T')[0]; + + await addFertilizerToCatalogue( + fdm, { + p_id_catalogue, + p_source, + p_name_nl, + p_name_en, + p_description, + p_dm: 37, + p_density: 20, + p_om: 20, + p_a: 30, + p_hc: 40, + p_eom: 50, + p_eoc: 60, + p_c_rt: 70, + p_c_of: 80, + p_c_if: 90, + p_c_fr: 100, + p_cn_of: 110, + p_n_rt: 120, + p_n_if: 130, + p_n_of: 140, + p_n_wc: 150, + p_p_rt: 160, + p_k_rt: 170, + p_mg_rt: 180, + p_ca_rt: 190, + p_ne: 200, + p_s_rt: 210, + p_s_wc: 220, + p_cu_rt: 230, + p_zn_rt: 240, + p_na_rt: 250, + p_si_rt: 260, + p_b_rt: 270, + p_mn_rt: 280, + p_ni_rt: 290, + p_fe_rt: 300, + p_mo_rt: 310, + p_co_rt: 320, + p_as_rt: 330, + p_cd_rt: 340, + pr_cr_rt: 350, + p_cr_vi: 360, + p_pb_rt: 370, + p_hg_rt: 380, + p_cl_rt: 390, + p_type_manure: true, + p_type_mineral: false, + p_type_compost: false + }) - const b_sowing_date = '2024-01-01' - await addCultivation(fdm, catalogueItem1, b_id, b_sowing_date) - const b_id2 = await addField( + p_id = await addFertilizer( fdm, + p_id_catalogue, b_id_farm, - 'test field 2', - 'test source 2', - 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))', - '2023-01-01', - '2023-12-31', - 'owner' - ) - await addCultivation(fdm, catalogueItem1, b_id2, b_sowing_date) - await addCultivation(fdm, catalogueItem2, b_id, b_sowing_date) + p_acquiring_amount, + p_acquiring_date + ); + }); + + it('should get cultivation plan for a farm', async () => { + await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); const cultivationPlan = await getCultivationPlan(fdm, b_id_farm); - expect(cultivationPlan.length).toBe(2); + expect(cultivationPlan).toBeDefined(); + expect(cultivationPlan.length).toBeGreaterThan(0); + + const wheatCultivation = cultivationPlan.find((c) => c.b_lu_catalogue === 'wheat'); + expect(wheatCultivation).toBeDefined(); + + expect(wheatCultivation?.fields.length).toBeGreaterThan(0); + const fieldInPlan = wheatCultivation?.fields.find(f => f.b_id === b_id); + expect(fieldInPlan).toBeDefined(); - const cultivation1 = cultivationPlan.find(item => item.b_lu_catalogue === catalogueItem1); - expect(cultivation1).toBeDefined(); - expect(cultivation1?.fields.length).toBe(2); + expect(fieldInPlan?.fertilizer_applications.length).toBeGreaterThan(0); + + const fertilizerApp = fieldInPlan!.fertilizer_applications.find(fa => fa.p_app_id != null) + + //Check for some key fertilizer application details (adapt as needed based on your data) + expect(fertilizerApp!.p_app_amount).toEqual(100) + expect(fertilizerApp!.p_app_method).toEqual('broadcasting') - const cultivation2 = cultivationPlan.find(item => item.b_lu_catalogue === catalogueItem2); - expect(cultivation2).toBeDefined(); - expect(cultivation2?.fields.length).toBe(1); }); + + + it('should return an empty array if no cultivations are found for the farm', async () => { + const emptyPlan = await getCultivationPlan(fdm, nanoid()); // Use a non-existent farm ID + expect(emptyPlan).toEqual([]); + }); + + }); }) \ No newline at end of file diff --git a/fdm-core/src/cultivation.ts b/fdm-core/src/cultivation.ts index 71fa239e1..5dc4e9b45 100644 --- a/fdm-core/src/cultivation.ts +++ b/fdm-core/src/cultivation.ts @@ -3,7 +3,7 @@ import { nanoid } from 'nanoid' import * as schema from './db/schema' import { type FdmType } from './fdm' -import { getCultivationType } from './cultivation.d' +import { cultivationPlanType, getCultivationType } from './cultivation.d' import { b } from 'vitest/dist/chunks/suite.BMWOKiTe.js' /** @@ -50,8 +50,8 @@ export async function addCultivationToCatalogue( .where(eq(schema.cultivationsCatalogue.b_lu_catalogue, properties.b_lu_catalogue)) .limit(1) - if (existing.length > 0) { - throw new Error('Cultivation already exists in catalogue') + if (existing.length > 0) { + throw new Error('Cultivation already exists in catalogue') } // Insert the cultivation in the db @@ -198,6 +198,7 @@ export async function getCultivation(fdm: FdmType, b_lu: schema.cultivationsType * @param fdm The FDM instance. * @param b_id The ID of the field. * @returns A Promise that resolves with an array of cultivation details. + * @alpha */ export async function getCultivations(fdm: FdmType, b_id: schema.fieldSowingTypeSelect['b_id']): Promise { @@ -226,20 +227,29 @@ export async function getCultivations(fdm: FdmType, b_id: schema.fieldSowingType * * The cultivation plan is an array of objects, where each object represents a unique cultivation * identified by its `b_lu_catalogue`. Each cultivation object also contains a `fields` array, - * listing the fields associated with that specific cultivation. The `fields` array contains objects, - * each specifying the `b_lu` (cultivation ID) and `b_id` (field ID) combination. + * listing the fields associated with that specific cultivation. Within each field object, there's + * a `fertilizer_applications` array detailing the fertilizers applied to that field. * * @param fdm The FDM instance. * @param b_id_farm The ID of the farm for which to retrieve the cultivation plan. - * @returns A Promise that resolves with an array representing the cultivation plan. + * @returns A Promise that resolves with an array representing the cultivation plan. * Each element in the array is an object with the following structure: * ``` * { * b_lu_catalogue: string; // Unique ID of the cultivation catalogue item * b_lu_name: string; // Name of the cultivation * fields: { // Array of fields associated with this cultivation - * b_lu: string; // Unique ID of the cultivation + * b_lu: string; // Unique ID of the cultivation * b_id: string; // Unique ID of the field + * b_name: string; // Name of the field + * fertilizer_applications: { // Array of fertilizer applications on this field + * p_id_catalogue: string; // Fertilizer catalogue ID + * p_name_nl: string; // Fertilizer name (Dutch) + * p_app_amount: number; // Amount applied + * p_app_method: string; // Application method + * p_app_date: Date; // Application date + * p_app_id: string; // Unique ID of the application + * }[] * }[]; * } * ``` @@ -248,22 +258,14 @@ export async function getCultivations(fdm: FdmType, b_id: schema.fieldSowingType * ```typescript * const cultivationPlan = await getCultivationPlan(fdm, 'farm123'); * if (cultivationPlan.length > 0) { - * console.log("Cultivation Plan:", cultivationPlan); + * console.log("Cultivation Plan:", cultivationPlan); * } else { * console.log("No cultivations found for this farm."); * } * ``` * @alpha */ -export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTypeSelect['b_id_farm']): Promise; -}>> { +export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTypeSelect['b_id_farm']): Promise { if (!b_id_farm) { throw new Error('Farm ID is required') } @@ -275,7 +277,13 @@ export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTy b_lu_name: schema.cultivationsCatalogue.b_lu_name, b_lu: schema.cultivations.b_lu, b_id: schema.fields.b_id, - b_name: schema.fields.b_name + b_name: schema.fields.b_name, + p_id_catalogue: schema.fertilizersCatalogue.p_id_catalogue, + p_name_nl: schema.fertilizersCatalogue.p_name_nl, + p_app_amount: schema.fertilizerApplication.p_app_amount, + p_app_method: schema.fertilizerApplication.p_app_method, + p_app_date: schema.fertilizerApplication.p_app_date, + p_app_id: schema.fertilizerApplication.p_app_id }) .from(schema.farms) .leftJoin(schema.farmManaging, eq(schema.farms.b_id_farm, schema.farmManaging.b_id_farm)) @@ -283,23 +291,64 @@ export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTy .leftJoin(schema.fieldSowing, eq(schema.fields.b_id, schema.fieldSowing.b_id)) .leftJoin(schema.cultivations, eq(schema.fieldSowing.b_lu, schema.cultivations.b_lu)) .leftJoin(schema.cultivationsCatalogue, eq(schema.cultivations.b_lu_catalogue, schema.cultivationsCatalogue.b_lu_catalogue)) + .leftJoin(schema.fertilizerApplication, eq(schema.fertilizerApplication.b_id, schema.fields.b_id)) + .leftJoin(schema.fertilizerPicking, eq(schema.fertilizerPicking.p_id, schema.fertilizerApplication.p_id)) + .leftJoin(schema.fertilizersCatalogue, eq(schema.fertilizersCatalogue.p_id_catalogue, schema.fertilizerPicking.p_id_catalogue)) .where(and( eq(schema.farms.b_id_farm, b_id_farm), isNotNull(schema.cultivationsCatalogue.b_lu_catalogue)) ) - const cultivationPlan = cultivations.reduce((acc, curr) => { - const existingCultivation = acc.find(item => item.b_lu_catalogue === curr.b_lu_catalogue) + const cultivationPlan = cultivations.reduce((acc: cultivationPlanType[], curr) => { + const existingCultivation = acc.find(item => item.b_lu_catalogue === curr.b_lu_catalogue); if (existingCultivation) { - existingCultivation.fields.push({ b_lu: curr.b_lu, b_id: curr.b_id, b_name: curr.b_name }) + const existingField = existingCultivation.fields.find(field => field.b_id === curr); + if (existingField) { + if (curr.p_app_id) { + existingField.fertilizer_applications.push({ + p_id_catalogue: curr.p_id_catalogue, + p_name_nl: curr.p_name_nl, + p_app_amount: curr.p_app_amount, + p_app_method: curr.p_app_method, + p_app_date: curr.p_app_date, + p_app_id: curr.p_app_id + }); + } + } else { + existingCultivation.fields.push({ + b_lu: curr.b_lu, + b_id: curr.b_id, + b_name: curr.b_name, + fertilizer_applications: curr.p_app_id ? [{ + p_id_catalogue: curr.p_id_catalogue, + p_name_nl: curr.p_name_nl, + p_app_amount: curr.p_app_amount, + p_app_method: curr.p_app_method, + p_app_date: curr.p_app_date, + p_app_id: curr.p_app_id + }] : [], + }); + } } else { acc.push({ b_lu_catalogue: curr.b_lu_catalogue, b_lu_name: curr.b_lu_name, - fields: [{ b_lu: curr.b_lu, b_id: curr.b_id, b_name: curr.b_name }] + fields: [{ + b_lu: curr.b_lu, + b_id: curr.b_id, + b_name: curr.b_name, + fertilizer_applications: curr.p_app_id ? [{ + p_id_catalogue: curr.p_id_catalogue, + p_name_nl: curr.p_name_nl, + p_app_amount: curr.p_app_amount, + p_app_method: curr.p_app_method, + p_app_date: curr.p_app_date, + p_app_id: curr.p_app_id + }] : [], + }], }); } - return acc + return acc; }, []); return cultivationPlan From be8d2ea4ee6cb6ce354b4f0e116f2ecddb1d473e Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:54:26 +0100 Subject: [PATCH 16/65] Submit something when adding --- .../custom/combobox-fertilizers.tsx | 163 +++++++++++------- ...b_id_farm.cultivations.$b_lu_catalogue.tsx | 22 ++- 2 files changed, 119 insertions(+), 66 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 3a2d755bf..a5df74ce7 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -6,81 +6,116 @@ import { Input } from "../ui/input" import { Label } from "../ui/label" import { Combobox } from "../custom/combobox" +import { Form, useFetcher, useNavigation } from "@remix-run/react" +import { FormEvent } from "react" -export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string }) { +export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string, action: string }) { + const navigation = useNavigation(); + const fetcher = useFetcher(); + + + // async function handleClickOnSubmitAddFertilizer(e: FormEvent) { + + // e.currentTarget + // const formData = new FormData(e.currentTarget); + // formData.append("actionForm", 'addFertilizer') + // console.log(e.currentTarget) + + // await fetcher.submit(formData, { + // method: "POST", + // }) + + + // } + async function handleClickOnSubmitRemoveFertilizer() { + + const formData = new FormData(); + formData.append("actionForm", 'removeFertilizer') + + await fetcher.submit(formData, { + method: "POST", + }) + } return (
-
-
- - -
-
- - +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
- - -
-
- -
-
-
- -
- {/*
Meststoffen
*/} -
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

-
-
- -
- {/*
*/} -
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

+ +
+ {/*
Meststoffen
*/} +
+
+
+

+ Runderdrijfmest +

+ {/*

m@example.com

*/} +
+
+

+ 30 ton / ha +

+
+
+

+ 2024-04-01 +

+
+
+ +
+ {/*
*/}
-
- +
+
+

+ Runderdrijfmest +

+ {/*

m@example.com

*/} +
+
+

+ 30 ton / ha +

+
+
+

+ 2024-04-01 +

+
+
+ +
-
+
) } \ No newline at end of file diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx index 92c6865e6..973433eeb 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx @@ -1,4 +1,4 @@ -import { type MetaFunction, type LoaderFunctionArgs, json } from "@remix-run/node"; +import { type MetaFunction, type LoaderFunctionArgs, json, ActionFunctionArgs } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; // Components @@ -115,6 +115,7 @@ export default function Index() { Vul de bemesting op bouwplanniveau in voor dit gewas.

@@ -131,6 +132,23 @@ export default function Index() {
- ); +} + +export async function action({ + request, params +}: ActionFunctionArgs) { + + const b_id_farm = params.b_id_farm + const b_lu_catalogue = params.b_lu_catalogue + const formData = await request.formData() + const form = formData.get('form') + + + if ( form === 'addFertilizer') { + return json({ success: true }) + } else { + throw new Error("Invalid POST actionForm") + } + } \ No newline at end of file From aab6c96099d422d8b6e6a876b90f3058813ac834 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:11:34 +0100 Subject: [PATCH 17/65] Upgrade date input to input picker --- .../custom/combobox-fertilizers.tsx | 126 +++++++++++------- 1 file changed, 77 insertions(+), 49 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index a5df74ce7..9510ea4f5 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -7,7 +7,12 @@ import { Label } from "../ui/label" import { Combobox } from "../custom/combobox" import { Form, useFetcher, useNavigation } from "@remix-run/react" -import { FormEvent } from "react" +import { format } from "date-fns" +import { FormEvent, useState } from "react" +import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover" +import { cn } from "@/lib/utils" +import { CalendarIcon } from "lucide-react" +import { Calendar } from "../ui/calendar" export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string, action: string }) { const navigation = useNavigation(); @@ -37,6 +42,8 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st }) } + const [date, setDate] = useState() + return (
@@ -54,7 +61,28 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st
- + + + + + + + +
-
- -
- {/*
Meststoffen
*/} -
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

-
-
- -
- {/*
*/} + +
+ +
+ {/*
Meststoffen
*/} +
+
+
+

+ Runderdrijfmest +

+ {/*

m@example.com

*/} +
+
+

+ 30 ton / ha +

+
+
+

+ 2024-04-01 +

+
+
+
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

-
-
- -
+ {/*
*/} +
+
+
+

+ Runderdrijfmest +

+ {/*

m@example.com

*/} +
+
+

+ 30 ton / ha +

+
+
+

+ 2024-04-01 +

+
+
+
- +
) } \ No newline at end of file From c10e25c468804a106e5d10a355002593640d7be7 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 09:02:25 +0100 Subject: [PATCH 18/65] Fix migration issue --- fdm-app/app/components/custom/combobox-fertilizers.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 9510ea4f5..15dbe8845 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -6,9 +6,9 @@ import { Input } from "../ui/input" import { Label } from "../ui/label" import { Combobox } from "../custom/combobox" -import { Form, useFetcher, useNavigation } from "@remix-run/react" +import { Form, useFetcher, useNavigation } from "react-router" import { format } from "date-fns" -import { FormEvent, useState } from "react" +import { useState } from "react" import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover" import { cn } from "@/lib/utils" import { CalendarIcon } from "lucide-react" From e2a4bd84dcdd1bf6e11a04066cc6bfaab774ab47 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:59:13 +0100 Subject: [PATCH 19/65] Refactor cultivation plan page --- .../components/blocks/cultivation-plan.tsx | 35 ------ fdm-app/app/components/ui/pagination.tsx | 116 ++++++++++++++++++ ...cultivations.$b_lu_catalogue.covercrop.tsx | 1 + ...farm.cultivations.$b_lu_catalogue.crop.tsx | 1 + ...ltivations.$b_lu_catalogue.fertilizers.tsx | 1 + ...b_id_farm.cultivations.$b_lu_catalogue.tsx | 71 +++++++---- .../app.addfarm.$b_id_farm.cultivations.tsx | 44 ++++++- 7 files changed, 204 insertions(+), 65 deletions(-) create mode 100644 fdm-app/app/components/ui/pagination.tsx create mode 100644 fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.covercrop.tsx create mode 100644 fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.crop.tsx create mode 100644 fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx diff --git a/fdm-app/app/components/blocks/cultivation-plan.tsx b/fdm-app/app/components/blocks/cultivation-plan.tsx index 8ba341eef..8bac2a670 100644 --- a/fdm-app/app/components/blocks/cultivation-plan.tsx +++ b/fdm-app/app/components/blocks/cultivation-plan.tsx @@ -8,42 +8,7 @@ import { buttonVariants } from "@/components/ui/button" import { Calendar } from "@/components/ui/calendar" // import { nl } from "react-day-picker/locale" // Could not be found somehow -interface SidebarNavProps extends React.HTMLAttributes { - items: { - href: string - title: string - }[] -} -export function SidebarNav({ className, items, ...props }: SidebarNavProps) { - const { pathname } = useLocation(); - - return ( - - ) -} export default function Cultivation(props: { action: string | undefined; }) { const navigation = useNavigation(); diff --git a/fdm-app/app/components/ui/pagination.tsx b/fdm-app/app/components/ui/pagination.tsx new file mode 100644 index 000000000..e9120dcc8 --- /dev/null +++ b/fdm-app/app/components/ui/pagination.tsx @@ -0,0 +1,116 @@ +import * as React from "react" +import { cn } from "~/lib/utils" +import { ButtonProps, buttonVariants } from "~/components/ui/button" +import { ChevronLeftIcon, ChevronRightIcon, DotsHorizontalIcon } from "@radix-ui/react-icons" + +const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => ( +
- + */}
); } - -export async function action({ - request, params -}: ActionFunctionArgs) { - - const b_id_farm = params.b_id_farm - const b_lu_catalogue = params.b_lu_catalogue - const formData = await request.formData() - const form = formData.get('form') - - - if ( form === 'addFertilizer') { - return json({ success: true }) - } else { - throw new Error("Invalid POST actionForm") - } - -} \ No newline at end of file diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx index 8568b848d..2c0d03a98 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx @@ -1,4 +1,4 @@ -import { type MetaFunction, type LoaderFunctionArgs, data } from "react-router"; +import { type MetaFunction, type LoaderFunctionArgs, data, useLocation } from "react-router"; import { Outlet, useLoaderData } from "react-router"; // Components @@ -13,8 +13,9 @@ import { Toaster } from "@/components/ui/toaster" // FDM import { fdm } from "../services/fdm.server"; import { getCultivationPlan, getFarm } from "@svenvw/fdm-core"; -import { Button } from "@/components/ui/button"; +import { Button, buttonVariants } from "@/components/ui/button"; import { SidebarNav } from "@/components/blocks/cultivation-plan"; +import { cn } from "@/lib/utils"; // Meta export const meta: MetaFunction = () => { @@ -125,4 +126,41 @@ export default function Index() { ); -} \ No newline at end of file +} + +interface SidebarNavProps extends React.HTMLAttributes { + items: { + href: string + title: string + }[] +} + +export function SidebarNav({ className, items, ...props }: SidebarNavProps) { + const { pathname } = useLocation(); + + return ( + + ) +} From 3c878ff512372d13bd98d7c6fe46f5ceddf9ab80 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:00:07 +0100 Subject: [PATCH 20/65] Start converting to form --- .../custom/combobox-fertilizers.tsx | 176 ++++++++++++------ ...ltivations.$b_lu_catalogue.fertilizers.tsx | 75 +++++++- ...b_id_farm.cultivations.$b_lu_catalogue.tsx | 20 +- 3 files changed, 199 insertions(+), 72 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 15dbe8845..cdcb629d3 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -1,23 +1,61 @@ - - -import { Button } from "@/components/ui/button" -import { Separator } from "../ui/separator" -import { Input } from "../ui/input" -import { Label } from "../ui/label" - -import { Combobox } from "../custom/combobox" import { Form, useFetcher, useNavigation } from "react-router" import { format } from "date-fns" import { useState } from "react" -import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover" -import { cn } from "@/lib/utils" +import { zodResolver } from "@hookform/resolvers/zod" +import { useRemixForm, RemixFormProvider } from "remix-hook-form" +import { z } from "zod" + +// Components import { CalendarIcon } from "lucide-react" -import { Calendar } from "../ui/calendar" +import { Button } from "@/components/ui/button" +import { Separator } from "@/components/ui/separator" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" +import { Calendar } from "@/components/ui/calendar" +import { + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { Combobox } from "@/components/custom/combobox" + +import { cn } from "@/lib/utils" +import { LoadingSpinner } from "./loadingspinner" + +export const FormSchema = z.object({ + p_app_amount: z.coerce.number({ + required_error: "Hoeveelheid is verplicht", + invalid_type_error: "Hoeveelheid moet een getal zijn", + }).positive({ + message: "Hoeveelheid moet positief zijn", + }).finite({ + message: "Hoeveelheid moet een geheel getal zijn", + }).safe({ + message: "Hoeveelheid moet een safe getal zijn", + }), + p_app_date: z.coerce.date({ + required_error: "Datum is verplicht", + invalid_type_error: "Datum is ongeldig", + }), +}) export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string, action: string }) { const navigation = useNavigation(); const fetcher = useFetcher(); + const form = useRemixForm>({ + mode: "onTouched", + resolver: zodResolver(FormSchema), + defaultValues: { + p_app_amount: 0, + p_app_date: new Date(), + }, + }) + // async function handleClickOnSubmitAddFertilizer(e: FormEvent) { @@ -46,53 +84,79 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st return (
-
- -
-
- - -
-
- - -
-
- - - - - - - - - -
-
- -
-
-
+
+ {/*
+ + + + + + + + + +
*/} +
+ {/* */} + +
+ + + +
diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index cb0f1c291..197a967f7 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -1 +1,74 @@ -export default function Index() {} \ No newline at end of file +import { useLoaderData, type LoaderFunctionArgs, data, ActionFunctionArgs } from "react-router"; +import { extractFormValuesFromRequest } from "@/lib/form"; +import { FormSchema } from "@/components/custom/combobox-fertilizers"; + +// Components +import { ComboboxFertilizers } from "@/components/custom/combobox-fertilizers"; + +// FDM +import { fdm } from "../services/fdm.server"; +import { getCultivationPlan, getCultivationsFromCatalogue, getFertilizersFromCatalogue } from "@svenvw/fdm-core"; + +// Loader +export async function loader({ + request, params +}: LoaderFunctionArgs) { + + // Get the Id of the farm + const b_id_farm = params.b_id_farm + if (!b_id_farm) { + throw data("Farm ID is required", { status: 400, statusText: "Farm ID is required" }); + } + + // Get the cultivation + const b_lu_catalogue = params.b_lu_catalogue + if (!b_lu_catalogue) { + throw data("Cultivation catalogue ID is required", { status: 400, statusText: "Cultivation catalogue ID is required" }); + } + + // Fertilizer options + const fertilizersCatalogue = await getFertilizersFromCatalogue(fdm) + const fertilizerOptions = fertilizersCatalogue.map(fertilizer => { + return { + value: fertilizer.p_id_catalogue, + label: fertilizer.p_name_nl + } + }) + + + return { + b_lu_catalogue: b_lu_catalogue, + b_id_farm: b_id_farm, + fertilizerOptions: fertilizerOptions + } +} + +export default function Index() { + const loaderData = useLoaderData(); + + return ( +
+

+ Vul de bemesting op bouwplanniveau in voor dit gewas. +

+ +
+ ) +} + +export async function action({ + request, + }: ActionFunctionArgs) { + console.log("action") + + const formValues = await extractFormValuesFromRequest(request, FormSchema) + console.log(formValues) + + return { + ok: true, + } + + } \ No newline at end of file diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx index cc5d862bc..12e81049e 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.tsx @@ -57,21 +57,10 @@ export async function loader({ } }) - // Fertilizer options - const fertilizersCatalogue = await getFertilizersFromCatalogue(fdm) - const fertilizerOptions = fertilizersCatalogue.map(fertilizer => { - return { - value: fertilizer.p_id_catalogue, - label: fertilizer.p_name_nl - } - }) - return { b_lu_catalogue: b_lu_catalogue, b_id_farm: b_id_farm, - cultivation: cultivation, - fertilizerOptions: fertilizerOptions, - cultivationOptions: cultivationOptions + cultivation: cultivation } } @@ -94,7 +83,7 @@ export default function Index() { }, { title: 'Bemesting', - href: `/app/addfarm/${loaderData.b_id_farm}/cultivations/${loaderData.b_lu_catalogue}/fertilizer` + href: `/app/addfarm/${loaderData.b_id_farm}/cultivations/${loaderData.b_lu_catalogue}/fertilizers` }, { title: 'Vanggewas', @@ -115,9 +104,10 @@ export default function Index() { {items.map((item) => ( - + Date: Thu, 12 Dec 2024 14:39:17 +0100 Subject: [PATCH 21/65] Add date picker to form --- .../custom/combobox-fertilizers.tsx | 82 +++++++++++++++---- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 3 + 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index cdcb629d3..4f3af4c90 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -91,28 +91,74 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st >
- {/*
- +
+ {/* -
*/} + /> */} +
+
+ ( + + Hoeveelheid* + + + + + + + )} + /> +
+
- ( - - Hoeveelheid* - - - - - - - )} - /> + ( + + Datum + + + + + + + + + // date > new Date() || date < new Date("1900-01-01") + // } + initialFocus + /> + + + + + + )} + />
+ {/*
diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 197a967f7..932a3d638 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -66,6 +66,9 @@ export async function action({ const formValues = await extractFormValuesFromRequest(request, FormSchema) console.log(formValues) + + const {p_app_amount, p_app_date} = formValues; + console.log(format(p_app_date)) return { ok: true, From 55313cf3d4c7e4a2024fccdc23f7712137140eb2 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:20:54 +0100 Subject: [PATCH 22/65] Include the combobox to the form --- .../custom/combobox-fertilizers.tsx | 15 ++- fdm-app/app/components/custom/combobox.tsx | 127 ++++++++++-------- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 1 - 3 files changed, 80 insertions(+), 63 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 4f3af4c90..cafe3bf0e 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -41,10 +41,13 @@ export const FormSchema = z.object({ required_error: "Datum is verplicht", invalid_type_error: "Datum is ongeldig", }), + p_id: z.coerce.string({ // TODO: Validate against the options that are available + required_error: "Keuze van meststof is verplicht", + invalid_type_error: "Meststof is ongeldig", + }) }) export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string, action: string }) { - const navigation = useNavigation(); const fetcher = useFetcher(); const form = useRemixForm>({ @@ -52,7 +55,7 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st resolver: zodResolver(FormSchema), defaultValues: { p_app_amount: 0, - p_app_date: new Date(), + // p_app_date: new Date(), }, }) @@ -81,7 +84,6 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st } const [date, setDate] = useState() - return (
@@ -92,10 +94,13 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st
- {/* + {/* */} */} + form={form} + name="fertilizer" + label={Meststof*} + />
void - onOpenChange?: (open: boolean) => void + form: any + name: string + label: any } export function Combobox({ options, - value: controlledValue, - defaultValue, - onChange, - onOpenChange + form, + name, + label }: ComboboxProps) { const [open, setOpen] = useState(false) - const [internalValue, setInternalValue] = useState(defaultValue ?? "") - - const value = controlledValue ?? internalValue - const handleValueChange = (newValue: string) => { - setInternalValue(newValue) - onChange?.(newValue) - } - const name = "combobox" return ( - - - - - - - - - Niks gevonden - - {options.map((option: optionType) => ( - { - setInternalValue(currentValue === value ? "" : currentValue) - setOpen(false) - }} + ( + + {label} + + + + + + + + + + + Niks gevonden + + {options.map((option: optionType) => ( + { + form.setValue(name, option.value) + setOpen(false) + }} + > +

{option.label}

+ +
+ ))} +
+
+
+
+
+ + +
+ )} + /> ) } \ No newline at end of file diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 932a3d638..9d5e84dc2 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -68,7 +68,6 @@ export async function action({ console.log(formValues) const {p_app_amount, p_app_date} = formValues; - console.log(format(p_app_date)) return { ok: true, From eb7bd667ceedcca714e2ed16e562aaa5b6b7b94f Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:22:34 +0100 Subject: [PATCH 23/65] Fixes --- .../custom/combobox-fertilizers.tsx | 122 +++++++++--------- 1 file changed, 60 insertions(+), 62 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index cafe3bf0e..11eb67392 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -83,7 +83,6 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st }) } - const [date, setDate] = useState() return (
@@ -91,79 +90,78 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st
-
{/* */} Meststof*} + name="p_id" + label={Meststof*} />
- ( - - Hoeveelheid* - - - - - - - )} - /> + ( + + Hoeveelheid* + + + + + + + )} + />
- +
- ( - - Datum - - - - - - - - - // date > new Date() || date < new Date("1900-01-01") - // } - initialFocus - /> - - - - - - )} - /> + ( + + Datum + + + + + + + + + // date > new Date() || date < new Date("1900-01-01") + // } + initialFocus + /> + + + + + + )} + />
- + {/*
From 92bae8b0eddf08218e5598c17afe346b7e74e1ca Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:43:10 +0100 Subject: [PATCH 24/65] Remove old code --- .../custom/combobox-fertilizers.tsx | 35 ++----------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 11eb67392..de11eb76e 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -160,39 +160,8 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st )} /> -
- - {/*
- - - - - - - - - -
*/} -
- {/* */} +
+
diff --git a/fdm-app/app/routes/app.addfarm.new.tsx b/fdm-app/app/routes/app.addfarm.new.tsx index 809b595f9..b6ec69b2a 100644 --- a/fdm-app/app/routes/app.addfarm.new.tsx +++ b/fdm-app/app/routes/app.addfarm.new.tsx @@ -1,7 +1,7 @@ import type { MetaFunction, ActionFunctionArgs, LoaderFunctionArgs } from "react-router"; import { useLoaderData, redirect } from "react-router"; import { z } from "zod" -import { addFarm, getFertilizersFromCatalogue } from "@svenvw/fdm-core"; +import { addFarm, addFertilizer, getFertilizersFromCatalogue } from "@svenvw/fdm-core"; // Components import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator } from "@/components/ui/breadcrumb"; @@ -25,9 +25,9 @@ export const meta: MetaFunction = () => { const FormSchema = z.object({ b_name_farm: z.string({ - required_error: "Naam van bedrijf is verplicht", + required_error: "Naam van bedrijf is verplicht", }).min(3, { - message: "Naam van bedrijf moet minimaal 3 karakters bevatten", + message: "Naam van bedrijf moet minimaal 3 karakters bevatten", }), }) @@ -35,35 +35,9 @@ const FormSchema = z.object({ export async function loader({ request, }: LoaderFunctionArgs) { - const fertilizers = await getFertilizersFromCatalogue(fdm); - - const organicFertilizersList = fertilizers - .filter(x => { return (x.p_type_manure || x.p_type_compost) }) - .map(x => { - return { - value: x.p_id_catalogue, - label: x.p_name_nl - } - }) - - const mineralFertilizersList = fertilizers - .filter(x => { return (x.p_type_mineral) }) - .map(x => { - return { - value: x.p_id_catalogue, - label: x.p_name_nl - } - }) return { - values: { - b_name_farm: null, - b_fertilizers_organic: null, - }, - lists: { - organicFertilizersList: organicFertilizersList, - mineralFertilizersList: mineralFertilizersList - } + b_name_farm: null, }; } @@ -97,11 +71,7 @@ export default function AddFarmPage() {
@@ -125,5 +95,11 @@ export async function action({ // Create a farm const b_id_farm = await addFarm(fdm, b_name_farm, null) + // Add the fertilizers from the catalogue to the database + const fertilizers = await getFertilizersFromCatalogue(fdm); + await fertilizers.map(async (fertilizer) => { + await addFertilizer(fdm, fertilizer.p_id_catalogue, b_id_farm) + }) + return redirect(`../addfarm/${b_id_farm}/map`) } \ No newline at end of file From efa423de6bc72ebc3060aa9a8d9da9632d331c7b Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:33:46 +0100 Subject: [PATCH 26/65] Export `getFertilizer` and `getFertilizers` --- .changeset/ninety-dots-compete.md | 5 +++++ fdm-core/src/index.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/ninety-dots-compete.md diff --git a/.changeset/ninety-dots-compete.md b/.changeset/ninety-dots-compete.md new file mode 100644 index 000000000..788d32b90 --- /dev/null +++ b/.changeset/ninety-dots-compete.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Export `getFertilizer` and `getFertilizers` diff --git a/fdm-core/src/index.ts b/fdm-core/src/index.ts index eeaa24477..d3aa330e8 100644 --- a/fdm-core/src/index.ts +++ b/fdm-core/src/index.ts @@ -21,6 +21,6 @@ export { createFdmServer, migrateFdmServer } from './fdm-server' // export { createFdmLocal, migrateFdmLocal } from './fdm-local' export { addFarm, getFarm, updateFarm, } from './farm' export { addField, getField, getFields, updateField } from './field' -export { addFertilizerToCatalogue, getFertilizersFromCatalogue, addFertilizer, removeFertilizer, addFertilizerApplication, updateFertilizerApplication, removeFertilizerApplication, getFertilizerApplication, getFertilizerApplications} from './fertilizer' +export { addFertilizerToCatalogue, getFertilizersFromCatalogue, addFertilizer, removeFertilizer, getFertilizer, getFertilizers, addFertilizerApplication, updateFertilizerApplication, removeFertilizerApplication, getFertilizerApplication, getFertilizerApplications} from './fertilizer' export { addCultivationToCatalogue, getCultivationsFromCatalogue, addCultivation, removeCultivation, getCultivation, getCultivations, getCultivationPlan } from './cultivation' export { signUpUser, getUserFromSession} from './iam' \ No newline at end of file From 5be0abc1c2c4a93a6207e22dea6f645faaf3e036 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:42:01 +0100 Subject: [PATCH 27/65] `getFertilizers` returns the details of the fertilizers similiar as `getFertilizer` --- .changeset/tough-boxes-clean.md | 5 ++++ fdm-core/src/fertilizer.d.ts | 4 --- fdm-core/src/fertilizer.ts | 43 ++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 .changeset/tough-boxes-clean.md diff --git a/.changeset/tough-boxes-clean.md b/.changeset/tough-boxes-clean.md new file mode 100644 index 000000000..beb0e0c32 --- /dev/null +++ b/.changeset/tough-boxes-clean.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +`getFertilizers` returns the details of the fertilizers similiar as `getFertilizer` diff --git a/fdm-core/src/fertilizer.d.ts b/fdm-core/src/fertilizer.d.ts index c831e5dd8..2c8e2fdce 100644 --- a/fdm-core/src/fertilizer.d.ts +++ b/fdm-core/src/fertilizer.d.ts @@ -34,8 +34,4 @@ export interface getFertilizerType { p_pb_rt: number | null p_hg_rt: number | null p_cl_cr: number | null -} - -export interface getFertilizersType { - p_id: string } \ No newline at end of file diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index e89636daa..9a03e7c57 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -3,7 +3,7 @@ import { nanoid } from 'nanoid' import * as schema from './db/schema' import { type FdmType } from './fdm' -import { getFertilizersType, getFertilizerType } from './fertilizer.d' +import { getFertilizerType } from './fertilizer.d' /** * Retrieves all fertilizers from the catalogue. @@ -220,17 +220,52 @@ export async function getFertilizer(fdm: FdmType, p_id: schema.fertilizersTypeSe * @returns A Promise that resolves with an array of fertilizer IDs. * @alpha */ -export async function getFertilizers(fdm: FdmType, b_id_farm: schema.fertilizerAcquiringTypeSelect['b_id_farm']): Promise { +export async function getFertilizers(fdm: FdmType, b_id_farm: schema.fertilizerAcquiringTypeSelect['b_id_farm']): Promise { const fertilizers = await fdm .select({ - p_id: schema.fertilizers.p_id + p_id: schema.fertilizers.p_id, + p_name_nl: schema.fertilizersCatalogue.p_name_nl, + p_name_en: schema.fertilizersCatalogue.p_name_en, + p_description: schema.fertilizersCatalogue.p_description, + p_acquiring_amount: schema.fertilizerAcquiring.p_acquiring_amount, + p_acquiring_date: schema.fertilizerAcquiring.p_acquiring_date, + p_picking_date: schema.fertilizerPicking.p_picking_date, + p_n_rt: schema.fertilizersCatalogue.p_n_rt, + p_n_if: schema.fertilizersCatalogue.p_n_if, + p_n_of: schema.fertilizersCatalogue.p_n_of, + p_n_wc: schema.fertilizersCatalogue.p_n_wc, + p_p_rt: schema.fertilizersCatalogue.p_p_rt, + p_k_rt: schema.fertilizersCatalogue.p_k_rt, + p_mg_rt: schema.fertilizersCatalogue.p_mg_rt, + p_ca_rt: schema.fertilizersCatalogue.p_ca_rt, + p_ne: schema.fertilizersCatalogue.p_ne, + p_s_rt: schema.fertilizersCatalogue.p_s_rt, + p_s_wc: schema.fertilizersCatalogue.p_s_wc, + p_cu_rt: schema.fertilizersCatalogue.p_cu_rt, + p_zn_rt: schema.fertilizersCatalogue.p_zn_rt, + p_na_rt: schema.fertilizersCatalogue.p_na_rt, + p_si_rt: schema.fertilizersCatalogue.p_si_rt, + p_b_rt: schema.fertilizersCatalogue.p_b_rt, + p_mn_rt: schema.fertilizersCatalogue.p_mn_rt, + p_ni_rt: schema.fertilizersCatalogue.p_ni_rt, + p_fe_rt: schema.fertilizersCatalogue.p_fe_rt, + p_mo_rt: schema.fertilizersCatalogue.p_mo_rt, + p_co_rt: schema.fertilizersCatalogue.p_co_rt, + p_as_rt: schema.fertilizersCatalogue.p_as_rt, + p_cd_rt: schema.fertilizersCatalogue.p_cd_rt, + p_cr_rt: schema.fertilizersCatalogue.p_cr_rt, + p_cr_vi: schema.fertilizersCatalogue.p_cr_vi, + p_pb_rt: schema.fertilizersCatalogue.p_pb_rt, + p_hg_rt: schema.fertilizersCatalogue.p_hg_rt, + p_cl_cr: schema.fertilizersCatalogue.p_cl_cr }) .from(schema.fertilizers) .leftJoin(schema.fertilizerAcquiring, eq(schema.fertilizers.p_id, schema.fertilizerAcquiring.p_id)) + .leftJoin(schema.fertilizerPicking, eq(schema.fertilizers.p_id, schema.fertilizerPicking.p_id)) + .leftJoin(schema.fertilizersCatalogue, eq(schema.fertilizerPicking.p_id_catalogue, schema.fertilizersCatalogue.p_id_catalogue)) .where(eq(schema.fertilizerAcquiring.b_id_farm, b_id_farm)) - return fertilizers } From 6ef3d440a1b43900fe53a5d55f950f8d96fddf1f Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:07:52 +0100 Subject: [PATCH 28/65] Alter `p_acquiring_date` and `p_picking_date` from date to timestamptz --- .changeset/six-plants-draw.md | 5 + fdm-core/src/cultivation.test.ts | 4 +- .../db/migrations/0002_famous_skullbuster.sql | 2 + .../src/db/migrations/meta/0002_snapshot.json | 1326 +++++++++++++++++ fdm-core/src/db/migrations/meta/_journal.json | 7 + fdm-core/src/db/schema.ts | 4 +- fdm-core/src/fertilizer.test.ts | 31 +- 7 files changed, 1362 insertions(+), 17 deletions(-) create mode 100644 .changeset/six-plants-draw.md create mode 100644 fdm-core/src/db/migrations/0002_famous_skullbuster.sql create mode 100644 fdm-core/src/db/migrations/meta/0002_snapshot.json diff --git a/.changeset/six-plants-draw.md b/.changeset/six-plants-draw.md new file mode 100644 index 000000000..bc7fa8ee9 --- /dev/null +++ b/.changeset/six-plants-draw.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-core": minor +--- + +Alter `p_acquiring_date` and `p_picking_date` from date to timestamptz diff --git a/fdm-core/src/cultivation.test.ts b/fdm-core/src/cultivation.test.ts index 8c873623d..618d758f1 100644 --- a/fdm-core/src/cultivation.test.ts +++ b/fdm-core/src/cultivation.test.ts @@ -243,7 +243,7 @@ describe('Cultivation Data Model', () => { const p_name_en = 'Test Fertilizer (EN)'; const p_description = 'This is a test fertilizer'; const p_acquiring_amount = 1000; - const p_acquiring_date = new Date().toISOString().split('T')[0]; + const p_acquiring_date = new Date(); await addFertilizerToCatalogue( fdm, { @@ -308,7 +308,7 @@ describe('Cultivation Data Model', () => { it('should get cultivation plan for a farm', async () => { - await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); + await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', new Date('2024-03-15')); const cultivationPlan = await getCultivationPlan(fdm, b_id_farm); diff --git a/fdm-core/src/db/migrations/0002_famous_skullbuster.sql b/fdm-core/src/db/migrations/0002_famous_skullbuster.sql new file mode 100644 index 000000000..8832b2e8f --- /dev/null +++ b/fdm-core/src/db/migrations/0002_famous_skullbuster.sql @@ -0,0 +1,2 @@ +ALTER TABLE "fdm-dev"."fertilizer_aquiring" ALTER COLUMN "p_acquiring_date" SET DATA TYPE timestamp with time zone;--> statement-breakpoint +ALTER TABLE "fdm-dev"."fertilizer_applying" ALTER COLUMN "p_app_date" SET DATA TYPE timestamp with time zone; \ No newline at end of file diff --git a/fdm-core/src/db/migrations/meta/0002_snapshot.json b/fdm-core/src/db/migrations/meta/0002_snapshot.json new file mode 100644 index 000000000..6d636947b --- /dev/null +++ b/fdm-core/src/db/migrations/meta/0002_snapshot.json @@ -0,0 +1,1326 @@ +{ + "id": "00b7ec3b-0e71-43e2-a165-49754ca6a2e8", + "prevId": "cba31a98-d13f-4d32-a439-66560f9ab977", + "version": "7", + "dialect": "postgresql", + "tables": { + "fdm-dev.cultivations": { + "name": "cultivations", + "schema": "fdm-dev", + "columns": { + "b_lu": { + "name": "b_lu", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "b_lu_catalogue": { + "name": "b_lu_catalogue", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "b_lu_idx": { + "name": "b_lu_idx", + "columns": [ + { + "expression": "b_lu", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cultivations_b_lu_catalogue_cultivations_catalogue_b_lu_catalogue_fk": { + "name": "cultivations_b_lu_catalogue_cultivations_catalogue_b_lu_catalogue_fk", + "tableFrom": "cultivations", + "tableTo": "cultivations_catalogue", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_lu_catalogue" + ], + "columnsTo": [ + "b_lu_catalogue" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.cultivations_catalogue": { + "name": "cultivations_catalogue", + "schema": "fdm-dev", + "columns": { + "b_lu_catalogue": { + "name": "b_lu_catalogue", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "b_lu_source": { + "name": "b_lu_source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "b_lu_name": { + "name": "b_lu_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "b_lu_name_en": { + "name": "b_lu_name_en", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "b_lu_hcat3": { + "name": "b_lu_hcat3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "b_lu_hcat3_name": { + "name": "b_lu_hcat3_name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "b_lu_catalogue_idx": { + "name": "b_lu_catalogue_idx", + "columns": [ + { + "expression": "b_lu_catalogue", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.farm_managing": { + "name": "farm_managing", + "schema": "fdm-dev", + "columns": { + "b_id": { + "name": "b_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "b_id_farm": { + "name": "b_id_farm", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "b_manage_start": { + "name": "b_manage_start", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "b_manage_end": { + "name": "b_manage_end", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "b_manage_type": { + "name": "b_manage_type", + "type": "b_manage_type", + "typeSchema": "fdm-dev", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "farm_managing_b_id_fields_b_id_fk": { + "name": "farm_managing_b_id_fields_b_id_fk", + "tableFrom": "farm_managing", + "tableTo": "fields", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_id" + ], + "columnsTo": [ + "b_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "farm_managing_b_id_farm_farms_b_id_farm_fk": { + "name": "farm_managing_b_id_farm_farms_b_id_farm_fk", + "tableFrom": "farm_managing", + "tableTo": "farms", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_id_farm" + ], + "columnsTo": [ + "b_id_farm" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "farm_managing_b_id_b_id_farm_pk": { + "name": "farm_managing_b_id_b_id_farm_pk", + "columns": [ + "b_id", + "b_id_farm" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.farms": { + "name": "farms", + "schema": "fdm-dev", + "columns": { + "b_id_farm": { + "name": "b_id_farm", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "b_name_farm": { + "name": "b_name_farm", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "b_sector": { + "name": "b_sector", + "type": "b_sector", + "typeSchema": "fdm-dev", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "b_id_farm_idx": { + "name": "b_id_farm_idx", + "columns": [ + { + "expression": "b_id_farm", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.fertilizer_aquiring": { + "name": "fertilizer_aquiring", + "schema": "fdm-dev", + "columns": { + "b_id_farm": { + "name": "b_id_farm", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_id": { + "name": "p_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_acquiring_amount": { + "name": "p_acquiring_amount", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_acquiring_date": { + "name": "p_acquiring_date", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "fertilizer_aquiring_b_id_farm_farms_b_id_farm_fk": { + "name": "fertilizer_aquiring_b_id_farm_farms_b_id_farm_fk", + "tableFrom": "fertilizer_aquiring", + "tableTo": "farms", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_id_farm" + ], + "columnsTo": [ + "b_id_farm" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "fertilizer_aquiring_p_id_fertilizers_p_id_fk": { + "name": "fertilizer_aquiring_p_id_fertilizers_p_id_fk", + "tableFrom": "fertilizer_aquiring", + "tableTo": "fertilizers", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "p_id" + ], + "columnsTo": [ + "p_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.fertilizer_applying": { + "name": "fertilizer_applying", + "schema": "fdm-dev", + "columns": { + "p_app_id": { + "name": "p_app_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "b_id": { + "name": "b_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_id": { + "name": "p_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_app_amount": { + "name": "p_app_amount", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_app_method": { + "name": "p_app_method", + "type": "p_app_method", + "typeSchema": "fdm-dev", + "primaryKey": false, + "notNull": false + }, + "p_app_date": { + "name": "p_app_date", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "p_app_idx": { + "name": "p_app_idx", + "columns": [ + { + "expression": "p_app_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "fertilizer_applying_b_id_fields_b_id_fk": { + "name": "fertilizer_applying_b_id_fields_b_id_fk", + "tableFrom": "fertilizer_applying", + "tableTo": "fields", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_id" + ], + "columnsTo": [ + "b_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "fertilizer_applying_p_id_fertilizers_p_id_fk": { + "name": "fertilizer_applying_p_id_fertilizers_p_id_fk", + "tableFrom": "fertilizer_applying", + "tableTo": "fertilizers", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "p_id" + ], + "columnsTo": [ + "p_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.fertilizer_picking": { + "name": "fertilizer_picking", + "schema": "fdm-dev", + "columns": { + "p_id": { + "name": "p_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_id_catalogue": { + "name": "p_id_catalogue", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_picking_date": { + "name": "p_picking_date", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "fertilizer_picking_p_id_fertilizers_p_id_fk": { + "name": "fertilizer_picking_p_id_fertilizers_p_id_fk", + "tableFrom": "fertilizer_picking", + "tableTo": "fertilizers", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "p_id" + ], + "columnsTo": [ + "p_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "fertilizer_picking_p_id_catalogue_fertilizers_catalogue_p_id_catalogue_fk": { + "name": "fertilizer_picking_p_id_catalogue_fertilizers_catalogue_p_id_catalogue_fk", + "tableFrom": "fertilizer_picking", + "tableTo": "fertilizers_catalogue", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "p_id_catalogue" + ], + "columnsTo": [ + "p_id_catalogue" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.fertilizers": { + "name": "fertilizers", + "schema": "fdm-dev", + "columns": { + "p_id": { + "name": "p_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "p_id_idx": { + "name": "p_id_idx", + "columns": [ + { + "expression": "p_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.fertilizers_catalogue": { + "name": "fertilizers_catalogue", + "schema": "fdm-dev", + "columns": { + "p_id_catalogue": { + "name": "p_id_catalogue", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "p_source": { + "name": "p_source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "p_name_nl": { + "name": "p_name_nl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "p_name_en": { + "name": "p_name_en", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "p_description": { + "name": "p_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "p_dm": { + "name": "p_dm", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_density": { + "name": "p_density", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_om": { + "name": "p_om", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_a": { + "name": "p_a", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_hc": { + "name": "p_hc", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_eom": { + "name": "p_eom", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_eoc": { + "name": "p_eoc", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_c_rt": { + "name": "p_c_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_c_of": { + "name": "p_c_of", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_c_if": { + "name": "p_c_if", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_c_fr": { + "name": "p_c_fr", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_cn_of": { + "name": "p_cn_of", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_n_rt": { + "name": "p_n_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_n_if": { + "name": "p_n_if", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_n_of": { + "name": "p_n_of", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_n_wc": { + "name": "p_n_wc", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_p_rt": { + "name": "p_p_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_k_rt": { + "name": "p_k_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_mg_rt": { + "name": "p_mg_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_ca_rt": { + "name": "p_ca_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_ne": { + "name": "p_ne", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_s_rt": { + "name": "p_s_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_s_wc": { + "name": "p_s_wc", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_cu_rt": { + "name": "p_cu_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_zn_rt": { + "name": "p_zn_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_na_rt": { + "name": "p_na_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_si_rt": { + "name": "p_si_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_b_rt": { + "name": "p_b_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_mn_rt": { + "name": "p_mn_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_ni_rt": { + "name": "p_ni_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_fe_rt": { + "name": "p_fe_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_mo_rt": { + "name": "p_mo_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_co_rt": { + "name": "p_co_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_as_rt": { + "name": "p_as_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_cd_rt": { + "name": "p_cd_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_cr_rt": { + "name": "p_cr_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_cr_vi": { + "name": "p_cr_vi", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_pb_rt": { + "name": "p_pb_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_hg_rt": { + "name": "p_hg_rt", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_cl_cr": { + "name": "p_cl_cr", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "p_type_manure": { + "name": "p_type_manure", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "p_type_mineral": { + "name": "p_type_mineral", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "p_type_compost": { + "name": "p_type_compost", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "p_id_catalogue_idx": { + "name": "p_id_catalogue_idx", + "columns": [ + { + "expression": "p_id_catalogue", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.field_sowing": { + "name": "field_sowing", + "schema": "fdm-dev", + "columns": { + "b_id": { + "name": "b_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "b_lu": { + "name": "b_lu", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "b_sowing_date": { + "name": "b_sowing_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "b_sowing_amount": { + "name": "b_sowing_amount", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "b_sowing_method": { + "name": "b_sowing_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "field_sowing_b_id_fields_b_id_fk": { + "name": "field_sowing_b_id_fields_b_id_fk", + "tableFrom": "field_sowing", + "tableTo": "fields", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_id" + ], + "columnsTo": [ + "b_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "field_sowing_b_lu_cultivations_b_lu_fk": { + "name": "field_sowing_b_lu_cultivations_b_lu_fk", + "tableFrom": "field_sowing", + "tableTo": "cultivations", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_lu" + ], + "columnsTo": [ + "b_lu" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "field_sowing_b_id_b_lu_pk": { + "name": "field_sowing_b_id_b_lu_pk", + "columns": [ + "b_id", + "b_lu" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.fields": { + "name": "fields", + "schema": "fdm-dev", + "columns": { + "b_id": { + "name": "b_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "b_name": { + "name": "b_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "b_geometry": { + "name": "b_geometry", + "type": "geometry(polygon)", + "primaryKey": false, + "notNull": false + }, + "b_id_source": { + "name": "b_id_source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "b_id_idx": { + "name": "b_id_idx", + "columns": [ + { + "expression": "b_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "b_geom_idx": { + "name": "b_geom_idx", + "columns": [ + { + "expression": "b_geometry", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gist", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.grants": { + "name": "grants", + "schema": "fdm-dev", + "columns": { + "b_farm_id": { + "name": "b_farm_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "destroyed": { + "name": "destroyed", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "grants_b_farm_id_farms_b_id_farm_fk": { + "name": "grants_b_farm_id_farms_b_id_farm_fk", + "tableFrom": "grants", + "tableTo": "farms", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "b_farm_id" + ], + "columnsTo": [ + "b_id_farm" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "grants_user_id_users_user_id_fk": { + "name": "grants_user_id_users_user_id_fk", + "tableFrom": "grants", + "tableTo": "users", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "user_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.session": { + "name": "session", + "schema": "fdm-dev", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_id_idx": { + "name": "session_id_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_users_user_id_fk": { + "name": "session_user_id_users_user_id_fk", + "tableFrom": "session", + "tableTo": "users", + "schemaTo": "fdm-dev", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "user_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "fdm-dev.users": { + "name": "users", + "schema": "fdm-dev", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "firstname": { + "name": "firstname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "surname": { + "name": "surname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created": { + "name": "created", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated": { + "name": "updated", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_id_idx": { + "name": "user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "enums": { + "fdm-dev.p_app_method": { + "name": "p_app_method", + "schema": "fdm-dev", + "values": [ + "slotted coulter", + "incorporation", + "injection", + "spraying", + "broadcasting", + "spoke wheel", + "pocket placement" + ] + }, + "fdm-dev.b_manage_type": { + "name": "b_manage_type", + "schema": "fdm-dev", + "values": [ + "owner", + "lease" + ] + }, + "fdm-dev.b_sector": { + "name": "b_sector", + "schema": "fdm-dev", + "values": [ + "diary", + "arable", + "tree_nursery", + "bulbs" + ] + } + }, + "schemas": { + "fdm-dev": "fdm-dev" + }, + "sequences": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index 46258a4fa..3baf1a98b 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -15,6 +15,13 @@ "when": 1733407330727, "tag": "0001_hesitant_brood", "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1734018887811, + "tag": "0002_famous_skullbuster", + "breakpoints": true } ] } \ No newline at end of file diff --git a/fdm-core/src/db/schema.ts b/fdm-core/src/db/schema.ts index 64c6931b7..eb1665542 100644 --- a/fdm-core/src/db/schema.ts +++ b/fdm-core/src/db/schema.ts @@ -80,7 +80,7 @@ export const fertilizerAcquiring = fdmSchema.table('fertilizer_aquiring', { b_id_farm: text().notNull().references(() => farms.b_id_farm), p_id: text().notNull().references(() => fertilizers.p_id), p_acquiring_amount: numericCasted(), //kg - p_acquiring_date: date({ mode: 'string' }), + p_acquiring_date: timestamp({ withTimezone: true }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), updated: timestamp({ withTimezone: true }) }) @@ -96,7 +96,7 @@ export const fertilizerApplication = fdmSchema.table('fertilizer_applying', { p_id: text().notNull().references(() => fertilizers.p_id), p_app_amount: numericCasted(), // kg / ha p_app_method: applicationMethodEnum(), - p_app_date: date({ mode: 'string' }), + p_app_date: timestamp({ withTimezone: true }), created: timestamp({ withTimezone: true }).notNull().defaultNow(), updated: timestamp({ withTimezone: true }) }, (table) => { diff --git a/fdm-core/src/fertilizer.test.ts b/fdm-core/src/fertilizer.test.ts index 73baea291..36e69d9f6 100644 --- a/fdm-core/src/fertilizer.test.ts +++ b/fdm-core/src/fertilizer.test.ts @@ -182,7 +182,7 @@ describe('Fertilizer Data Model', () => { ) const p_acquiring_amount = 1000 - const p_acquiring_date = new Date().toISOString().split('T')[0] + const p_acquiring_date = new Date() const p_id = await addFertilizer( fdm, p_id_catalogue, @@ -261,7 +261,7 @@ describe('Fertilizer Data Model', () => { ) const p_acquiring_amount = 1000 - const p_acquiring_date = new Date().toISOString().split('T')[0] + const p_acquiring_date = new Date() // Add two fertilizers to the farm await addFertilizer(fdm, p_id_catalogue, b_id_farm, p_acquiring_amount, p_acquiring_date) @@ -336,7 +336,7 @@ describe('Fertilizer Data Model', () => { ) const p_acquiring_amount = 1000 - const p_acquiring_date = new Date().toISOString().split('T')[0] + const p_acquiring_date = new Date() const p_id = await addFertilizer( fdm, p_id_catalogue, @@ -434,7 +434,7 @@ describe('Fertilizer Data Model', () => { ) const p_acquiring_amount = 1000 - const p_acquiring_date = new Date().toISOString().split('T')[0] + const p_acquiring_date = new Date() p_id = await addFertilizer( fdm, p_id_catalogue, @@ -450,13 +450,15 @@ describe('Fertilizer Data Model', () => { }); it('should add a new fertilizer application', async () => { + const p_app_date = new Date('2024-03-15'); + const new_p_app_id = await addFertilizerApplication( fdm, b_id, p_id, 100, 'broadcasting', - '2024-03-15', + p_app_date ); expect(new_p_app_id).toBeDefined(); @@ -466,19 +468,22 @@ describe('Fertilizer Data Model', () => { expect(fertilizerApplication?.p_id).toBe(p_id); expect(fertilizerApplication?.p_app_amount).toBe(100); expect(fertilizerApplication?.p_app_method).toBe('broadcasting'); - expect(fertilizerApplication?.p_app_date).toEqual('2024-03-15'); + expect(fertilizerApplication?.p_app_date).toEqual(p_app_date); }); it('should update a fertilizer application', async () => { - const p_app_id = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); + const p_app_date1 = new Date('2024-03-15'); + const p_app_date2 = new Date('2024-04-20'); + + const p_app_id = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', p_app_date1); - await updateFertilizerApplication(fdm, p_app_id, b_id, p_id, 200, 'injection', '2024-04-20'); + await updateFertilizerApplication(fdm, p_app_id, b_id, p_id, 200, 'injection', p_app_date2); const updatedApplication = await getFertilizerApplication(fdm, p_app_id); expect(updatedApplication?.p_app_amount).toBe(200); expect(updatedApplication?.p_app_method).toBe('injection'); - expect(updatedApplication?.p_app_date).toEqual('2024-04-20'); + expect(updatedApplication?.p_app_date).toEqual(p_app_date2); }); @@ -490,7 +495,7 @@ describe('Fertilizer Data Model', () => { p_id, 100, 'broadcasting', - '2024-03-15', + new Date('2024-03-15'), ); await removeFertilizerApplication(fdm, new_p_app_id); @@ -500,15 +505,15 @@ describe('Fertilizer Data Model', () => { }); it('should get a fertilizer application', async () => { - const p_app_id = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); + const p_app_id = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', new Date('2024-03-15')); const fertilizerApplication = await getFertilizerApplication(fdm, p_app_id); expect(fertilizerApplication).toBeDefined(); expect(fertilizerApplication?.p_app_id).toBe(p_app_id); }); it('should get fertilizer applications for a field', async () => { - await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', '2024-03-15'); - await addFertilizerApplication(fdm, b_id, p_id, 150, 'injection', '2024-04-18'); + await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', new Date('2024-03-15')); + await addFertilizerApplication(fdm, b_id, p_id, 150, 'injection', new Date('2024-04-18')); const fertilizerApplications = await getFertilizerApplications(fdm, b_id); From 423b18b411f9818cbc877c3f5f915a4df32086de Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:11:30 +0100 Subject: [PATCH 29/65] Save the applications to the db --- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 60 ++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 9d5e84dc2..0fb1f59d3 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -7,7 +7,7 @@ import { ComboboxFertilizers } from "@/components/custom/combobox-fertilizers"; // FDM import { fdm } from "../services/fdm.server"; -import { getCultivationPlan, getCultivationsFromCatalogue, getFertilizersFromCatalogue } from "@svenvw/fdm-core"; +import { getCultivationPlan, getFertilizers, addFertilizerApplication, getFertilizer } from "@svenvw/fdm-core"; // Loader export async function loader({ @@ -27,15 +27,14 @@ export async function loader({ } // Fertilizer options - const fertilizersCatalogue = await getFertilizersFromCatalogue(fdm) - const fertilizerOptions = fertilizersCatalogue.map(fertilizer => { + const fertilizers = await getFertilizers(fdm, b_id_farm) + const fertilizerOptions = fertilizers.map(fertilizer => { return { - value: fertilizer.p_id_catalogue, + value: fertilizer.p_id, label: fertilizer.p_name_nl } }) - return { b_lu_catalogue: b_lu_catalogue, b_id_farm: b_id_farm, @@ -60,17 +59,50 @@ export default function Index() { } export async function action({ - request, - }: ActionFunctionArgs) { - console.log("action") - + request, params +}: ActionFunctionArgs) { + + // Get the Id of the farm + const b_id_farm = params.b_id_farm + if (!b_id_farm) { + throw data("Farm ID is required", { status: 400, statusText: "Farm ID is required" }); + } + + // Get the cultivation + const b_lu_catalogue = params.b_lu_catalogue + if (!b_lu_catalogue) { + throw data("Cultivation catalogue ID is required", { status: 400, statusText: "Cultivation catalogue ID is required" }); + } + + // Collect form entry const formValues = await extractFormValuesFromRequest(request, FormSchema) - console.log(formValues) + const { p_id, p_app_amount, p_app_date } = formValues; + + // Get the cultivation details for this cultivation + const cultivationPlan = await getCultivationPlan(fdm, b_id_farm).catch(error => { + throw data("Failed to fetch cultivation plan", { status: 500, statusText: error.message }); + }); + + // Get the id of the fields with this cultivation + const fields = cultivationPlan.find(cultivation => cultivation.b_lu_catalogue === b_lu_catalogue).fields + + fields.map(async (field) => { + + const b_id = field.b_id + await addFertilizerApplication( + fdm, + b_id, + p_id, + p_app_amount, + null, + p_app_date + ) + + + }) - const {p_app_amount, p_app_date} = formValues; - return { ok: true, } - - } \ No newline at end of file + +} From c8c9ca69a052e8e94f3dc2610b4d055fc70d06e0 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:48:02 +0100 Subject: [PATCH 30/65] Add feedback that fertilizer application is saved --- .../custom/combobox-fertilizers.tsx | 29 +------------ fdm-app/app/components/ui/sonner.tsx | 29 +++++++++++++ fdm-app/app/root.tsx | 28 +++++++++++-- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 13 +++--- fdm-app/package.json | 3 ++ pnpm-lock.yaml | 41 +++++++++++++++++++ 6 files changed, 105 insertions(+), 38 deletions(-) create mode 100644 fdm-app/app/components/ui/sonner.tsx diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index de11eb76e..ae3f18a20 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -1,6 +1,5 @@ -import { Form, useFetcher, useNavigation } from "react-router" +import { Form } from "react-router" import { format } from "date-fns" -import { useState } from "react" import { zodResolver } from "@hookform/resolvers/zod" import { useRemixForm, RemixFormProvider } from "remix-hook-form" import { z } from "zod" @@ -10,7 +9,6 @@ import { CalendarIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Separator } from "@/components/ui/separator" import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Calendar } from "@/components/ui/calendar" import { @@ -48,7 +46,6 @@ export const FormSchema = z.object({ }) export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string, action: string }) { - const fetcher = useFetcher(); const form = useRemixForm>({ mode: "onTouched", @@ -59,30 +56,6 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st }, }) - - // async function handleClickOnSubmitAddFertilizer(e: FormEvent) { - - // e.currentTarget - // const formData = new FormData(e.currentTarget); - // formData.append("actionForm", 'addFertilizer') - // console.log(e.currentTarget) - - // await fetcher.submit(formData, { - // method: "POST", - // }) - - - // } - async function handleClickOnSubmitRemoveFertilizer() { - - const formData = new FormData(); - formData.append("actionForm", 'removeFertilizer') - - await fetcher.submit(formData, { - method: "POST", - }) - } - return (
diff --git a/fdm-app/app/components/ui/sonner.tsx b/fdm-app/app/components/ui/sonner.tsx new file mode 100644 index 000000000..1128edfce --- /dev/null +++ b/fdm-app/app/components/ui/sonner.tsx @@ -0,0 +1,29 @@ +import { useTheme } from "next-themes" +import { Toaster as Sonner } from "sonner" + +type ToasterProps = React.ComponentProps + +const Toaster = ({ ...props }: ToasterProps) => { + const { theme = "system" } = useTheme() + + return ( + + ) +} + +export { Toaster } diff --git a/fdm-app/app/root.tsx b/fdm-app/app/root.tsx index 357f7db9b..e597abbba 100644 --- a/fdm-app/app/root.tsx +++ b/fdm-app/app/root.tsx @@ -1,5 +1,9 @@ -import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; -import type { LinksFunction } from "react-router"; +import { useEffect } from "react"; +import { data, Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "react-router"; +import type { LinksFunction, LoaderFunctionArgs } from "react-router"; +import { getToast } from "remix-toast"; +import { Toaster } from "@/components/ui/sonner" +import { toast as notify } from "sonner"; import styles from "~/tailwind.css?url"; @@ -17,7 +21,24 @@ export const links: LinksFunction = () => [ }, ]; +export const loader = async ({ request }: LoaderFunctionArgs) => { + const { toast, headers } = await getToast(request); + return data({ toast }, { headers }); +} + export function Layout() { + const { toast } = useLoaderData(); + + // Hook to show the toasts + useEffect(() => { + if (toast?.type === "error") { + notify.error(toast.message); + } + if (toast?.type === "success") { + notify.success(toast.message); + } + }, [toast]); + return ( @@ -26,8 +47,9 @@ export function Layout() { - + + diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 0fb1f59d3..51da17213 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -1,9 +1,10 @@ import { useLoaderData, type LoaderFunctionArgs, data, ActionFunctionArgs } from "react-router"; -import { extractFormValuesFromRequest } from "@/lib/form"; -import { FormSchema } from "@/components/custom/combobox-fertilizers"; +import { dataWithSuccess} from "remix-toast"; // Components import { ComboboxFertilizers } from "@/components/custom/combobox-fertilizers"; +import { extractFormValuesFromRequest } from "@/lib/form"; +import { FormSchema } from "@/components/custom/combobox-fertilizers"; // FDM import { fdm } from "../services/fdm.server"; @@ -38,8 +39,8 @@ export async function loader({ return { b_lu_catalogue: b_lu_catalogue, b_id_farm: b_id_farm, - fertilizerOptions: fertilizerOptions - } + fertilizerOptions: fertilizerOptions, + }; } export default function Index() { @@ -101,8 +102,6 @@ export async function action({ }) - return { - ok: true, - } + return dataWithSuccess({ result: "Data saved successfully" }, { message: "Bemesting is toegevoegd! 🎉" }) } diff --git a/fdm-app/package.json b/fdm-app/package.json index 42f9bb807..6fabc3c51 100644 --- a/fdm-app/package.json +++ b/fdm-app/package.json @@ -37,6 +37,7 @@ "isbot": "^5.1.17", "lucide-react": "^0.468.0", "mapbox-gl": "^3.8.0", + "next-themes": "^0.4.4", "react": "^18.3.1", "react-day-picker": "8.10.1", "react-dom": "^18.3.1", @@ -45,7 +46,9 @@ "react-router": "^7.0.2", "react-router-dom": "^7.0.2", "remix-hook-form": "6.0.0", + "remix-toast": "^2.0.0", "remix-utils": "^7.7.0", + "sonner": "^1.7.1", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "wkx": "^0.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef23bcdd8..8eb44bfb3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -97,6 +97,9 @@ importers: mapbox-gl: specifier: ^3.8.0 version: 3.8.0 + next-themes: + specifier: ^0.4.4 + version: 0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -121,9 +124,15 @@ importers: remix-hook-form: specifier: 6.0.0 version: 6.0.0(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.54.0(react@18.3.1))(react-router@7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + remix-toast: + specifier: ^2.0.0 + version: 2.0.0(react-router@7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) remix-utils: specifier: ^7.7.0 version: 7.7.0(@remix-run/node@2.15.1(typescript@5.7.2))(@remix-run/react@2.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@remix-run/router@1.21.0)(react@18.3.1)(zod@3.24.1) + sonner: + specifier: ^1.7.1 + version: 1.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tailwind-merge: specifier: ^2.5.5 version: 2.5.5 @@ -6520,6 +6529,12 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + next-themes@0.4.4: + resolution: {integrity: sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==} + peerDependencies: + react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} @@ -7685,6 +7700,11 @@ packages: react-hook-form: ^7.51.0 react-router: '>=7.0.0' + remix-toast@2.0.0: + resolution: {integrity: sha512-kLIiOKjR9syUxkXrqT/OtcYQ9PuuyYIiGhjzCGgplIHIq/JEdq6ff9TcDDlpSD3VvydOsIe4U5ZCGK00FCdXmw==} + peerDependencies: + react-router: '>=7.0.0' + remix-utils@7.7.0: resolution: {integrity: sha512-J8NhP044nrNIam/xOT1L9a4RQ9FSaA2wyrUwmN8ZT+c/+CdAAf70yfaLnvMyKcV5U+8BcURQ/aVbth77sT6jGA==} engines: {node: '>=18.0.0'} @@ -7986,6 +8006,12 @@ packages: sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + sonner@1.7.1: + resolution: {integrity: sha512-b6LHBfH32SoVasRFECrdY8p8s7hXPDn3OHUFbZZbiB1ctLS9Gdh6rpX2dVrpQA0kiL5jcRzDDldwwLkSKk3+QQ==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + sort-asc@0.2.0: resolution: {integrity: sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==} engines: {node: '>=0.10.0'} @@ -16694,6 +16720,11 @@ snapshots: neo-async@2.6.2: {} + next-themes@0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + no-case@3.0.4: dependencies: lower-case: 2.0.2 @@ -17984,6 +18015,11 @@ snapshots: react-hook-form: 7.54.0(react@18.3.1) react-router: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + remix-toast@2.0.0(react-router@7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + dependencies: + react-router: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + zod: 3.24.1 + remix-utils@7.7.0(@remix-run/node@2.15.1(typescript@5.7.2))(@remix-run/react@2.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@remix-run/router@1.21.0)(react@18.3.1)(zod@3.24.1): dependencies: type-fest: 4.30.0 @@ -18318,6 +18354,11 @@ snapshots: uuid: 8.3.2 websocket-driver: 0.7.4 + sonner@1.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + sort-asc@0.2.0: {} sort-css-media-queries@2.2.0: {} From 9484ca2c3ee87c354f34f489c5ac0b22c27d68a1 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:28:06 +0100 Subject: [PATCH 31/65] Show fertilizers applied --- .../custom/combobox-fertilizers.tsx | 71 +++++++------------ ...ltivations.$b_lu_catalogue.fertilizers.tsx | 12 +++- 2 files changed, 35 insertions(+), 48 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index ae3f18a20..0857b3a7a 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -45,7 +45,7 @@ export const FormSchema = z.object({ }) }) -export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string, action: string }) { +export function ComboboxFertilizers(props: { fertilizerApplications: any, options: { value: string, label: string }[], defaultValue?: string, action: string }) { const form = useRemixForm>({ mode: "onTouched", @@ -133,8 +133,8 @@ export function ComboboxFertilizers(props: { options: { value: string, label: st )} /> -
-
+
+
-
- {/*
*/} -
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

-
-
- + {props.fertilizerApplications.map((application) => ( +
+
+

+ {application.p_name_nl} +

+ {/*

m@example.com

*/} +
+
+

+ {application.p_app_amount} ton / ha +

+
+
+

+ {format(application.p_app_date, "yyyy-MM-dd")} +

+
+
+ +
+
-
+ ))}
diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 51da17213..d0bfb65e6 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -36,10 +36,18 @@ export async function loader({ } }) + // Get the fertilizer applications + const cultivationPlan = await getCultivationPlan(fdm, b_id_farm).catch(error => { + throw data("Failed to fetch cultivation plan", { status: 500, statusText: error.message }); + }); + const fields = cultivationPlan.find(cultivation => cultivation.b_lu_catalogue === b_lu_catalogue).fields + const fertilizerApplications = fields[0].fertilizer_applications; + return { b_lu_catalogue: b_lu_catalogue, b_id_farm: b_id_farm, fertilizerOptions: fertilizerOptions, + fertilizerApplications: fertilizerApplications }; } @@ -52,6 +60,7 @@ export default function Index() { Vul de bemesting op bouwplanniveau in voor dit gewas.

@@ -88,7 +97,6 @@ export async function action({ const fields = cultivationPlan.find(cultivation => cultivation.b_lu_catalogue === b_lu_catalogue).fields fields.map(async (field) => { - const b_id = field.b_id await addFertilizerApplication( fdm, @@ -98,8 +106,6 @@ export async function action({ null, p_app_date ) - - }) return dataWithSuccess({ result: "Data saved successfully" }, { message: "Bemesting is toegevoegd! 🎉" }) From 071526e4b9c1c27014684de5932cd8873dbf65cc Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:38:24 +0100 Subject: [PATCH 32/65] Fix returning all fertilizer applications --- fdm-core/src/cultivation.test.ts | 17 +++++-- fdm-core/src/cultivation.ts | 78 +++++++++++++------------------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/fdm-core/src/cultivation.test.ts b/fdm-core/src/cultivation.test.ts index 618d758f1..eb483ce94 100644 --- a/fdm-core/src/cultivation.test.ts +++ b/fdm-core/src/cultivation.test.ts @@ -308,7 +308,8 @@ describe('Cultivation Data Model', () => { it('should get cultivation plan for a farm', async () => { - await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', new Date('2024-03-15')); + const p_app_id1 = await addFertilizerApplication(fdm, b_id, p_id, 100, 'broadcasting', new Date('2024-03-15')); + const p_app_id2 = await addFertilizerApplication(fdm, b_id, p_id, 200, 'broadcasting', new Date('2024-04-15')); const cultivationPlan = await getCultivationPlan(fdm, b_id_farm); @@ -323,15 +324,21 @@ describe('Cultivation Data Model', () => { expect(fieldInPlan).toBeDefined(); - expect(fieldInPlan?.fertilizer_applications.length).toBeGreaterThan(0); + expect(fieldInPlan?.fertilizer_applications.length).toEqual(2); - const fertilizerApp = fieldInPlan!.fertilizer_applications.find(fa => fa.p_app_id != null) + const fertilizerApp1 = fieldInPlan!.fertilizer_applications.find(fa => fa.p_app_id === p_app_id1) //Check for some key fertilizer application details (adapt as needed based on your data) - expect(fertilizerApp!.p_app_amount).toEqual(100) - expect(fertilizerApp!.p_app_method).toEqual('broadcasting') + expect(fertilizerApp1!.p_app_amount).toEqual(100) + expect(fertilizerApp1!.p_app_method).toEqual('broadcasting') + const fertilizerApp2 = fieldInPlan!.fertilizer_applications.find(fa => fa.p_app_id === p_app_id2) + + //Check for some key fertilizer application details (adapt as needed based on your data) + expect(fertilizerApp2!.p_app_amount).toEqual(200) + expect(fertilizerApp2!.p_app_method).toEqual('broadcasting') + }); diff --git a/fdm-core/src/cultivation.ts b/fdm-core/src/cultivation.ts index 5dc4e9b45..538d5759d 100644 --- a/fdm-core/src/cultivation.ts +++ b/fdm-core/src/cultivation.ts @@ -299,57 +299,43 @@ export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTy isNotNull(schema.cultivationsCatalogue.b_lu_catalogue)) ) - const cultivationPlan = cultivations.reduce((acc: cultivationPlanType[], curr) => { - const existingCultivation = acc.find(item => item.b_lu_catalogue === curr.b_lu_catalogue); - if (existingCultivation) { - const existingField = existingCultivation.fields.find(field => field.b_id === curr); - if (existingField) { - if (curr.p_app_id) { - existingField.fertilizer_applications.push({ - p_id_catalogue: curr.p_id_catalogue, - p_name_nl: curr.p_name_nl, - p_app_amount: curr.p_app_amount, - p_app_method: curr.p_app_method, - p_app_date: curr.p_app_date, - p_app_id: curr.p_app_id - }); - } - } else { - existingCultivation.fields.push({ + const cultivationPlan = cultivations.reduce((acc: cultivationPlanType[], curr) => { + let existingCultivation = acc.find(item => item.b_lu_catalogue === curr.b_lu_catalogue); + + if (!existingCultivation) { + existingCultivation = { + b_lu_catalogue: curr.b_lu_catalogue, + b_lu_name: curr.b_lu_name, + fields: [] + }; + acc.push(existingCultivation); + } + + let existingField = existingCultivation.fields.find(field => field.b_id === curr.b_id); + + if (!existingField) { + existingField = { b_lu: curr.b_lu, b_id: curr.b_id, b_name: curr.b_name, - fertilizer_applications: curr.p_app_id ? [{ - p_id_catalogue: curr.p_id_catalogue, - p_name_nl: curr.p_name_nl, - p_app_amount: curr.p_app_amount, - p_app_method: curr.p_app_method, - p_app_date: curr.p_app_date, - p_app_id: curr.p_app_id - }] : [], + fertilizer_applications: [] + }; + existingCultivation.fields.push(existingField); + } + + if (curr.p_app_id) { // Only add if it's a fertilizer application + existingField.fertilizer_applications.push({ + p_id_catalogue: curr.p_id_catalogue, + p_name_nl: curr.p_name_nl, + p_app_amount: curr.p_app_amount, + p_app_method: curr.p_app_method, + p_app_date: curr.p_app_date, + p_app_id: curr.p_app_id }); } - } else { - acc.push({ - b_lu_catalogue: curr.b_lu_catalogue, - b_lu_name: curr.b_lu_name, - fields: [{ - b_lu: curr.b_lu, - b_id: curr.b_id, - b_name: curr.b_name, - fertilizer_applications: curr.p_app_id ? [{ - p_id_catalogue: curr.p_id_catalogue, - p_name_nl: curr.p_name_nl, - p_app_amount: curr.p_app_amount, - p_app_method: curr.p_app_method, - p_app_date: curr.p_app_date, - p_app_id: curr.p_app_id - }] : [], - }], - }); - } - return acc; - }, []); + + return acc; + }, []); return cultivationPlan } catch (error) { From 296e476b95ca3175704a739ec45d74622a87ea68 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:59:22 +0100 Subject: [PATCH 33/65] Fix aligning --- fdm-app/app/components/custom/combobox-fertilizers.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 0857b3a7a..d38177225 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -154,8 +154,8 @@ export function ComboboxFertilizers(props: { fertilizerApplications: any, option {/*
Meststoffen
*/}
{props.fertilizerApplications.map((application) => ( -
-
+
+

{application.p_name_nl}

@@ -171,7 +171,7 @@ export function ComboboxFertilizers(props: { fertilizerApplications: any, option {format(application.p_app_date, "yyyy-MM-dd")}

-
+
From 7db0478ec96fc7c3377d18de3d304fc9836e4d92 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Fri, 13 Dec 2024 17:06:11 +0100 Subject: [PATCH 34/65] Reset form after submission --- fdm-app/app/components/custom/combobox-fertilizers.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index d38177225..7ff879022 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -23,6 +23,7 @@ import { Combobox } from "@/components/custom/combobox" import { cn } from "@/lib/utils" import { LoadingSpinner } from "./loadingspinner" +import { useEffect } from "react" export const FormSchema = z.object({ p_app_amount: z.coerce.number({ @@ -53,9 +54,15 @@ export function ComboboxFertilizers(props: { fertilizerApplications: any, option defaultValues: { p_app_amount: 0, // p_app_date: new Date(), - }, + } }) + useEffect(() => { + if (form.formState.isSubmitSuccessful) { + form.reset() + } + }, [form.formState]) + return (
From 6ab9f5fe841511f4e1d32e550bb0b7278dc1dc8b Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Fri, 13 Dec 2024 17:12:19 +0100 Subject: [PATCH 35/65] Improve alignment --- fdm-app/app/components/custom/combobox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdm-app/app/components/custom/combobox.tsx b/fdm-app/app/components/custom/combobox.tsx index a1f48c290..7af6f9c3e 100644 --- a/fdm-app/app/components/custom/combobox.tsx +++ b/fdm-app/app/components/custom/combobox.tsx @@ -50,7 +50,7 @@ export function Combobox({ control={form.control} name={name} render={({ field }) => ( - + {label} From 78a00746dc61beca24a24805c766d08be571c7c0 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:35:23 +0100 Subject: [PATCH 36/65] Return the p_app_id's for a cultivation --- .../custom/combobox-fertilizers.tsx | 2 +- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 52 ++++++++++++++++--- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 7ff879022..322d748f9 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -46,7 +46,7 @@ export const FormSchema = z.object({ }) }) -export function ComboboxFertilizers(props: { fertilizerApplications: any, options: { value: string, label: string }[], defaultValue?: string, action: string }) { +export function ComboboxFertilizers(props: { fertilizerApplications: any[], options: { value: string, label: string }[], defaultValue?: string, action: string }) { const form = useRemixForm>({ mode: "onTouched", diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index d0bfb65e6..0235583df 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -1,5 +1,5 @@ import { useLoaderData, type LoaderFunctionArgs, data, ActionFunctionArgs } from "react-router"; -import { dataWithSuccess} from "remix-toast"; +import { dataWithSuccess } from "remix-toast"; // Components import { ComboboxFertilizers } from "@/components/custom/combobox-fertilizers"; @@ -15,20 +15,21 @@ export async function loader({ request, params }: LoaderFunctionArgs) { - // Get the Id of the farm + // Extract farm ID from URL parameters const b_id_farm = params.b_id_farm if (!b_id_farm) { throw data("Farm ID is required", { status: 400, statusText: "Farm ID is required" }); } - // Get the cultivation + // Extract cultivation catalogue ID from URL parameters const b_lu_catalogue = params.b_lu_catalogue if (!b_lu_catalogue) { throw data("Cultivation catalogue ID is required", { status: 400, statusText: "Cultivation catalogue ID is required" }); } - // Fertilizer options + // Fetch available fertilizers for the farm const fertilizers = await getFertilizers(fdm, b_id_farm) + // Map fertilizers to options for the combobox const fertilizerOptions = fertilizers.map(fertilizer => { return { value: fertilizer.p_id, @@ -36,12 +37,49 @@ export async function loader({ } }) - // Get the fertilizer applications + // Fetch the cultivation plan for the farm const cultivationPlan = await getCultivationPlan(fdm, b_id_farm).catch(error => { throw data("Failed to fetch cultivation plan", { status: 500, statusText: error.message }); }); - const fields = cultivationPlan.find(cultivation => cultivation.b_lu_catalogue === b_lu_catalogue).fields - const fertilizerApplications = fields[0].fertilizer_applications; + + // Find the target cultivation within the cultivation plan + const targetCultivation = cultivationPlan.find(c => c.b_lu_catalogue === b_lu_catalogue); + if (!targetCultivation) { + throw data("Cultivation not found", { status: 404 }); + } + + // Combine similar fertilizer applications across all fields of the target cultivation. + const fertilizerApplications = targetCultivation.fields.reduce((accumulator, field) => { + field.fertilizer_applications.forEach(app => { + // Create a key based on application properties to identify similar applications. + const applicationKey = JSON.stringify({ + p_id_catalogue: app.p_id_catalogue, + p_app_amount: app.p_app_amount, + p_app_method: app.p_app_method, + p_app_date: app.p_app_date, + }); + + // Check if a similar application already exists in the accumulator. + const existingApplication = accumulator.find( + (existingApp) => JSON.stringify({ + p_id_catalogue: existingApp.p_id_catalogue, + p_app_amount: existingApp.p_app_amount, + p_app_method: existingApp.p_app_method, + p_app_date: existingApp.p_app_date, + }) === applicationKey + ); + + if (existingApplication) { + // If similar application exists, add the current p_app_id to its p_app_ids array. + existingApplication.p_app_ids.push(app.p_app_id); + } else { + // If it's a new application, add it to the accumulator with a new p_app_ids array. + accumulator.push({ ...app, p_app_ids: [app.p_app_id] }); + } + }); + + return accumulator; + }, []); return { b_lu_catalogue: b_lu_catalogue, From d2bb50cd714b0315838b5429e054fdd0abedfdb4 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:18:57 +0100 Subject: [PATCH 37/65] Add deletion of fertilizer applications --- .../custom/combobox-fertilizers.tsx | 14 ++- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 86 +++++++++++++------ 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx index 322d748f9..9d7fc4da6 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/combobox-fertilizers.tsx @@ -1,4 +1,4 @@ -import { Form } from "react-router" +import { Form, useFetcher } from "react-router" import { format } from "date-fns" import { zodResolver } from "@hookform/resolvers/zod" import { useRemixForm, RemixFormProvider } from "remix-hook-form" @@ -47,6 +47,7 @@ export const FormSchema = z.object({ }) export function ComboboxFertilizers(props: { fertilizerApplications: any[], options: { value: string, label: string }[], defaultValue?: string, action: string }) { + const fetcher = useFetcher(); const form = useRemixForm>({ mode: "onTouched", @@ -63,6 +64,13 @@ export function ComboboxFertilizers(props: { fertilizerApplications: any[], opti } }, [form.formState]) + const handleDelete = (p_app_ids: string[]) => { + fetcher.submit( + { p_app_ids }, + { method: "delete", action: props.action } + ); + }; + return (
@@ -179,7 +187,9 @@ export function ComboboxFertilizers(props: { fertilizerApplications: any[], opti

- +
diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 0235583df..f46bf7c20 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -1,5 +1,5 @@ import { useLoaderData, type LoaderFunctionArgs, data, ActionFunctionArgs } from "react-router"; -import { dataWithSuccess } from "remix-toast"; +import { dataWithError, dataWithSuccess } from "remix-toast"; // Components import { ComboboxFertilizers } from "@/components/custom/combobox-fertilizers"; @@ -8,7 +8,7 @@ import { FormSchema } from "@/components/custom/combobox-fertilizers"; // FDM import { fdm } from "../services/fdm.server"; -import { getCultivationPlan, getFertilizers, addFertilizerApplication, getFertilizer } from "@svenvw/fdm-core"; +import { getCultivationPlan, getFertilizers, addFertilizerApplication, getFertilizer, removeFertilizerApplication } from "@svenvw/fdm-core"; // Loader export async function loader({ @@ -21,7 +21,7 @@ export async function loader({ throw data("Farm ID is required", { status: 400, statusText: "Farm ID is required" }); } - // Extract cultivation catalogue ID from URL parameters + // Extract cultivation catalogue ID from URL parameters const b_lu_catalogue = params.b_lu_catalogue if (!b_lu_catalogue) { throw data("Cultivation catalogue ID is required", { status: 400, statusText: "Cultivation catalogue ID is required" }); @@ -37,7 +37,7 @@ export async function loader({ } }) - // Fetch the cultivation plan for the farm + // Fetch the cultivation plan for the farm const cultivationPlan = await getCultivationPlan(fdm, b_id_farm).catch(error => { throw data("Failed to fetch cultivation plan", { status: 500, statusText: error.message }); }); @@ -122,30 +122,62 @@ export async function action({ throw data("Cultivation catalogue ID is required", { status: 400, statusText: "Cultivation catalogue ID is required" }); } - // Collect form entry - const formValues = await extractFormValuesFromRequest(request, FormSchema) - const { p_id, p_app_amount, p_app_date } = formValues; + if (request.method == 'POST') { + // Collect form entry + const formValues = await extractFormValuesFromRequest(request, FormSchema) + const { p_id, p_app_amount, p_app_date } = formValues; - // Get the cultivation details for this cultivation - const cultivationPlan = await getCultivationPlan(fdm, b_id_farm).catch(error => { - throw data("Failed to fetch cultivation plan", { status: 500, statusText: error.message }); - }); + // Get the cultivation details for this cultivation + const cultivationPlan = await getCultivationPlan(fdm, b_id_farm).catch(error => { + throw data("Failed to fetch cultivation plan", { status: 500, statusText: error.message }); + }); - // Get the id of the fields with this cultivation - const fields = cultivationPlan.find(cultivation => cultivation.b_lu_catalogue === b_lu_catalogue).fields - - fields.map(async (field) => { - const b_id = field.b_id - await addFertilizerApplication( - fdm, - b_id, - p_id, - p_app_amount, - null, - p_app_date - ) - }) + // Get the id of the fields with this cultivation + const fields = cultivationPlan.find(cultivation => cultivation.b_lu_catalogue === b_lu_catalogue).fields - return dataWithSuccess({ result: "Data saved successfully" }, { message: "Bemesting is toegevoegd! 🎉" }) + fields.map(async (field) => { + const b_id = field.b_id + await addFertilizerApplication( + fdm, + b_id, + p_id, + p_app_amount, + null, + p_app_date + ) + }) -} + return dataWithSuccess({ result: "Data saved successfully" }, { message: "Bemesting is toegevoegd! 🎉" }) + + } else if (request.method == 'DELETE') { + + const formData = await request.formData(); + const p_app_ids = formData.get("p_app_ids")?.toString(); + + if (!p_app_ids) { + return dataWithError( + 'Missing values for p_app_ids', + "Oops! Something went wrong. Please try again later." + ); + + } + + try { + + p_app_ids.split(',').map(async (p_app_id: string) => { + await removeFertilizerApplication(fdm, p_app_id); + }) + + return dataWithSuccess({}, { message: "Bemesting is verwijderd" }); + } catch (error) { + // Handle errors appropriately. Log the error for debugging purposes. + console.error("Error deleting fertilizer application:", error); + return dataWithError(null, "Oops! Something went wrong. Please try again later."); + } + } + + // Handle other methods. This returns an error response for methods other than POST or DELETE, which may or may not be what's desired. + console.error(`${request.method} is not supported`) + return dataWithError(null, "Oops! Something went wrong. Please try again later."); + +} \ No newline at end of file From eb2c0648734a81b3b558665adbfe179bd4b283c2 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:27:12 +0100 Subject: [PATCH 38/65] Update the blocks for crop and catch crop --- .../components/blocks/cultivation-plan.tsx | 72 ------------------- ...cultivations.$b_lu_catalogue.covercrop.tsx | 11 ++- ...farm.cultivations.$b_lu_catalogue.crop.tsx | 67 ++++++++++++++++- 3 files changed, 76 insertions(+), 74 deletions(-) delete mode 100644 fdm-app/app/components/blocks/cultivation-plan.tsx diff --git a/fdm-app/app/components/blocks/cultivation-plan.tsx b/fdm-app/app/components/blocks/cultivation-plan.tsx deleted file mode 100644 index 8bac2a670..000000000 --- a/fdm-app/app/components/blocks/cultivation-plan.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { useState } from "react"; -import { Form, useLocation, useNavigation } from "react-router"; - -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label"; -import { Input } from "@/components/ui/input"; -import { buttonVariants } from "@/components/ui/button" -import { Calendar } from "@/components/ui/calendar" -// import { nl } from "react-day-picker/locale" // Could not be found somehow - - - -export default function Cultivation(props: { action: string | undefined; }) { - const navigation = useNavigation(); - - // Get sowing and harvesting dates - const [dateSowing, setDateSowing] = useState(new Date('2024-03-01')) - const [dateHarvesting, setDateHarvesting] = useState(new Date('2024-10-01')) - - - return ( -
-
-

- Werk de opbrengst, stikstofgehalte en zaai- en oogstdatum bij voor dit gewas. -

-
-
-
-
-
-
- - -
-
- - -
-
-
- - -
-
- - -
-
-
-
-
- ) -} \ No newline at end of file diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.covercrop.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.covercrop.tsx index cb0f1c291..6ea513492 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.covercrop.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.covercrop.tsx @@ -1 +1,10 @@ -export default function Index() {} \ No newline at end of file +export default function Index() { + + return (
+
+

+ Vanggewas wordt binnenkort toegevoegd +

+
+
) +} \ No newline at end of file diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.crop.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.crop.tsx index 0afe78418..b2daf3bef 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.crop.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.crop.tsx @@ -1 +1,66 @@ -export default function Index() {} +import { useState } from "react"; +import { Form, useNavigation } from "react-router"; + +import { Label } from "@/components/ui/label"; +import { Input } from "@/components/ui/input"; +import { Calendar } from "@/components/ui/calendar" + +export default function Index(props: { action: string | undefined; }) { + const navigation = useNavigation(); + + // Get sowing and harvesting dates + const [dateSowing, setDateSowing] = useState(new Date('2024-03-01')) + const [dateHarvesting, setDateHarvesting] = useState(new Date('2024-10-01')) + + return ( +
+
+

+ Werk de opbrengst, stikstofgehalte en zaai- en oogstdatum bij voor dit gewas. +

+
+
+
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+
+ ) +} From 2f011d6a60795751f6946aa1f725eeb96e46c4ee Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:27:26 +0100 Subject: [PATCH 39/65] Rename the FertilizerApplicationsForm --- ...combobox-fertilizers.tsx => fertilizer-applications.tsx} | 2 +- ....$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename fdm-app/app/components/custom/{combobox-fertilizers.tsx => fertilizer-applications.tsx} (98%) diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/fertilizer-applications.tsx similarity index 98% rename from fdm-app/app/components/custom/combobox-fertilizers.tsx rename to fdm-app/app/components/custom/fertilizer-applications.tsx index 9d7fc4da6..ffcf829ca 100644 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ b/fdm-app/app/components/custom/fertilizer-applications.tsx @@ -46,7 +46,7 @@ export const FormSchema = z.object({ }) }) -export function ComboboxFertilizers(props: { fertilizerApplications: any[], options: { value: string, label: string }[], defaultValue?: string, action: string }) { +export function FertilizerApplicationsForm(props: { fertilizerApplications: any[], options: { value: string, label: string }[], defaultValue?: string, action: string }) { const fetcher = useFetcher(); const form = useRemixForm>({ diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index f46bf7c20..0983bf1c6 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -2,9 +2,9 @@ import { useLoaderData, type LoaderFunctionArgs, data, ActionFunctionArgs } from import { dataWithError, dataWithSuccess } from "remix-toast"; // Components -import { ComboboxFertilizers } from "@/components/custom/combobox-fertilizers"; +import { FertilizerApplicationsForm } from "@/components/custom/fertilizer-applications"; import { extractFormValuesFromRequest } from "@/lib/form"; -import { FormSchema } from "@/components/custom/combobox-fertilizers"; +import { FormSchema } from "@/components/custom/fertilizer-applications"; // FDM import { fdm } from "../services/fdm.server"; @@ -97,7 +97,7 @@ export default function Index() {

Vul de bemesting op bouwplanniveau in voor dit gewas.

- Date: Mon, 16 Dec 2024 11:30:14 +0100 Subject: [PATCH 40/65] Add changeset --- .changeset/brown-frogs-explode.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/brown-frogs-explode.md diff --git a/.changeset/brown-frogs-explode.md b/.changeset/brown-frogs-explode.md new file mode 100644 index 000000000..c1d779bf0 --- /dev/null +++ b/.changeset/brown-frogs-explode.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-app": minor +--- + +Add `FertilizerApplicationsForm` to list, add and delete fertilizer applications From 7fa5bbffb09b9f7f4bb0398d85a5dfce944dca6a Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:32:51 +0100 Subject: [PATCH 41/65] Combine into single db migration --- ...tant_brood.sql => 0001_quiet_mysterio.sql} | 4 +- .../db/migrations/0002_famous_skullbuster.sql | 2 - .../src/db/migrations/meta/0001_snapshot.json | 6 +- .../src/db/migrations/meta/0002_snapshot.json | 1326 ----------------- fdm-core/src/db/migrations/meta/_journal.json | 11 +- 5 files changed, 7 insertions(+), 1342 deletions(-) rename fdm-core/src/db/migrations/{0001_hesitant_brood.sql => 0001_quiet_mysterio.sql} (99%) delete mode 100644 fdm-core/src/db/migrations/0002_famous_skullbuster.sql delete mode 100644 fdm-core/src/db/migrations/meta/0002_snapshot.json diff --git a/fdm-core/src/db/migrations/0001_hesitant_brood.sql b/fdm-core/src/db/migrations/0001_quiet_mysterio.sql similarity index 99% rename from fdm-core/src/db/migrations/0001_hesitant_brood.sql rename to fdm-core/src/db/migrations/0001_quiet_mysterio.sql index a33af4c68..925ea3938 100644 --- a/fdm-core/src/db/migrations/0001_hesitant_brood.sql +++ b/fdm-core/src/db/migrations/0001_quiet_mysterio.sql @@ -42,7 +42,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_aquiring" ( "b_id_farm" text NOT NULL, "p_id" text NOT NULL, "p_acquiring_amount" numeric, - "p_acquiring_date" date, + "p_acquiring_date" timestamp with time zone, "created" timestamp with time zone DEFAULT now() NOT NULL, "updated" timestamp with time zone ); @@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS "fdm-dev"."fertilizer_applying" ( "p_id" text NOT NULL, "p_app_amount" numeric, "p_app_method" "fdm-dev"."p_app_method", - "p_app_date" date, + "p_app_date" timestamp with time zone, "created" timestamp with time zone DEFAULT now() NOT NULL, "updated" timestamp with time zone ); diff --git a/fdm-core/src/db/migrations/0002_famous_skullbuster.sql b/fdm-core/src/db/migrations/0002_famous_skullbuster.sql deleted file mode 100644 index 8832b2e8f..000000000 --- a/fdm-core/src/db/migrations/0002_famous_skullbuster.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "fdm-dev"."fertilizer_aquiring" ALTER COLUMN "p_acquiring_date" SET DATA TYPE timestamp with time zone;--> statement-breakpoint -ALTER TABLE "fdm-dev"."fertilizer_applying" ALTER COLUMN "p_app_date" SET DATA TYPE timestamp with time zone; \ No newline at end of file diff --git a/fdm-core/src/db/migrations/meta/0001_snapshot.json b/fdm-core/src/db/migrations/meta/0001_snapshot.json index 9f446ab75..3b538b3ea 100644 --- a/fdm-core/src/db/migrations/meta/0001_snapshot.json +++ b/fdm-core/src/db/migrations/meta/0001_snapshot.json @@ -1,5 +1,5 @@ { - "id": "cba31a98-d13f-4d32-a439-66560f9ab977", + "id": "7193c998-34fa-4ea4-bdf9-ff503d3d7825", "prevId": "a835be94-9cd8-4b1f-88c0-749e8bd36b22", "version": "7", "dialect": "postgresql", @@ -309,7 +309,7 @@ }, "p_acquiring_date": { "name": "p_acquiring_date", - "type": "date", + "type": "timestamp with time zone", "primaryKey": false, "notNull": false }, @@ -399,7 +399,7 @@ }, "p_app_date": { "name": "p_app_date", - "type": "date", + "type": "timestamp with time zone", "primaryKey": false, "notNull": false }, diff --git a/fdm-core/src/db/migrations/meta/0002_snapshot.json b/fdm-core/src/db/migrations/meta/0002_snapshot.json deleted file mode 100644 index 6d636947b..000000000 --- a/fdm-core/src/db/migrations/meta/0002_snapshot.json +++ /dev/null @@ -1,1326 +0,0 @@ -{ - "id": "00b7ec3b-0e71-43e2-a165-49754ca6a2e8", - "prevId": "cba31a98-d13f-4d32-a439-66560f9ab977", - "version": "7", - "dialect": "postgresql", - "tables": { - "fdm-dev.cultivations": { - "name": "cultivations", - "schema": "fdm-dev", - "columns": { - "b_lu": { - "name": "b_lu", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "b_lu_catalogue": { - "name": "b_lu_catalogue", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "b_lu_idx": { - "name": "b_lu_idx", - "columns": [ - { - "expression": "b_lu", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "cultivations_b_lu_catalogue_cultivations_catalogue_b_lu_catalogue_fk": { - "name": "cultivations_b_lu_catalogue_cultivations_catalogue_b_lu_catalogue_fk", - "tableFrom": "cultivations", - "tableTo": "cultivations_catalogue", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_lu_catalogue" - ], - "columnsTo": [ - "b_lu_catalogue" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.cultivations_catalogue": { - "name": "cultivations_catalogue", - "schema": "fdm-dev", - "columns": { - "b_lu_catalogue": { - "name": "b_lu_catalogue", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "b_lu_source": { - "name": "b_lu_source", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "b_lu_name": { - "name": "b_lu_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "b_lu_name_en": { - "name": "b_lu_name_en", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "b_lu_hcat3": { - "name": "b_lu_hcat3", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "b_lu_hcat3_name": { - "name": "b_lu_hcat3_name", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "b_lu_catalogue_idx": { - "name": "b_lu_catalogue_idx", - "columns": [ - { - "expression": "b_lu_catalogue", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.farm_managing": { - "name": "farm_managing", - "schema": "fdm-dev", - "columns": { - "b_id": { - "name": "b_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "b_id_farm": { - "name": "b_id_farm", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "b_manage_start": { - "name": "b_manage_start", - "type": "date", - "primaryKey": false, - "notNull": false - }, - "b_manage_end": { - "name": "b_manage_end", - "type": "date", - "primaryKey": false, - "notNull": false - }, - "b_manage_type": { - "name": "b_manage_type", - "type": "b_manage_type", - "typeSchema": "fdm-dev", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "farm_managing_b_id_fields_b_id_fk": { - "name": "farm_managing_b_id_fields_b_id_fk", - "tableFrom": "farm_managing", - "tableTo": "fields", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_id" - ], - "columnsTo": [ - "b_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "farm_managing_b_id_farm_farms_b_id_farm_fk": { - "name": "farm_managing_b_id_farm_farms_b_id_farm_fk", - "tableFrom": "farm_managing", - "tableTo": "farms", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_id_farm" - ], - "columnsTo": [ - "b_id_farm" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "farm_managing_b_id_b_id_farm_pk": { - "name": "farm_managing_b_id_b_id_farm_pk", - "columns": [ - "b_id", - "b_id_farm" - ] - } - }, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.farms": { - "name": "farms", - "schema": "fdm-dev", - "columns": { - "b_id_farm": { - "name": "b_id_farm", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "b_name_farm": { - "name": "b_name_farm", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "b_sector": { - "name": "b_sector", - "type": "b_sector", - "typeSchema": "fdm-dev", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "b_id_farm_idx": { - "name": "b_id_farm_idx", - "columns": [ - { - "expression": "b_id_farm", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.fertilizer_aquiring": { - "name": "fertilizer_aquiring", - "schema": "fdm-dev", - "columns": { - "b_id_farm": { - "name": "b_id_farm", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_id": { - "name": "p_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_acquiring_amount": { - "name": "p_acquiring_amount", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_acquiring_date": { - "name": "p_acquiring_date", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "fertilizer_aquiring_b_id_farm_farms_b_id_farm_fk": { - "name": "fertilizer_aquiring_b_id_farm_farms_b_id_farm_fk", - "tableFrom": "fertilizer_aquiring", - "tableTo": "farms", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_id_farm" - ], - "columnsTo": [ - "b_id_farm" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "fertilizer_aquiring_p_id_fertilizers_p_id_fk": { - "name": "fertilizer_aquiring_p_id_fertilizers_p_id_fk", - "tableFrom": "fertilizer_aquiring", - "tableTo": "fertilizers", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "p_id" - ], - "columnsTo": [ - "p_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.fertilizer_applying": { - "name": "fertilizer_applying", - "schema": "fdm-dev", - "columns": { - "p_app_id": { - "name": "p_app_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "b_id": { - "name": "b_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_id": { - "name": "p_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_app_amount": { - "name": "p_app_amount", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_app_method": { - "name": "p_app_method", - "type": "p_app_method", - "typeSchema": "fdm-dev", - "primaryKey": false, - "notNull": false - }, - "p_app_date": { - "name": "p_app_date", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "p_app_idx": { - "name": "p_app_idx", - "columns": [ - { - "expression": "p_app_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "fertilizer_applying_b_id_fields_b_id_fk": { - "name": "fertilizer_applying_b_id_fields_b_id_fk", - "tableFrom": "fertilizer_applying", - "tableTo": "fields", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_id" - ], - "columnsTo": [ - "b_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "fertilizer_applying_p_id_fertilizers_p_id_fk": { - "name": "fertilizer_applying_p_id_fertilizers_p_id_fk", - "tableFrom": "fertilizer_applying", - "tableTo": "fertilizers", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "p_id" - ], - "columnsTo": [ - "p_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.fertilizer_picking": { - "name": "fertilizer_picking", - "schema": "fdm-dev", - "columns": { - "p_id": { - "name": "p_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_id_catalogue": { - "name": "p_id_catalogue", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_picking_date": { - "name": "p_picking_date", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "fertilizer_picking_p_id_fertilizers_p_id_fk": { - "name": "fertilizer_picking_p_id_fertilizers_p_id_fk", - "tableFrom": "fertilizer_picking", - "tableTo": "fertilizers", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "p_id" - ], - "columnsTo": [ - "p_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "fertilizer_picking_p_id_catalogue_fertilizers_catalogue_p_id_catalogue_fk": { - "name": "fertilizer_picking_p_id_catalogue_fertilizers_catalogue_p_id_catalogue_fk", - "tableFrom": "fertilizer_picking", - "tableTo": "fertilizers_catalogue", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "p_id_catalogue" - ], - "columnsTo": [ - "p_id_catalogue" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.fertilizers": { - "name": "fertilizers", - "schema": "fdm-dev", - "columns": { - "p_id": { - "name": "p_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "p_id_idx": { - "name": "p_id_idx", - "columns": [ - { - "expression": "p_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.fertilizers_catalogue": { - "name": "fertilizers_catalogue", - "schema": "fdm-dev", - "columns": { - "p_id_catalogue": { - "name": "p_id_catalogue", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "p_source": { - "name": "p_source", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "p_name_nl": { - "name": "p_name_nl", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "p_name_en": { - "name": "p_name_en", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "p_description": { - "name": "p_description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "p_dm": { - "name": "p_dm", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_density": { - "name": "p_density", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_om": { - "name": "p_om", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_a": { - "name": "p_a", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_hc": { - "name": "p_hc", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_eom": { - "name": "p_eom", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_eoc": { - "name": "p_eoc", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_c_rt": { - "name": "p_c_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_c_of": { - "name": "p_c_of", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_c_if": { - "name": "p_c_if", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_c_fr": { - "name": "p_c_fr", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_cn_of": { - "name": "p_cn_of", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_n_rt": { - "name": "p_n_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_n_if": { - "name": "p_n_if", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_n_of": { - "name": "p_n_of", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_n_wc": { - "name": "p_n_wc", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_p_rt": { - "name": "p_p_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_k_rt": { - "name": "p_k_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_mg_rt": { - "name": "p_mg_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_ca_rt": { - "name": "p_ca_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_ne": { - "name": "p_ne", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_s_rt": { - "name": "p_s_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_s_wc": { - "name": "p_s_wc", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_cu_rt": { - "name": "p_cu_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_zn_rt": { - "name": "p_zn_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_na_rt": { - "name": "p_na_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_si_rt": { - "name": "p_si_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_b_rt": { - "name": "p_b_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_mn_rt": { - "name": "p_mn_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_ni_rt": { - "name": "p_ni_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_fe_rt": { - "name": "p_fe_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_mo_rt": { - "name": "p_mo_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_co_rt": { - "name": "p_co_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_as_rt": { - "name": "p_as_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_cd_rt": { - "name": "p_cd_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_cr_rt": { - "name": "p_cr_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_cr_vi": { - "name": "p_cr_vi", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_pb_rt": { - "name": "p_pb_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_hg_rt": { - "name": "p_hg_rt", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_cl_cr": { - "name": "p_cl_cr", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "p_type_manure": { - "name": "p_type_manure", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "p_type_mineral": { - "name": "p_type_mineral", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "p_type_compost": { - "name": "p_type_compost", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "p_id_catalogue_idx": { - "name": "p_id_catalogue_idx", - "columns": [ - { - "expression": "p_id_catalogue", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.field_sowing": { - "name": "field_sowing", - "schema": "fdm-dev", - "columns": { - "b_id": { - "name": "b_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "b_lu": { - "name": "b_lu", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "b_sowing_date": { - "name": "b_sowing_date", - "type": "date", - "primaryKey": false, - "notNull": false - }, - "b_sowing_amount": { - "name": "b_sowing_amount", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "b_sowing_method": { - "name": "b_sowing_method", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "field_sowing_b_id_fields_b_id_fk": { - "name": "field_sowing_b_id_fields_b_id_fk", - "tableFrom": "field_sowing", - "tableTo": "fields", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_id" - ], - "columnsTo": [ - "b_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "field_sowing_b_lu_cultivations_b_lu_fk": { - "name": "field_sowing_b_lu_cultivations_b_lu_fk", - "tableFrom": "field_sowing", - "tableTo": "cultivations", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_lu" - ], - "columnsTo": [ - "b_lu" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "field_sowing_b_id_b_lu_pk": { - "name": "field_sowing_b_id_b_lu_pk", - "columns": [ - "b_id", - "b_lu" - ] - } - }, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.fields": { - "name": "fields", - "schema": "fdm-dev", - "columns": { - "b_id": { - "name": "b_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "b_name": { - "name": "b_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "b_geometry": { - "name": "b_geometry", - "type": "geometry(polygon)", - "primaryKey": false, - "notNull": false - }, - "b_id_source": { - "name": "b_id_source", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "b_id_idx": { - "name": "b_id_idx", - "columns": [ - { - "expression": "b_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "b_geom_idx": { - "name": "b_geom_idx", - "columns": [ - { - "expression": "b_geometry", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gist", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.grants": { - "name": "grants", - "schema": "fdm-dev", - "columns": { - "b_farm_id": { - "name": "b_farm_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "destroyed": { - "name": "destroyed", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "grants_b_farm_id_farms_b_id_farm_fk": { - "name": "grants_b_farm_id_farms_b_id_farm_fk", - "tableFrom": "grants", - "tableTo": "farms", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "b_farm_id" - ], - "columnsTo": [ - "b_id_farm" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "grants_user_id_users_user_id_fk": { - "name": "grants_user_id_users_user_id_fk", - "tableFrom": "grants", - "tableTo": "users", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "user_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.session": { - "name": "session", - "schema": "fdm-dev", - "columns": { - "session_id": { - "name": "session_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "session_id_idx": { - "name": "session_id_idx", - "columns": [ - { - "expression": "session_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "session_user_id_users_user_id_fk": { - "name": "session_user_id_users_user_id_fk", - "tableFrom": "session", - "tableTo": "users", - "schemaTo": "fdm-dev", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "user_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "fdm-dev.users": { - "name": "users", - "schema": "fdm-dev", - "columns": { - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "firstname": { - "name": "firstname", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "surname": { - "name": "surname", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created": { - "name": "created", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated": { - "name": "updated", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "user_id_idx": { - "name": "user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - } - }, - "enums": { - "fdm-dev.p_app_method": { - "name": "p_app_method", - "schema": "fdm-dev", - "values": [ - "slotted coulter", - "incorporation", - "injection", - "spraying", - "broadcasting", - "spoke wheel", - "pocket placement" - ] - }, - "fdm-dev.b_manage_type": { - "name": "b_manage_type", - "schema": "fdm-dev", - "values": [ - "owner", - "lease" - ] - }, - "fdm-dev.b_sector": { - "name": "b_sector", - "schema": "fdm-dev", - "values": [ - "diary", - "arable", - "tree_nursery", - "bulbs" - ] - } - }, - "schemas": { - "fdm-dev": "fdm-dev" - }, - "sequences": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/fdm-core/src/db/migrations/meta/_journal.json b/fdm-core/src/db/migrations/meta/_journal.json index 3baf1a98b..31bd61caf 100644 --- a/fdm-core/src/db/migrations/meta/_journal.json +++ b/fdm-core/src/db/migrations/meta/_journal.json @@ -12,15 +12,8 @@ { "idx": 1, "version": "7", - "when": 1733407330727, - "tag": "0001_hesitant_brood", - "breakpoints": true - }, - { - "idx": 2, - "version": "7", - "when": 1734018887811, - "tag": "0002_famous_skullbuster", + "when": 1734345091202, + "tag": "0001_quiet_mysterio", "breakpoints": true } ] From b1981e2592c87100d558bbbee6d887325c4e6b9c Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:35:39 +0100 Subject: [PATCH 42/65] Small fixes --- fdm-core/src/cultivation.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fdm-core/src/cultivation.ts b/fdm-core/src/cultivation.ts index 538d5759d..617936066 100644 --- a/fdm-core/src/cultivation.ts +++ b/fdm-core/src/cultivation.ts @@ -4,7 +4,6 @@ import { nanoid } from 'nanoid' import * as schema from './db/schema' import { type FdmType } from './fdm' import { cultivationPlanType, getCultivationType } from './cultivation.d' -import { b } from 'vitest/dist/chunks/suite.BMWOKiTe.js' /** * Retrieves cultivations available in the catalogue. @@ -42,7 +41,7 @@ export async function addCultivationToCatalogue( b_lu_hcat3_name: schema.cultivationsCatalogueTypeInsert['b_lu_hcat3_name'] } ): Promise { - await fdm.transaction(async (tx) => { + await fdm.transaction(async (tx: FdmType) => { // Check for existing cultivation const existing = await tx .select() @@ -148,7 +147,7 @@ export async function addCultivation( }) } catch (error) { - throw new Error(`addCultivation failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error }) + throw new Error(`addCultivation failed: ${error instanceof Error ? error.message : String(error)}`) } }) @@ -299,7 +298,7 @@ export async function getCultivationPlan(fdm: FdmType, b_id_farm: schema.farmsTy isNotNull(schema.cultivationsCatalogue.b_lu_catalogue)) ) - const cultivationPlan = cultivations.reduce((acc: cultivationPlanType[], curr) => { + const cultivationPlan = cultivations.reduce((acc: cultivationPlanType[], curr: any) => { let existingCultivation = acc.find(item => item.b_lu_catalogue === curr.b_lu_catalogue); if (!existingCultivation) { From ac824d0d3e08d8245be456f1816aa5f103a88dd5 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:38:44 +0100 Subject: [PATCH 43/65] Bump version numbers and update changelog --- .changeset/brown-frogs-explode.md | 5 ----- .changeset/empty-insects-look.md | 5 ----- .changeset/gorgeous-beans-help.md | 5 ----- .changeset/lovely-buses-marry.md | 5 ----- .changeset/ninety-dots-compete.md | 5 ----- .changeset/proud-files-film.md | 5 ----- .changeset/six-plants-draw.md | 5 ----- .changeset/six-tomatoes-exist.md | 5 ----- .changeset/sweet-spoons-try.md | 5 ----- .changeset/tough-boxes-clean.md | 5 ----- .changeset/tricky-spiders-accept.md | 5 ----- fdm-app/CHANGELOG.md | 21 +++++++++++++++++++++ fdm-app/package.json | 6 +++--- fdm-core/CHANGELOG.md | 17 +++++++++++++++++ fdm-core/package.json | 2 +- fdm-data/CHANGELOG.md | 15 +++++++++++++++ fdm-data/package.json | 4 ++-- 17 files changed, 59 insertions(+), 61 deletions(-) delete mode 100644 .changeset/brown-frogs-explode.md delete mode 100644 .changeset/empty-insects-look.md delete mode 100644 .changeset/gorgeous-beans-help.md delete mode 100644 .changeset/lovely-buses-marry.md delete mode 100644 .changeset/ninety-dots-compete.md delete mode 100644 .changeset/proud-files-film.md delete mode 100644 .changeset/six-plants-draw.md delete mode 100644 .changeset/six-tomatoes-exist.md delete mode 100644 .changeset/sweet-spoons-try.md delete mode 100644 .changeset/tough-boxes-clean.md delete mode 100644 .changeset/tricky-spiders-accept.md diff --git a/.changeset/brown-frogs-explode.md b/.changeset/brown-frogs-explode.md deleted file mode 100644 index c1d779bf0..000000000 --- a/.changeset/brown-frogs-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-app": minor ---- - -Add `FertilizerApplicationsForm` to list, add and delete fertilizer applications diff --git a/.changeset/empty-insects-look.md b/.changeset/empty-insects-look.md deleted file mode 100644 index c1dcb611b..000000000 --- a/.changeset/empty-insects-look.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Rename `p_amount` at `fertilizer_acquiring` to `p_acquiring_amount` diff --git a/.changeset/gorgeous-beans-help.md b/.changeset/gorgeous-beans-help.md deleted file mode 100644 index 49c9e50c1..000000000 --- a/.changeset/gorgeous-beans-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Rename `p_date_acquiring` to `p_acquiring_date` anc convert type from timestamp to date diff --git a/.changeset/lovely-buses-marry.md b/.changeset/lovely-buses-marry.md deleted file mode 100644 index 471b409f8..000000000 --- a/.changeset/lovely-buses-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": patch ---- - -Fix by adding `b_name` to output type of `getCultivationPlan` diff --git a/.changeset/ninety-dots-compete.md b/.changeset/ninety-dots-compete.md deleted file mode 100644 index 788d32b90..000000000 --- a/.changeset/ninety-dots-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Export `getFertilizer` and `getFertilizers` diff --git a/.changeset/proud-files-film.md b/.changeset/proud-files-film.md deleted file mode 100644 index ca71f38a7..000000000 --- a/.changeset/proud-files-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Add functions `addFertilizerApplication`, `updateFertilizerApplication`, `removeFertilizerApplication`, `getFertilizerApplication` and `getFertilizerApplications` diff --git a/.changeset/six-plants-draw.md b/.changeset/six-plants-draw.md deleted file mode 100644 index bc7fa8ee9..000000000 --- a/.changeset/six-plants-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Alter `p_acquiring_date` and `p_picking_date` from date to timestamptz diff --git a/.changeset/six-tomatoes-exist.md b/.changeset/six-tomatoes-exist.md deleted file mode 100644 index 20b642009..000000000 --- a/.changeset/six-tomatoes-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-app": minor ---- - -Remove selection of fertilizers for acquiring but select all fertilizers diff --git a/.changeset/sweet-spoons-try.md b/.changeset/sweet-spoons-try.md deleted file mode 100644 index 83f527465..000000000 --- a/.changeset/sweet-spoons-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Add to output of `getCultivationPlan` the `fertilizer_applications` diff --git a/.changeset/tough-boxes-clean.md b/.changeset/tough-boxes-clean.md deleted file mode 100644 index beb0e0c32..000000000 --- a/.changeset/tough-boxes-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -`getFertilizers` returns the details of the fertilizers similiar as `getFertilizer` diff --git a/.changeset/tricky-spiders-accept.md b/.changeset/tricky-spiders-accept.md deleted file mode 100644 index 483856d0a..000000000 --- a/.changeset/tricky-spiders-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@svenvw/fdm-core": minor ---- - -Add `fertilizer_application` table diff --git a/fdm-app/CHANGELOG.md b/fdm-app/CHANGELOG.md index 96eacc5c4..0ff0b04be 100644 --- a/fdm-app/CHANGELOG.md +++ b/fdm-app/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog fdm-app +## 0.4.0 + +### Minor Changes + +- bee0e62: Add `FertilizerApplicationsForm` to list, add and delete fertilizer applications +- 4112897: Remove selection of fertilizers for acquiring but select all fertilizers + +### Patch Changes + +- Updated dependencies [7af3fda] +- Updated dependencies [bc4e75f] +- Updated dependencies [a948c61] +- Updated dependencies [efa423d] +- Updated dependencies [b0c001e] +- Updated dependencies [6ef3d44] +- Updated dependencies [61da12f] +- Updated dependencies [5be0abc] +- Updated dependencies [4189f5d] + - @svenvw/fdm-core@0.7.0 + - @svenvw/fdm-data@1.0.0 + ## 0.3.1 ### Patch Changes diff --git a/fdm-app/package.json b/fdm-app/package.json index 6fabc3c51..afd7d6570 100644 --- a/fdm-app/package.json +++ b/fdm-app/package.json @@ -1,6 +1,6 @@ { "name": "@svenvw/fdm-app", - "version": "0.3.1", + "version": "0.4.0", "private": true, "sideEffects": false, "type": "module", @@ -77,8 +77,8 @@ "vite-tsconfig-paths": "^4.3.2" }, "peerDependencies": { - "@svenvw/fdm-core": "workspace:>=0.6.1", - "@svenvw/fdm-data": "workspace:>=0.4.0" + "@svenvw/fdm-core": "workspace:>=0.7.0", + "@svenvw/fdm-data": "workspace:>=0.5.0" }, "engines": { "node": ">=20.0.0" diff --git a/fdm-core/CHANGELOG.md b/fdm-core/CHANGELOG.md index 0e8ff5d5c..1ce798aad 100644 --- a/fdm-core/CHANGELOG.md +++ b/fdm-core/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog fdm-core +## 0.7.0 + +### Minor Changes + +- 7af3fda: Rename `p_amount` at `fertilizer_acquiring` to `p_acquiring_amount` +- bc4e75f: Rename `p_date_acquiring` to `p_acquiring_date` anc convert type from timestamp to date +- efa423d: Export `getFertilizer` and `getFertilizers` +- b0c001e: Add functions `addFertilizerApplication`, `updateFertilizerApplication`, `removeFertilizerApplication`, `getFertilizerApplication` and `getFertilizerApplications` +- 6ef3d44: Alter `p_acquiring_date` and `p_picking_date` from date to timestamptz +- 61da12f: Add to output of `getCultivationPlan` the `fertilizer_applications` +- 5be0abc: `getFertilizers` returns the details of the fertilizers similiar as `getFertilizer` +- 4189f5d: Add `fertilizer_application` table + +### Patch Changes + +- a948c61: Fix by adding `b_name` to output type of `getCultivationPlan` + ## 0.6.1 ### Patch Changes diff --git a/fdm-core/package.json b/fdm-core/package.json index 22faf7ba3..7be338694 100644 --- a/fdm-core/package.json +++ b/fdm-core/package.json @@ -1,7 +1,7 @@ { "name": "@svenvw/fdm-core", "private": false, - "version": "0.6.1", + "version": "0.7.0", "description": "Interface for the Farm Data Model", "license": "MIT", "homepage": "https://svenvw.github.io/fdm/", diff --git a/fdm-data/CHANGELOG.md b/fdm-data/CHANGELOG.md index 34d7a6b0a..a9149c257 100644 --- a/fdm-data/CHANGELOG.md +++ b/fdm-data/CHANGELOG.md @@ -1,5 +1,20 @@ # fdm-data +## 0.5.0 + +### Patch Changes + +- Updated dependencies [7af3fda] +- Updated dependencies [bc4e75f] +- Updated dependencies [a948c61] +- Updated dependencies [efa423d] +- Updated dependencies [b0c001e] +- Updated dependencies [6ef3d44] +- Updated dependencies [61da12f] +- Updated dependencies [5be0abc] +- Updated dependencies [4189f5d] + - @svenvw/fdm-core@0.7.0 + ## 0.4.0 ### Minor Changes diff --git a/fdm-data/package.json b/fdm-data/package.json index 3e902a03e..d88a95c14 100644 --- a/fdm-data/package.json +++ b/fdm-data/package.json @@ -1,7 +1,7 @@ { "name": "@svenvw/fdm-data", "private": false, - "version": "0.4.0", + "version": "0.5.0", "description": "Extend Farm Data Model with catalogue data", "license": "MIT", "homepage": "https://github.com/SvenVw/fdm", @@ -58,7 +58,7 @@ "vitest": "^2.1.3" }, "peerDependencies": { - "@svenvw/fdm-core": "workspace:>=0.6.1" + "@svenvw/fdm-core": "workspace:>=0.7.0" }, "packageManager": "pnpm@9.14.2", "publishConfig": { From 878ddb569becbb73d65ab93b50ec45c4d4452ea5 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:56:29 +0100 Subject: [PATCH 44/65] Update fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Sven Verweij <37927107+SvenVw@users.noreply.github.com> --- ..._id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 0983bf1c6..84710dcbc 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -164,9 +164,12 @@ export async function action({ try { - p_app_ids.split(',').map(async (p_app_id: string) => { - await removeFertilizerApplication(fdm, p_app_id); - }) + const p_app_ids_array = p_app_ids.split(','); + await Promise.all( + p_app_ids_array.map((p_app_id: string) => + removeFertilizerApplication(fdm, p_app_id) + ) + ); return dataWithSuccess({}, { message: "Bemesting is verwijderd" }); } catch (error) { From 69f47ecaa6fc171554388b2b32d8820b7ab455fe Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:59:14 +0100 Subject: [PATCH 45/65] Ensure p_app_method parameter is correctly handled in addFertilizerApplication --- ...farm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 84710dcbc..426e3ba3c 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -142,7 +142,7 @@ export async function action({ b_id, p_id, p_app_amount, - null, + undefined, p_app_date ) }) From 9862df670533efe5aadfbccfbe3e8b0b103640f8 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:01:28 +0100 Subject: [PATCH 46/65] Use consistent b_lu_catalogue variable when adding cultivations --- fdm-core/src/cultivation.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdm-core/src/cultivation.test.ts b/fdm-core/src/cultivation.test.ts index eb483ce94..cfa8d10c4 100644 --- a/fdm-core/src/cultivation.test.ts +++ b/fdm-core/src/cultivation.test.ts @@ -234,7 +234,7 @@ describe('Cultivation Data Model', () => { b_lu_hcat3_name: "test" }) - b_lu = await addCultivation(fdm, 'wheat', b_id, '2024-03-01') + b_lu = await addCultivation(fdm, b_lu_catalogue, b_id, '2024-03-01') // Add fertilizer to catalogue (needed for fertilizer application) const p_id_catalogue = nanoid(); @@ -316,7 +316,7 @@ describe('Cultivation Data Model', () => { expect(cultivationPlan).toBeDefined(); expect(cultivationPlan.length).toBeGreaterThan(0); - const wheatCultivation = cultivationPlan.find((c) => c.b_lu_catalogue === 'wheat'); + const wheatCultivation = cultivationPlan.find((c) => c.b_lu_catalogue === b_lu_catalogue); expect(wheatCultivation).toBeDefined(); expect(wheatCultivation?.fields.length).toBeGreaterThan(0); From 4e6e8bb7f394a9e87723074dc651d57a2315d52c Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:05:25 +0100 Subject: [PATCH 47/65] Update fdm-app/app/root.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Sven Verweij <37927107+SvenVw@users.noreply.github.com> --- fdm-app/app/root.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fdm-app/app/root.tsx b/fdm-app/app/root.tsx index e597abbba..015693686 100644 --- a/fdm-app/app/root.tsx +++ b/fdm-app/app/root.tsx @@ -22,8 +22,13 @@ export const links: LinksFunction = () => [ ]; export const loader = async ({ request }: LoaderFunctionArgs) => { - const { toast, headers } = await getToast(request); - return data({ toast }, { headers }); + try { + const { toast, headers } = await getToast(request); + return data({ toast }, { headers }); + } catch (error) { + console.error('Failed to get toast:', error); + return data({ toast: null }, {}); + } } export function Layout() { From c846c0f82510f8e057a2f37727d2e0b078aef0c0 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:05:42 +0100 Subject: [PATCH 48/65] Add validation for b_id and p_id before inserting --- fdm-core/src/fertilizer.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index 9a03e7c57..6d26abf26 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -325,6 +325,19 @@ export async function addFertilizerApplication( p_app_method: schema.fertilizerApplicationTypeInsert['p_app_method'], p_app_date: schema.fertilizerApplicationTypeInsert['p_app_date'] ): Promise { + + // Validate that the field exists + const fieldExists = await fdm.select().from(schema.fields).where(eq(schema.fields.b_id, b_id)).limit(1); + if (fieldExists.length === 0) { + throw new Error(`Field with b_id ${b_id} does not exist`); + } + + // Validate that the fertilizer exists + const fertilizerExists = await fdm.select().from(schema.fertilizers).where(eq(schema.fertilizers.p_id, p_id)).limit(1); + if (fertilizerExists.length === 0) { + throw new Error(`Fertilizer with p_id ${p_id} does not exist`); + } + const p_app_id = nanoid(); try { @@ -370,7 +383,7 @@ export async function updateFertilizerApplication( try { await fdm .update(schema.fertilizerApplication) - .set({b_id, p_id, p_app_amount, p_app_method, p_app_date}) + .set({ b_id, p_id, p_app_amount, p_app_method, p_app_date }) .where(eq(schema.fertilizerApplication.p_app_id, p_app_id)); } catch (error) { throw new Error(`Failed to update fertilizer application: ${error}`); From 2623632bdfecca49a5afbc02cf6810075b31fe9f Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:10:20 +0100 Subject: [PATCH 49/65] Update fdm-app/app/routes/app.addfarm.new.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Sven Verweij <37927107+SvenVw@users.noreply.github.com> --- fdm-app/app/routes/app.addfarm.new.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.new.tsx b/fdm-app/app/routes/app.addfarm.new.tsx index b6ec69b2a..fac6b7522 100644 --- a/fdm-app/app/routes/app.addfarm.new.tsx +++ b/fdm-app/app/routes/app.addfarm.new.tsx @@ -96,10 +96,18 @@ export async function action({ const b_id_farm = await addFarm(fdm, b_name_farm, null) // Add the fertilizers from the catalogue to the database - const fertilizers = await getFertilizersFromCatalogue(fdm); - await fertilizers.map(async (fertilizer) => { - await addFertilizer(fdm, fertilizer.p_id_catalogue, b_id_farm) - }) + try { + const fertilizers = await getFertilizersFromCatalogue(fdm); + await Promise.all( + fertilizers.map(fertilizer => + addFertilizer(fdm, fertilizer.p_id_catalogue, b_id_farm) + ) + ); + } catch (error) { + console.error('Failed to add fertilizers:', error); + // Consider how to handle this error - perhaps return a specific error response + throw error; + } return redirect(`../addfarm/${b_id_farm}/map`) } \ No newline at end of file From a5883f38ca141ed15b40456bef54c42a0416c457 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:10:29 +0100 Subject: [PATCH 50/65] Upgrade tsconfig to ES2022 --- fdm-core/tsconfig.json | 4 ++-- fdm-data/tsconfig.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fdm-core/tsconfig.json b/fdm-core/tsconfig.json index 0511b9f0e..8f3e48303 100644 --- a/fdm-core/tsconfig.json +++ b/fdm-core/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ES2022", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "skipLibCheck": true, /* Bundler mode */ diff --git a/fdm-data/tsconfig.json b/fdm-data/tsconfig.json index 0511b9f0e..8f3e48303 100644 --- a/fdm-data/tsconfig.json +++ b/fdm-data/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ES2022", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "skipLibCheck": true, /* Bundler mode */ From 4db3182ee4e05ed58b1f25c5a0a7a791efe281b0 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:10:37 +0100 Subject: [PATCH 51/65] Fix error message --- fdm-core/src/fertilizer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdm-core/src/fertilizer.ts b/fdm-core/src/fertilizer.ts index 6d26abf26..ccf025adf 100644 --- a/fdm-core/src/fertilizer.ts +++ b/fdm-core/src/fertilizer.ts @@ -350,7 +350,7 @@ export async function addFertilizerApplication( p_app_date, }); } catch (error) { - throw new Error(`Failed to add fertilizer application: ${error}`); + throw new Error(`Failed to add fertilizer application: ${error instanceof Error ? error.message : String(error)}`, { cause: error }); } return p_app_id; From 6e41e544aa18143370970d172e6b5c332353789f Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:13:01 +0100 Subject: [PATCH 52/65] Update fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Sven Verweij <37927107+SvenVw@users.noreply.github.com> --- ...ltivations.$b_lu_catalogue.fertilizers.tsx | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 84710dcbc..8c64fdaab 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -52,21 +52,14 @@ export async function loader({ const fertilizerApplications = targetCultivation.fields.reduce((accumulator, field) => { field.fertilizer_applications.forEach(app => { // Create a key based on application properties to identify similar applications. - const applicationKey = JSON.stringify({ - p_id_catalogue: app.p_id_catalogue, - p_app_amount: app.p_app_amount, - p_app_method: app.p_app_method, - p_app_date: app.p_app_date, - }); - - // Check if a similar application already exists in the accumulator. - const existingApplication = accumulator.find( - (existingApp) => JSON.stringify({ - p_id_catalogue: existingApp.p_id_catalogue, - p_app_amount: existingApp.p_app_amount, - p_app_method: existingApp.p_app_method, - p_app_date: existingApp.p_app_date, - }) === applicationKey + const isSimilarApplication = (app1: any, app2: any) => + app1.p_id_catalogue === app2.p_id_catalogue && + app1.p_app_amount === app2.p_app_amount && + app1.p_app_method === app2.p_app_method && + app1.p_app_date === app2.p_app_date; + + const existingApplication = accumulator.find(existingApp => + isSimilarApplication(existingApp, app) ); if (existingApplication) { From 6173e469704266343b01e05a2e75c9d0beb7547d Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:17:16 +0100 Subject: [PATCH 53/65] Add type checking for form data --- ..._farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 426e3ba3c..68ebbd256 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -152,21 +152,20 @@ export async function action({ } else if (request.method == 'DELETE') { const formData = await request.formData(); - const p_app_ids = formData.get("p_app_ids")?.toString(); + const rawAppIds = formData.get("p_app_ids"); - if (!p_app_ids) { + if (!rawAppIds || typeof rawAppIds !== 'string') { return dataWithError( - 'Missing values for p_app_ids', + 'Invalid or missing p_app_ids value', "Oops! Something went wrong. Please try again later." ); - } try { - const p_app_ids_array = p_app_ids.split(','); + const p_app_ids = rawAppIds.split(','); await Promise.all( - p_app_ids_array.map((p_app_id: string) => + p_app_ids.map((p_app_id: string) => removeFertilizerApplication(fdm, p_app_id) ) ); From 6bff009449a72756d9166d494bc97b85947c5379 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:21:43 +0100 Subject: [PATCH 54/65] Review form initialization values. --- fdm-app/app/components/custom/fertilizer-applications.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdm-app/app/components/custom/fertilizer-applications.tsx b/fdm-app/app/components/custom/fertilizer-applications.tsx index ffcf829ca..d30b4e78f 100644 --- a/fdm-app/app/components/custom/fertilizer-applications.tsx +++ b/fdm-app/app/components/custom/fertilizer-applications.tsx @@ -53,8 +53,8 @@ export function FertilizerApplicationsForm(props: { fertilizerApplications: any[ mode: "onTouched", resolver: zodResolver(FormSchema), defaultValues: { - p_app_amount: 0, - // p_app_date: new Date(), + p_app_amount: undefined, + p_app_date: new Date(), } }) From be29e5a6926f3fbc91f07067f117e897dff6da56 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:27:46 +0100 Subject: [PATCH 55/65] Fix comparison --- ....$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index e89028004..3b2463e05 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -56,8 +56,8 @@ export async function loader({ app1.p_id_catalogue === app2.p_id_catalogue && app1.p_app_amount === app2.p_app_amount && app1.p_app_method === app2.p_app_method && - app1.p_app_date === app2.p_app_date; - + app1.p_app_date.getTime() === app2.p_app_date.getTime(); + const existingApplication = accumulator.find(existingApp => isSimilarApplication(existingApp, app) ); @@ -73,6 +73,8 @@ export async function loader({ return accumulator; }, []); + console.log(fertilizerApplications) + return { b_lu_catalogue: b_lu_catalogue, From f7c94ce7acbba772c5d0d3c2f9f43b5022aca670 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:30:00 +0100 Subject: [PATCH 56/65] Resolve component redeclaration --- fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx index 2c0d03a98..c947cc622 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.tsx @@ -14,7 +14,6 @@ import { Toaster } from "@/components/ui/toaster" import { fdm } from "../services/fdm.server"; import { getCultivationPlan, getFarm } from "@svenvw/fdm-core"; import { Button, buttonVariants } from "@/components/ui/button"; -import { SidebarNav } from "@/components/blocks/cultivation-plan"; import { cn } from "@/lib/utils"; // Meta From 74a768b58f412eeb92daf679e0b3fed94123be91 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:32:22 +0100 Subject: [PATCH 57/65] Add loading state and error handling to delete operation. --- .../custom/fertilizer-applications.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/fdm-app/app/components/custom/fertilizer-applications.tsx b/fdm-app/app/components/custom/fertilizer-applications.tsx index d30b4e78f..c653c8e26 100644 --- a/fdm-app/app/components/custom/fertilizer-applications.tsx +++ b/fdm-app/app/components/custom/fertilizer-applications.tsx @@ -65,8 +65,10 @@ export function FertilizerApplicationsForm(props: { fertilizerApplications: any[ }, [form.formState]) const handleDelete = (p_app_ids: string[]) => { + if (fetcher.state === 'submitting') return; + fetcher.submit( - { p_app_ids }, + { p_app_ids }, { method: "delete", action: props.action } ); }; @@ -187,8 +189,18 @@ export function FertilizerApplicationsForm(props: { fertilizerApplications: any[

-
From fdbf240fc1d604c2041e78199569a8ac37861f8a Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:34:58 +0100 Subject: [PATCH 58/65] Remove console.log --- ...farm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 3b2463e05..5b2a50421 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -73,8 +73,6 @@ export async function loader({ return accumulator; }, []); - console.log(fertilizerApplications) - return { b_lu_catalogue: b_lu_catalogue, From 3c410e2cac9b63f3a66860da147251ae48d356bb Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:35:18 +0100 Subject: [PATCH 59/65] Add proper TypeScript types for props. --- .../custom/fertilizer-applications.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/fdm-app/app/components/custom/fertilizer-applications.tsx b/fdm-app/app/components/custom/fertilizer-applications.tsx index c653c8e26..c574e30ed 100644 --- a/fdm-app/app/components/custom/fertilizer-applications.tsx +++ b/fdm-app/app/components/custom/fertilizer-applications.tsx @@ -45,8 +45,27 @@ export const FormSchema = z.object({ invalid_type_error: "Meststof is ongeldig", }) }) +interface FertilizerApplication { + p_app_id: string; + p_app_ids: string[]; + p_name_nl: string; + p_app_amount: number; + p_app_date: Date; + } + + interface FertilizerOption { + value: string; + label: string; + } + + interface FertilizerApplicationsFormProps { + fertilizerApplications: FertilizerApplication[]; + options: FertilizerOption[]; + defaultValue?: string; + action: string; + } -export function FertilizerApplicationsForm(props: { fertilizerApplications: any[], options: { value: string, label: string }[], defaultValue?: string, action: string }) { +export function FertilizerApplicationsForm(props: FertilizerApplicationsFormProps) { const fetcher = useFetcher(); const form = useRemixForm>({ From 6c21a08f206a22943b5e510a54d591a899786edc Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:39:26 +0100 Subject: [PATCH 60/65] Improve toast with addFarm --- fdm-app/app/routes/app.addfarm.new.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.new.tsx b/fdm-app/app/routes/app.addfarm.new.tsx index fac6b7522..8c11bda2d 100644 --- a/fdm-app/app/routes/app.addfarm.new.tsx +++ b/fdm-app/app/routes/app.addfarm.new.tsx @@ -1,5 +1,5 @@ import type { MetaFunction, ActionFunctionArgs, LoaderFunctionArgs } from "react-router"; -import { useLoaderData, redirect } from "react-router"; +import { useLoaderData, redirect, data } from "react-router"; import { z } from "zod" import { addFarm, addFertilizer, getFertilizersFromCatalogue } from "@svenvw/fdm-core"; @@ -14,6 +14,7 @@ import { Farm } from "@/components/blocks/farm"; // Services import { fdm } from "../services/fdm.server"; import { extractFormValuesFromRequest } from "@/lib/form"; +import { dataWithError, dataWithSuccess, redirectWithSuccess } from "remix-toast"; // Meta export const meta: MetaFunction = () => { @@ -106,8 +107,8 @@ export async function action({ } catch (error) { console.error('Failed to add fertilizers:', error); // Consider how to handle this error - perhaps return a specific error response - throw error; + return dataWithError(null, "Oops! Something went wrong. Please try again later."); } - return redirect(`../addfarm/${b_id_farm}/map`) + return redirectWithSuccess(`../addfarm/${b_id_farm}/map`, { message: "Bedrijf is toegevoegd! 🎉" }) } \ No newline at end of file From 3dd4f443150fb51ea158a76e3ccd3e07bd865cd2 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:41:24 +0100 Subject: [PATCH 61/65] Improve type --- fdm-app/app/components/custom/combobox.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdm-app/app/components/custom/combobox.tsx b/fdm-app/app/components/custom/combobox.tsx index 7af6f9c3e..2a207d279 100644 --- a/fdm-app/app/components/custom/combobox.tsx +++ b/fdm-app/app/components/custom/combobox.tsx @@ -1,4 +1,4 @@ -import { useState } from "react" +import { ReactNode, useState } from "react" import { Button } from "@/components/ui/button" import { @@ -34,7 +34,7 @@ interface ComboboxProps { options: { value: string, label: string }[] form: any name: string - label: any + label: ReactNode } export function Combobox({ From 098e8d0d3815ae8d6440d54734a71d53fe967950 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:18:26 +0100 Subject: [PATCH 62/65] Update fdm-app/app/routes/app.addfarm.new.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Sven Verweij <37927107+SvenVw@users.noreply.github.com> --- fdm-app/app/routes/app.addfarm.new.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.new.tsx b/fdm-app/app/routes/app.addfarm.new.tsx index 8c11bda2d..e33dfb407 100644 --- a/fdm-app/app/routes/app.addfarm.new.tsx +++ b/fdm-app/app/routes/app.addfarm.new.tsx @@ -104,11 +104,10 @@ export async function action({ addFertilizer(fdm, fertilizer.p_id_catalogue, b_id_farm) ) ); + return redirectWithSuccess(`../addfarm/${b_id_farm}/map`, { message: "Bedrijf is toegevoegd! 🎉" }) } catch (error) { console.error('Failed to add fertilizers:', error); // Consider how to handle this error - perhaps return a specific error response return dataWithError(null, "Oops! Something went wrong. Please try again later."); } - - return redirectWithSuccess(`../addfarm/${b_id_farm}/map`, { message: "Bedrijf is toegevoegd! 🎉" }) } \ No newline at end of file From d1eb1b2873f2dd7a9c6b7acc59c9c246254a55aa Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:19:02 +0100 Subject: [PATCH 63/65] Upgrade to ES2022 --- fdm-calculator/CHANGELOG.md | 7 +++++++ fdm-calculator/package.json | 2 +- fdm-calculator/tsconfig.json | 4 ++-- fdm-core/CHANGELOG.md | 1 + fdm-data/CHANGELOG.md | 1 + 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/fdm-calculator/CHANGELOG.md b/fdm-calculator/CHANGELOG.md index 7999c41c6..f77b9b7d1 100644 --- a/fdm-calculator/CHANGELOG.md +++ b/fdm-calculator/CHANGELOG.md @@ -1,5 +1,12 @@ # fdm-calculator +## 0.0.2 + +### Patch Changes + +- Upgrade to use ES2022 + + ## 0.0.1 ### Patch Changes diff --git a/fdm-calculator/package.json b/fdm-calculator/package.json index 5da7f6149..d8d09afd3 100644 --- a/fdm-calculator/package.json +++ b/fdm-calculator/package.json @@ -1,7 +1,7 @@ { "name": "fdm-calculator", "private": true, - "version": "0.0.1", + "version": "0.0.2", "description": "Calculate various insights based on the Farm Data Model", "license": "MIT", "homepage": "https://github.com/SvenVw/fdm", diff --git a/fdm-calculator/tsconfig.json b/fdm-calculator/tsconfig.json index 0511b9f0e..8f3e48303 100644 --- a/fdm-calculator/tsconfig.json +++ b/fdm-calculator/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ES2022", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "skipLibCheck": true, /* Bundler mode */ diff --git a/fdm-core/CHANGELOG.md b/fdm-core/CHANGELOG.md index 1ce798aad..f2c9b8796 100644 --- a/fdm-core/CHANGELOG.md +++ b/fdm-core/CHANGELOG.md @@ -16,6 +16,7 @@ ### Patch Changes - a948c61: Fix by adding `b_name` to output type of `getCultivationPlan` +- Upgrade to use ES2022 ## 0.6.1 diff --git a/fdm-data/CHANGELOG.md b/fdm-data/CHANGELOG.md index a9149c257..22388f46b 100644 --- a/fdm-data/CHANGELOG.md +++ b/fdm-data/CHANGELOG.md @@ -4,6 +4,7 @@ ### Patch Changes +- Upgrade to use ES2022 - Updated dependencies [7af3fda] - Updated dependencies [bc4e75f] - Updated dependencies [a948c61] From 460247455fe0cd4b9e13ea3290d9e01641c801e6 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:20:53 +0100 Subject: [PATCH 64/65] Improve error message --- ..._farm.cultivations.$b_lu_catalogue.fertilizers.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx index 5b2a50421..0fe4564b8 100644 --- a/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx +++ b/fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx @@ -52,13 +52,13 @@ export async function loader({ const fertilizerApplications = targetCultivation.fields.reduce((accumulator, field) => { field.fertilizer_applications.forEach(app => { // Create a key based on application properties to identify similar applications. - const isSimilarApplication = (app1: any, app2: any) => + const isSimilarApplication = (app1: any, app2: any) => app1.p_id_catalogue === app2.p_id_catalogue && app1.p_app_amount === app2.p_app_amount && app1.p_app_method === app2.p_app_method && app1.p_app_date.getTime() === app2.p_app_date.getTime(); - - const existingApplication = accumulator.find(existingApp => + + const existingApplication = accumulator.find(existingApp => isSimilarApplication(existingApp, app) ); @@ -167,7 +167,10 @@ export async function action({ } catch (error) { // Handle errors appropriately. Log the error for debugging purposes. console.error("Error deleting fertilizer application:", error); - return dataWithError(null, "Oops! Something went wrong. Please try again later."); + return dataWithError( + error instanceof Error ? error.message : "Unknown error", + "Er is een fout opgetreden bij het verwijderen van de bemesting. Probeer het later opnieuw." + ); } } From 87e0c8a75dbc8e31937ab9ab1ebbe4a25464b263 Mon Sep 17 00:00:00 2001 From: Sven Verweij <37927107+SvenVw@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:28:28 +0100 Subject: [PATCH 65/65] Add transaction management for atomic operations --- fdm-app/app/routes/app.addfarm.new.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/fdm-app/app/routes/app.addfarm.new.tsx b/fdm-app/app/routes/app.addfarm.new.tsx index e33dfb407..efe929be9 100644 --- a/fdm-app/app/routes/app.addfarm.new.tsx +++ b/fdm-app/app/routes/app.addfarm.new.tsx @@ -94,20 +94,17 @@ export async function action({ const { b_name_farm } = formValues; // Create a farm - const b_id_farm = await addFarm(fdm, b_name_farm, null) - - // Add the fertilizers from the catalogue to the database try { + const b_id_farm = await addFarm(fdm, b_name_farm, null); const fertilizers = await getFertilizersFromCatalogue(fdm); await Promise.all( - fertilizers.map(fertilizer => + fertilizers.map(fertilizer => addFertilizer(fdm, fertilizer.p_id_catalogue, b_id_farm) ) ); - return redirectWithSuccess(`../addfarm/${b_id_farm}/map`, { message: "Bedrijf is toegevoegd! 🎉" }) + return redirectWithSuccess(`../addfarm/${b_id_farm}/map`, { message: "Bedrijf is toegevoegd! 🎉" }); } catch (error) { - console.error('Failed to add fertilizers:', error); - // Consider how to handle this error - perhaps return a specific error response - return dataWithError(null, "Oops! Something went wrong. Please try again later."); + console.error('Failed to create farm with fertilizers:', error); + return dataWithError(null, "Er is iets misgegaan bij het aanmaken van het bedrijf."); } } \ No newline at end of file