Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
a959860
LF-4765 Add get prescriptions route to routes
Duncan-Brain Apr 23, 2025
3b38070
LF-4765 Add get prescriptions wireframe to controller
Duncan-Brain Apr 23, 2025
0f9e03e
LF-4765 WIP - add basic mock and get farmaddon function
Duncan-Brain Apr 24, 2025
07c4a5b
LF-4765 send response for postman testing
Duncan-Brain Apr 25, 2025
645fd4d
LF-4765 Add blocked model util
Duncan-Brain Apr 25, 2025
549fd6c
LF-4765 update mocking function
Duncan-Brain Apr 25, 2025
1ed1420
LF-4765 Was confused about which route I should use moved irrigation …
Duncan-Brain Apr 25, 2025
8ca78c2
LF-4765 Add dayjs package
Duncan-Brain Apr 28, 2025
89fa6b0
LF-4765 Add model function to return utc_offset
Duncan-Brain Apr 28, 2025
d489db1
LF-4765 Add new farm service and add farm specific date utils
Duncan-Brain Apr 29, 2025
7149fa7
LF-4765 Add type guard and change syntax for task_id
Duncan-Brain Apr 29, 2025
c4ffe7d
LF-4765 Add ensemble call to service and remove and export mocked fun…
Duncan-Brain Apr 29, 2025
72ac94d
LF-4765 Copy irrigation prescription request fromat for returning moc…
Duncan-Brain Apr 29, 2025
e6dbd57
LF-4765 Update task model with jsdoc, uncomment external id info now …
Duncan-Brain May 1, 2025
a44f01d
LF-4765 Export point type and update type guard to only test external…
Duncan-Brain May 1, 2025
7f62c17
LF-4765 Finally stop cheating, just adding full types
Duncan-Brain May 1, 2025
498fb9f
LF-4765 Add task id search to data formatting, refactor some types an…
Duncan-Brain May 1, 2025
74671e1
LF-4765 Filter tasks by farm Id since org_id are not constrained to j…
Duncan-Brain May 2, 2025
e60d300
LF-4765 update scope check
Duncan-Brain May 2, 2025
36bbde8
LF-4765 Fix data type in irrigation types
Duncan-Brain May 2, 2025
ce0a969
LF-4765 Add more types to type file
Duncan-Brain May 2, 2025
f82a34a
LF-4765 Update model function to return all tasks, update ensemble se…
Duncan-Brain May 2, 2025
f21d713
LF-4765 Add tests for get endpoint
Duncan-Brain May 2, 2025
d9c6532
LF-4765 Add after date to request query, remove farmDate utilities, a…
Duncan-Brain May 2, 2025
335ba39
LF-4765 Add after date to tests
Duncan-Brain May 2, 2025
c62de99
LF-4765 Cleanup duplicated types
Duncan-Brain May 2, 2025
1cb661d
LF-4765 Remove mistakenly added function
Duncan-Brain May 6, 2025
76e4fbc
LF-4765 Farm date cleanup
Duncan-Brain May 6, 2025
2e90e3a
LF-4765 Remove extra mocking function and move to tests, add todo for…
Duncan-Brain May 6, 2025
867842f
LF-4765 improve/fix mock logic
Duncan-Brain May 7, 2025
4860c06
LF-4765 Adjust frontend query to backend specs, move mocks to backend
Duncan-Brain May 7, 2025
406ca29
LF-4765 Update date params for irrigation prescription endpoints
Duncan-Brain May 7, 2025
ed4a117
LF-4765 Add management plan type and dependencies
Duncan-Brain May 8, 2025
43899c1
LF-4765 Add mamangement plan to expected return mock and type
Duncan-Brain May 8, 2025
f72a318
LF-4765 rename what was a temporary variable to a permanent one
Duncan-Brain May 8, 2025
8e8c1f3
LF-4765 Update types file with farm addon and point
Duncan-Brain May 8, 2025
3940875
LF-4765 Invalidate irrigation prescription query between logouts
Duncan-Brain May 8, 2025
6aa5d17
LF-4765 Send empty array if no farm addons that provide irrigation pr…
Duncan-Brain May 8, 2025
6edc866
LF-4765 Add frontend date utils to backend tests utils
Duncan-Brain May 9, 2025
cda8040
LF-4765 Fix tests to accomodate new values
Duncan-Brain May 9, 2025
e0dcf25
Merge branch 'integration' into LF-4765-create-get-endpoint-to-fetch-…
Duncan-Brain May 9, 2025
ff5aedf
LF-4765 Fix package lock
Duncan-Brain May 9, 2025
7008086
LF-4765 Touch up comments and types
Duncan-Brain May 9, 2025
e00783b
LF-4765 Add query check middleware
Duncan-Brain May 15, 2025
199247e
LF-4765 Update irrigation prescription types and type guard to use ne…
Duncan-Brain May 15, 2025
7927a3a
LF-4765 Small fixes to update comments, error array and accessing rec…
Duncan-Brain May 15, 2025
e7a9115
LF-4765 Add comments to regex check for use when testing with postman
Duncan-Brain May 15, 2025
bf0310c
LF-4765 Update jsdoc
Duncan-Brain May 15, 2025
b461a6a
LF-4765 Refactor tests proper by creating facotries and mocking the e…
Duncan-Brain May 16, 2025
7dae074
LF-4765 Make required query params in controller move type owner
Duncan-Brain May 16, 2025
86cbd5c
LF-4765 Add query params to frontend
Duncan-Brain May 16, 2025
66b0f86
LF-4765 Refactor mocking
Duncan-Brain May 16, 2025
78d0cc3
LF-4765 undo type casting
Duncan-Brain May 20, 2025
7207d69
LF-4765 Invalidate tags on task deletion and creation
Duncan-Brain May 20, 2025
1e530ae
LF-4765 Plural url form
Duncan-Brain May 20, 2025
4871eb3
LF-4765 Add addonPartner service
Duncan-Brain May 20, 2025
39172f8
LF-4765 Move types and data formatting to service
Duncan-Brain May 20, 2025
8d54eab
LF-4765 Move shouldSend boolean to only affect ESci
Duncan-Brain May 20, 2025
3a6219f
LF-4765 rename mock
Duncan-Brain May 20, 2025
6f14118
Merge branch 'integration' into LF-4765-create-get-endpoint-to-fetch-…
Duncan-Brain May 20, 2025
009e46a
Merge branch 'integration' into LF-4765-create-get-endpoint-to-fetch-…
kathyavini May 21, 2025
42b9df0
LF-4765 Wrong type for shouldSend
Duncan-Brain May 21, 2025
8090cf4
Merge branch 'integration' into LF-4765-create-get-endpoint-to-fetch-…
Duncan-Brain May 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2025 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { Response } from 'express';
import { LiteFarmRequest, HttpError } from '../types.js';
import { IrrigationPrescriptionQueryParams } from '../middleware/validation/checkIrrigationPrescription.js';
import { getAddonPartnerIrrigationPrescriptions } from '../services/addonPartner.js';

const irrigationPrescriptionController = {
getPrescriptions() {
return async (
req: LiteFarmRequest<Required<IrrigationPrescriptionQueryParams>>,
res: Response,
) => {
try {
const { farm_id } = req.headers;
const { startTime, endTime, shouldSend } = req.query;

const irrigationPrescriptions = await getAddonPartnerIrrigationPrescriptions(
// @ts-expect-error - farm_id is guaranteed here by the checkScope middleware with single argument
farm_id,
startTime,
endTime,
shouldSend,
);

return res.status(200).send(irrigationPrescriptions);
} catch (error: unknown) {
console.error(error);
const err = error as HttpError;
const status = err.status || err.code || 500;
return res.status(status).json({
error: err.message || err,
});
}
};
},
};

export default irrigationPrescriptionController;
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,26 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { Request, Response } from 'express';
import { Response } from 'express';
import { getOrgLocationAndCropData, sendFieldAndCropDataToEsci } from '../util/ensembleService.js';
import { LiteFarmRequest } from '../types.js';

interface HttpError extends Error {
status?: number;
code?: number; // LF custom error
}

interface LiteFarmQuery {
interface InitiateFarmIrrigationPrescriptionQueryParams {
allOrgs?: string;
shouldSend?: string;
}

export interface LiteFarmRequest extends Request<unknown, unknown, unknown, LiteFarmQuery> {
Comment thread
Duncan-Brain marked this conversation as resolved.
headers: Request['headers'] & {
farm_id?: string;
};
}

const irrigationPrescriptionRequestController = {
initiateFarmIrrigationPrescription() {
return async (req: LiteFarmRequest, res: Response) => {
return async (
req: LiteFarmRequest<InitiateFarmIrrigationPrescriptionQueryParams>,
res: Response,
) => {
const { farm_id } = req.headers;
const { allOrgs, shouldSend } = req.query;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2025 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { Request, Response, NextFunction } from 'express';
import { isISO8601Format } from '../../util/validation.js';

export interface IrrigationPrescriptionQueryParams {
startTime?: string;
endTime?: string;
shouldSend?: string;
}

export function checkGetIrrigationPrescription() {
return async (
req: Request<unknown, unknown, unknown, IrrigationPrescriptionQueryParams>,
res: Response,
next: NextFunction,
) => {
const { startTime, endTime, shouldSend } = req.query;

if (shouldSend != 'true' && shouldSend != 'false') {
return res.status(400).send('Please provide shouldSend as true or false');
}

if (!startTime || !isISO8601Format(startTime)) {
return res.status(400).send('Please provide startTime in ISO 8601 format');
}

if (!endTime || !isISO8601Format(endTime)) {
return res.status(400).send('Please provide endTime in ISO 8601 format');
}

next();
};
}
13 changes: 13 additions & 0 deletions packages/api/src/models/farmAddonModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ class FarmAddon extends baseModel {
.where('addon_partner_id', addonPartnerId)
.whereNotDeleted();
}

/**
* Retrieves unique addon partner ids from farm addons.
*
* @param {string} farmId - The ID of the farm.
* @returns {Promise<Array<{addon_partner_id: number}>>} The partner identifiers for the farm queried.
*/
static async getDistinctFarmAddonPartnerIds(farmId) {
return FarmAddon.query()
.distinct('addon_partner_id')
.where('farm_id', farmId)
.whereNotDeleted();
}
}

export default FarmAddon;
2 changes: 1 addition & 1 deletion packages/api/src/models/irrigationTypesModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class IrrigationTypesModel extends BaseModel {
type: 'object',
required: [''],
properties: {
irrigation_type_id: { type: 'string' },
irrigation_type_id: { type: 'integer' },

@Duncan-Brain Duncan-Brain May 9, 2025

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error in model setup -- type is actually incrementing pk

irrigation_type_name: { type: 'string' },
farm_id: { type: 'string' },
default_measuring_type: { type: 'string' },
Expand Down
30 changes: 26 additions & 4 deletions packages/api/src/models/taskModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,16 +360,19 @@ class TaskModel extends BaseModel {
*/
static async getUnassignedTasksDueThisWeekFromIds(taskIds, isDayLaterThanUTC = false) {
const dayLaterInterval = isDayLaterThanUTC ? '"1 day"' : '"0 days"';
return await TaskModel.query().select('*').whereIn('task_id', taskIds).whereRaw(
`
return await TaskModel.query()
.select('*')
.whereIn('task_id', taskIds)
.whereRaw(
`
task.assignee_user_id IS NULL
AND task.complete_date IS NULL
AND task.abandon_date IS NULL
AND task.due_date <= (now() + ('1 week')::interval + (?)::interval)::date
AND task.due_date >= (now() + (?)::interval)::date
`,
[dayLaterInterval, dayLaterInterval],
);
[dayLaterInterval, dayLaterInterval],
);
}

/**
Expand Down Expand Up @@ -510,6 +513,25 @@ class TaskModel extends BaseModel {
.withGraphFetched('[animals(selectId), animal_batches(selectId)]')
.whereIn('task_id', taskIds);
}

/**
* Returns farm tasks for an array of external ids
*
* @param {string} farmId - The farm requesting irrigation tasks.
* @param {number[]} externalIds - Array of external irrigation prescription ids of interest.
* @static
* @async
* @returns {import('./types.js').IrrigationTask[]} - Returns found irrigation tasks.
*/
static async getIrrigationTasksWithExternalIdByFarm(farmId, externalIds) {
return await TaskModel.query()
.select('task.*')
.withGraphJoined('[locations, irrigation_task]')
.whereNotNull('irrigation_task.irrigation_prescription_external_id')
.whereIn('irrigation_task.irrigation_prescription_external_id', externalIds)
.where('locations.farm_id', farmId)
.whereNotDeleted();
}
}

export default TaskModel;
Loading