Skip to content

Commit

Permalink
Merge pull request #3586 from LiteFarmOrg/LF-4577/Remove_animal_task_…
Browse files Browse the repository at this point in the history
…date_validation

LF-4577: Remove animal task dates validation
  • Loading branch information
SayakaOno authored Dec 10, 2024
2 parents 0dc2135 + cf34557 commit 9196483
Show file tree
Hide file tree
Showing 6 changed files with 1 addition and 338 deletions.
36 changes: 0 additions & 36 deletions packages/api/src/middleware/validation/checkAnimalOrBatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,41 +430,6 @@ const checkInvalidIds = async (invalidIds) => {
}
};

export async function checkDateWithTaskDueDate(animalOrBatch, animalOrBatchKey) {
const { id, birth_date, brought_in_date } = animalOrBatch;

if (!birth_date && !brought_in_date) {
return;
}

const oldestDueDateTask = await AnimalOrBatchModel[animalOrBatchKey]
.relatedQuery('tasks')
.select('due_date')
.for(id)
.whereNotDeleted()
.orderBy('due_date', 'asc')
.first();

// return if no associated tasks
if (!oldestDueDateTask?.due_date) {
return;
}

const dueDate = new Date(oldestDueDateTask.due_date);
const dueDateAtMidnight = new Date(dueDate.getFullYear(), dueDate.getMonth(), dueDate.getDate());

for (const item of [birth_date, brought_in_date].filter(Boolean)) {
const date = new Date(item);
const dateAtMidnight = new Date(date.getFullYear(), date.getMonth(), date.getDate());

if (dueDateAtMidnight < dateAtMidnight) {
throw customError(
`Birth and brought-in dates must be on or before associated tasks' due dates`,
);
}
}
}

export function checkCreateAnimalOrBatch(animalOrBatchKey) {
return async (req, res, next) => {
const trx = await transaction.start(Model.knex());
Expand Down Expand Up @@ -543,7 +508,6 @@ export function checkEditAnimalOrBatch(animalOrBatchKey) {
await checkAnimalUseRelationship(animalOrBatch, animalOrBatchKey);
await checkAnimalOrigin(animalOrBatch, false);
await checkAnimalIdentifier(animalOrBatch, animalOrBatchKey, false);
await checkDateWithTaskDueDate(animalOrBatch, animalOrBatchKey);

// Skip the process if type_name and breed_name are not passed
if (!type_name && !breed_name) {
Expand Down
69 changes: 1 addition & 68 deletions packages/api/src/middleware/validation/checkTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@

import TaskModel from '../../models/taskModel.js';
import { checkSoilAmendmentTaskProducts } from './checkSoilAmendmentTaskProducts.js';
import {
ANIMAL_TASKS,
checkAnimalAndBatchIds,
isOnOrAfterBirthAndBroughtInDates,
} from '../../util/animal.js';
import { ANIMAL_TASKS, checkAnimalAndBatchIds } from '../../util/animal.js';
import { CUSTOM_TASK } from '../../util/task.js';
import { checkIsArray, customError } from '../../util/customErrors.js';

Expand Down Expand Up @@ -235,18 +231,6 @@ async function checkAnimalTask(req, taskType, dateName) {
isAnimalOrBatchRequired,
);

if ((related_animal_ids?.length || related_batch_ids?.length) && dateName === 'due_date') {
const isValidDate = await isOnOrAfterBirthAndBroughtInDates(
req.body[dateName],
related_animal_ids,
related_batch_ids,
);

if (!isValidDate) {
throw customError(`${dateName} must be on or after the animals' birth and brought-in dates`);
}
}

const taskTypeCheck = {
animal_movement_task: checkAnimalMovementTask,
}[taskType];
Expand Down Expand Up @@ -274,20 +258,6 @@ async function checkAnimalCompleteTask(req, taskType, taskId) {
if (ANIMAL_TASKS.includes(taskType) && !finalizedAnimals?.length && !finalizedBatches?.length) {
throw customError('No animals or batches to apply the task to');
}

if (finalizedAnimals || finalizedBatches) {
const isValidDate = await isOnOrAfterBirthAndBroughtInDates(
req.body.complete_date,
(finalizedAnimals.animals || []).map(({ id }) => id),
(finalizedBatches.animal_batches || []).map(({ id }) => id),
);

if (!isValidDate) {
throw customError(
`complete_date must be on or after the animals' birth and brought-in dates`,
);
}
}
}

export function checkDeleteTask() {
Expand Down Expand Up @@ -330,40 +300,3 @@ async function checkAnimalMovementTask(req) {
checkIsArray(req.body.animal_movement_task.purpose_ids, 'purpose_ids');
}
}

export function checkDueDate() {
return async (req, res, next) => {
try {
const { due_date } = req.body;
const { task_id } = req.params;

const { animals, animal_batches } = await TaskModel.query()
.select('task_id')
.withGraphFetched('[animals(selectId), animal_batches(selectId)]')
.where({ task_id })
.first();

if (animals.length || animal_batches.length) {
const isValidDate = await isOnOrAfterBirthAndBroughtInDates(
due_date.split('T')[0],
animals.map(({ id }) => id),
animal_batches.map(({ id }) => id),
);

if (!isValidDate) {
throw customError(`due_date must be on or after the animals' birth and brought-in dates`);
}
}
next();
} catch (error) {
console.error(error);

if (error.type === 'LiteFarmCustom') {
return error.body
? res.status(error.code).json({ ...error.body, message: error.message })
: res.status(error.code).send(error.message);
}
return res.status(500).json({ error });
}
};
}
2 changes: 0 additions & 2 deletions packages/api/src/routes/taskRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
checkCompleteTask,
checkCreateTask,
checkDeleteTask,
checkDueDate,
} from '../middleware/validation/checkTask.js';

router.patch(
Expand All @@ -55,7 +54,6 @@ router.patch(
'/patch_due_date/:task_id',
hasFarmAccess({ params: 'task_id' }),
checkScope(['edit:task']),
checkDueDate(),
taskController.patchTaskDate,
);

Expand Down
39 changes: 0 additions & 39 deletions packages/api/src/util/animal.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { raw } from 'objection';
import knex from './knex.js';
import baseController from '../controllers/baseController.js';
import CustomAnimalBreedModel from '../models/customAnimalBreedModel.js';
Expand Down Expand Up @@ -195,44 +194,6 @@ export const checkAnimalAndBatchIds = async (animalIds, batchIds, farmId, isRequ
}
};

export async function isOnOrAfterBirthAndBroughtInDates(date, animalIds, batchIds) {
const animalRelevantDate = await AnimalModel.query()
.select(raw('GREATEST(birth_date, brought_in_date)').as('date'))
.whereIn('id', [...new Set(animalIds)])
.whereNotNull('birth_date')
.orWhereNotNull('brought_in_date')
.first();

const batchRelevantDate = await AnimalBatchModel.query()
.select(raw('GREATEST(birth_date, brought_in_date)').as('date'))
.whereIn('id', [...new Set(batchIds)])
.whereNotNull('birth_date')
.orWhereNotNull('brought_in_date')
.first();

if (!animalRelevantDate && !batchRelevantDate) {
return true;
}

const latestRelevantDate = new Date(
Math.max(
animalRelevantDate?.date?.getTime() ?? -Infinity,
batchRelevantDate?.date?.getTime() ?? -Infinity,
),
);

const latestRelevantDateAtMidnight = new Date(
latestRelevantDate.getFullYear(),
latestRelevantDate.getMonth(),
latestRelevantDate.getDate(),
);

const [y, m, d] = date.split('-');
const inputDateAtMidnight = new Date(y, m - 1, d);

return inputDateAtMidnight >= latestRelevantDateAtMidnight;
}

export const handleIncompleteTasksForAnimalsAndBatches = async (
req,
trx,
Expand Down
73 changes: 0 additions & 73 deletions packages/api/tests/animalAndAnimalBatchCommon.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,79 +200,6 @@ describe('Animal and Animal Batch Tests', () => {
}
};

// PATCH
describe.each(['animal', 'batch'])('Patch %s', (animalOrBatch) => {
const today = new Date();
const todayInYYYYMMDD = toLocal8601Extended(today);

test(`should be able to update ${animalOrBatch}'s birth or brough-in date to the same date as tasks' due date`, async () => {
const [[entity1]] = await createAnimalsOrBatches(animalOrBatch, 1);

// Create a task with due date
await createAnimalTask({
[`${animalOrBatch}Ids`]: [entity1.id],
taskData: { due_date: todayInYYYYMMDD },
});

// Update birth_date to the same date as task's due date
const patchReq = animalOrBatch === 'animal' ? animalPatchRequest : batchPatchRequest;
const resWithBirthDate = await patchReq({ user_id, farm_id }, [
{ id: entity1.id, birth_date: `${todayInYYYYMMDD}T00:00:00.000-08:00` },
]);

expect(resWithBirthDate.status).toBe(204);

// Update brought_in_date to the same date as task's due date
const resWithBroughtInDate = await patchReq({ user_id, farm_id }, [
{
id: entity1.id,
origin_id: broughtInOrigin.id,
brought_in_date: `${todayInYYYYMMDD}T00:00:00.000-08:00`,
},
]);
expect(resWithBroughtInDate.status).toBe(204);
});

test(`should not be able to update ${animalOrBatch}'s birth or brough-in date after tasks' due date`, async () => {
const [[entity1]] = await createAnimalsOrBatches(animalOrBatch, 1);

// Create tasks with due dates
await createAnimalTask({
[`${animalOrBatch}Ids`]: [entity1.id],
taskData: { due_date: todayInYYYYMMDD },
});
const { taskId: task2Id } = await createAnimalTask({
[`${animalOrBatch}Ids`]: [entity1.id],
});
await knex('task').update('due_date', yesterdayInYYYYMMDD).where('task_id', task2Id);

const patchReq = animalOrBatch === 'animal' ? animalPatchRequest : batchPatchRequest;

// Try to update to an invalid birth_date
const resWithBirthDate = await patchReq({ user_id, farm_id }, [
{ id: entity1.id, birth_date: `${todayInYYYYMMDD}T00:00:00.000-08:00` },
]);

expect(resWithBirthDate.status).toBe(400);
expect(resWithBirthDate.error.text).toBe(
`Birth and brought-in dates must be on or before associated tasks' due dates`,
);

// Try to update to an invalid brought_in_date
const resWithBroughtInDate = await patchReq({ user_id, farm_id }, [
{
id: entity1.id,
origin_id: broughtInOrigin.id,
brought_in_date: `${todayInYYYYMMDD}T00:00:00.000-08:00`,
},
]);
expect(resWithBroughtInDate.status).toBe(400);
expect(resWithBroughtInDate.error.text).toBe(
`Birth and brought-in dates must be on or before associated tasks' due dates`,
);
});
});

// REMOVE
describe.each(['animal', 'batch'])('Remove %s with tasks', (animalOrBatch) => {
test(`Should remove ${animalOrBatch} with incomplete task`, async () => {
Expand Down
Loading

0 comments on commit 9196483

Please sign in to comment.