Skip to content

Commit

Permalink
fix(fd2): enforces asset and log naming conventions (#235)
Browse files Browse the repository at this point in the history
**Pull Request Description**

The naming conventions for logs and assets as described in
`docs/DataModel.md` are now enforced in the code.

Closes #208 

---

**Licensing Certification**

FarmData2 is a [Free Cultural
Work](https://freedomdefined.org/Definition) and all accepted
contributions are licensed as described in the LICENSE.md file. This
requires that the contributor holds the rights to do so. By submitting
this pull request **I certify that I satisfy the terms of the [Developer
Certificate of Origin](https://developercertificate.org/)** for its
contents.
  • Loading branch information
braughtg authored Apr 16, 2024
1 parent 5fb743c commit c09f998
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 74 deletions.
6 changes: 6 additions & 0 deletions docs/DataModel.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,16 @@ Every operation in FarmData2 has one or more logs associated with it.

#### Seeding Logs

`yyyy-mm-dd_<type>_<crop>` - where `<type>` is `ts`, `ds`, or `cs` as defined above.

#### Transplanting Logs

`yyyy-mm-dd_xp_<crop>`

#### Tillage Logs

`yyyy-mm-dd_sd_<location>`

#### Amendment Logs

### Quantities
Expand Down
35 changes: 30 additions & 5 deletions library/farmosUtil/farmosUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,7 @@ export async function runTransaction(operations) {
/**
* Create a plant asset (i.e. an asset of type `asset--plant`).
*
* @param {string} assetName the name of the plant asset to create.
* @param {string} date the date on which the plant asset was created.
* @param {string} cropName the name of the crop to associate with the plant asset.
* @param {string} [comment = ""] a comment the comment to associate with this plant asset.
* @param {Array<Object>} [parents = []] an array of `asset--plant` objects to associate as parents of the new plant asset.
Expand All @@ -1575,7 +1575,7 @@ export async function runTransaction(operations) {
* @category Plant
*/
export async function createPlantAsset(
assetName,
date,
cropName,
comment = '',
parents = []
Expand All @@ -1588,6 +1588,8 @@ export async function createPlantAsset(
parentArray.push({ type: 'asset--plant', id: parent.id });
}

const assetName = date + '_' + cropName;

// create an asset--plant
const plantAsset = farm.asset.create({
type: 'asset--plant',
Expand Down Expand Up @@ -1917,10 +1919,23 @@ export async function createSeedingLog(
const quantitiesArray = getQuantityObjects(quantities);
const logCategoriesArray = await getLogCategoryObjects(logCategories);

// Generate log name based on conventions in docs/DataModel.md.
const cropIdToNameMap = await getCropIdToTermMap();
let logName = dayjs(seedingDate).format('YYYY-MM-DD');
if (logCategories.includes('seeding_tray')) {
logName += '_ts_';
} else if (logCategories.includes('seeding_direct')) {
logName += '_ds_';
} else if (logCategories.includes('seeding_cover_crop')) {
logName += '_cs_';
}
logName += cropIdToNameMap.get(plantAsset.relationships.plant_type[0].id)
.attributes.name;

const seedingLogData = {
type: 'log--seeding',
attributes: {
name: plantAsset.attributes.name,
name: logName,
timestamp: dayjs(seedingDate).format(),
status: 'done',
is_movement: true,
Expand Down Expand Up @@ -2026,10 +2041,13 @@ export async function createSoilDisturbanceActivityLog(
});
}

let assetName =
dayjs(disturbanceDate).format('YYYY-MM-DD') + '_sd_' + locationName;

const activityLogData = {
type: 'log--activity',
attributes: {
name: plantAsset.attributes.name,
name: assetName,
timestamp: dayjs(disturbanceDate).format(),
status: 'done',
purchase_date: dayjs(disturbanceDate).format(),
Expand Down Expand Up @@ -2293,10 +2311,17 @@ export async function createTransplantingActivityLog(
const quantitiesArray = getQuantityObjects(quantities);
const logCategoriesArray = await getLogCategoryObjects(['transplanting']);

const cropIdToTermMap = await getCropIdToTermMap();
const logName =
dayjs(transplantingDate).format('YYYY-MM-DD') +
'_xp_' +
cropIdToTermMap.get(plantAsset.relationships.plant_type[0].id).attributes
.name;

const activityLogData = {
type: 'log--activity',
attributes: {
name: plantAsset.attributes.name,
name: logName,
timestamp: dayjs(transplantingDate).format(),
status: 'done',
is_movement: true,
Expand Down
38 changes: 25 additions & 13 deletions library/farmosUtil/farmosUtil.plant.unit.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ describe('Test the plant asset functions', () => {
});

it('Create a plant asset', () => {
cy.wrap(farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment'))
cy.wrap(farmosUtil.createPlantAsset('1999-01-03', 'ARUGULA', 'testComment'))
.then((plantAsset) => {
cy.wrap(farmosUtil.getPlantAsset(plantAsset.id));
})
.then((result) => {
expect(result.attributes.name).to.equal('testPlant');
expect(result.attributes.name).to.equal('1999-01-03_ARUGULA');
expect(result.attributes.status).to.equal('active');
expect(result.attributes.notes.value).to.equal('testComment');
expect(result.relationships.plant_type[0].id).to.equal(
Expand All @@ -33,18 +33,28 @@ describe('Test the plant asset functions', () => {
});

it('Create a plant asset with parents', () => {
cy.wrap(farmosUtil.createPlantAsset('p1', 'ARUGULA', 'p1')).as('p1');
cy.wrap(farmosUtil.createPlantAsset('p2', 'ARUGULA', 'p2')).as('p2');
cy.wrap(farmosUtil.createPlantAsset('p3', 'ARUGULA', 'p3')).as('p3');
cy.wrap(farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'p1')).as(
'p1'
);
cy.wrap(farmosUtil.createPlantAsset('1999-01-03', 'ARUGULA', 'p2')).as(
'p2'
);
cy.wrap(farmosUtil.createPlantAsset('1999-01-04', 'ARUGULA', 'p3')).as(
'p3'
);

cy.getAll(['@p1', '@p2', '@p3']).then(([p1, p2, p3]) => {
cy.wrap(
farmosUtil.createPlantAsset('child', 'ARUGULA', 'child', [p1, p2, p3])
farmosUtil.createPlantAsset('1999-01-05', 'ARUGULA', 'child', [
p1,
p2,
p3,
])
).as('plant');
});

cy.getAll(['@plant', '@p1', '@p2', '@p3']).then(([plant, p1, p2, p3]) => {
expect(plant.attributes.name).to.equal('child');
expect(plant.attributes.name).to.equal('1999-01-05_ARUGULA');
expect(plant.attributes.status).to.equal('active');
expect(plant.attributes.notes.value).to.equal('child');
expect(plant.relationships.plant_type[0].id).to.equal(
Expand All @@ -64,7 +74,7 @@ describe('Test the plant asset functions', () => {

cy.wrap(
farmosUtil
.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
.then(() => {
throw new Error('Creating plant asset should have failed.');
})
Expand All @@ -76,7 +86,7 @@ describe('Test the plant asset functions', () => {

it('Delete a plant asset', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).then((plantAsset) => {
cy.wrap(farmosUtil.deletePlantAsset(plantAsset.id)).then((result) => {
expect(result.status).to.equal(204);
Expand All @@ -102,10 +112,12 @@ describe('Test the plant asset functions', () => {
});

it('Archive/Unarchive a plant asset', () => {
cy.wrap(farmosUtil.createPlantAsset('p1', 'ARUGULA', 'p1')).as('p1');
cy.wrap(farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'p1')).as(
'p1'
);

cy.get('@p1').then((p1) => {
expect(p1.attributes.name).to.equal('p1');
expect(p1.attributes.name).to.equal('1999-01-02_ARUGULA');
expect(p1.attributes.status).to.equal('active');

cy.wrap(farmosUtil.archivePlantAsset(p1.id, true)).as('archived');
Expand All @@ -116,7 +128,7 @@ describe('Test the plant asset functions', () => {
});

cy.get('@p1-archived').then((p1Archived) => {
expect(p1Archived.attributes.name).to.equal('p1');
expect(p1Archived.attributes.name).to.equal('1999-01-02_ARUGULA');
expect(p1Archived.attributes.status).to.equal('archived');

cy.wrap(farmosUtil.archivePlantAsset(p1Archived.id), false).as(
Expand All @@ -129,7 +141,7 @@ describe('Test the plant asset functions', () => {
});

cy.get('@p1-unArchived').then((p1unArchived) => {
expect(p1unArchived.attributes.name).to.equal('p1');
expect(p1unArchived.attributes.name).to.equal('1999-01-02_ARUGULA');
expect(p1unArchived.attributes.status).to.equal('active');
});
});
Expand Down
2 changes: 1 addition & 1 deletion library/farmosUtil/farmosUtil.quantity.unit.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('Test the quantity functions', () => {

it('Create a quantity with an inventory adjustment', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.get('@plantAsset').then((plantAsset) => {
Expand Down
44 changes: 38 additions & 6 deletions library/farmosUtil/farmosUtil.seeding.unit.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Test the seeding log functions', () => {

it('Create a tray seeding log', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.wrap(
Expand All @@ -60,7 +60,7 @@ describe('Test the seeding log functions', () => {
expect(result.attributes.timestamp).to.contain('1999-01-02');
expect(result.attributes.purchase_date).to.contain('1999-01-02');

expect(result.attributes.name).to.equal(plantAsset.attributes.name);
expect(result.attributes.name).to.equal('1999-01-02_ts_ARUGULA');

expect(result.attributes.status).to.equal('done');
expect(result.attributes.is_movement).to.equal(true);
Expand Down Expand Up @@ -90,7 +90,7 @@ describe('Test the seeding log functions', () => {

it('Create a direct seeding log w/ beds', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.wrap(
Expand All @@ -116,7 +116,7 @@ describe('Test the seeding log functions', () => {
expect(result.attributes.timestamp).to.contain('1999-01-02');
expect(result.attributes.purchase_date).to.contain('1999-01-02');

expect(result.attributes.name).to.equal(plantAsset.attributes.name);
expect(result.attributes.name).to.equal('1999-01-02_ds_ARUGULA');

expect(result.attributes.status).to.equal('done');
expect(result.attributes.is_movement).to.equal(true);
Expand Down Expand Up @@ -151,13 +151,45 @@ describe('Test the seeding log functions', () => {
);
});

it('Create a cover crop seeding log', () => {
cy.wrap(
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.wrap(
farmosUtil.createStandardQuantity('count', 7, 'testLabel', 'TRAYS')
).as('quantity');

cy.getAll(['@plantAsset', '@quantity']).then(([plantAsset, quantity]) => {
cy.wrap(
farmosUtil.createSeedingLog(
'01/02/1999',
'CHUAU',
[],
['seeding', 'seeding_cover_crop'],
plantAsset,
[quantity]
)
).as('seedingLog');
});

cy.get('@seedingLog').then((seedingLog) => {
cy.wrap(farmosUtil.getSeedingLog(seedingLog.id)).then((result) => {
expect(result.attributes.timestamp).to.contain('1999-01-02');
expect(result.attributes.purchase_date).to.contain('1999-01-02');

expect(result.attributes.name).to.equal('1999-01-02_cs_ARUGULA');
});
});
});

it('Error creating seeding log', { retries: 4 }, () => {
cy.intercept('POST', '**/api/log/seeding', {
statusCode: 401,
});

cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.get('@plantAsset').then((plantAsset) => {
Expand All @@ -184,7 +216,7 @@ describe('Test the seeding log functions', () => {

it('Delete a seeding log', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.wrap(
Expand Down
12 changes: 6 additions & 6 deletions library/farmosUtil/farmosUtil.soil.unit.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('Test the soil disturbance activity log functions', () => {

it('Create a soil disturbance activity log for a field', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.wrap(
Expand Down Expand Up @@ -80,7 +80,7 @@ describe('Test the soil disturbance activity log functions', () => {
cy.wrap(farmosUtil.getSoilDisturbanceActivityLog(soilLog.id)).then(
(result) => {
expect(result.type).to.equal('log--activity');
expect(result.attributes.name).to.equal(plantAsset.attributes.name);
expect(result.attributes.name).to.equal('1999-01-02_sd_A');
expect(result.attributes.timestamp).to.contain('1999-01-02');
expect(result.attributes.status).to.equal('done');
expect(result.attributes.is_movement).to.equal(false);
Expand Down Expand Up @@ -119,7 +119,7 @@ describe('Test the soil disturbance activity log functions', () => {

it('Create a soil disturbance activity log for a Greenhouse w/ beds', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.wrap(
Expand Down Expand Up @@ -157,7 +157,7 @@ describe('Test the soil disturbance activity log functions', () => {
cy.wrap(farmosUtil.getSoilDisturbanceActivityLog(soilLog.id)).then(
(result) => {
expect(result.type).to.equal('log--activity');
expect(result.attributes.name).to.equal(plantAsset.attributes.name);
expect(result.attributes.name).to.equal('1999-01-02_sd_CHUAU');
expect(result.attributes.timestamp).to.contain('1999-01-02');
expect(result.attributes.status).to.equal('done');
expect(result.attributes.is_movement).to.equal(false);
Expand Down Expand Up @@ -209,7 +209,7 @@ describe('Test the soil disturbance activity log functions', () => {
});

cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.get('@plantAsset').then((plantAsset) => {
Expand Down Expand Up @@ -238,7 +238,7 @@ describe('Test the soil disturbance activity log functions', () => {

it('Delete a soil disturbance activity log', () => {
cy.wrap(
farmosUtil.createPlantAsset('testPlant', 'ARUGULA', 'testComment')
farmosUtil.createPlantAsset('1999-01-02', 'ARUGULA', 'testComment')
).as('plantAsset');

cy.get('@plantAsset').then((plantAsset) => {
Expand Down
10 changes: 5 additions & 5 deletions library/farmosUtil/farmosUtil.transaction.unit.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,12 @@ describe('Test the plant asset functions', () => {
cropName: 'ARUGULA',
comment: 'test comment',
};
const assetName = 'test asset';

const createPlantAsset = {
name: 'createPlantAsset',
do: async () => {
return await farmosUtil.createPlantAsset(
assetName,
'1999-01-02',
formData.cropName,
formData.comment
);
Expand All @@ -139,7 +138,9 @@ describe('Test the plant asset functions', () => {
cy.wrap(farmosUtil.runTransaction(ops)).as('result');

cy.get('@result').then((result) => {
expect(result.createPlantAsset.attributes.name).to.equal(assetName);
expect(result.createPlantAsset.attributes.name).to.equal(
'1999-01-02_ARUGULA'
);
});
});

Expand All @@ -148,13 +149,12 @@ describe('Test the plant asset functions', () => {
cropName: 'WATERMELON',
comment: 'test comment',
};
const assetName = 'test asset';

const createPlantAsset = {
name: 'createPlantAsset',
do: async () => {
return await farmosUtil.createPlantAsset(
assetName,
'1999-01-02',
formData.cropName,
formData.comment
);
Expand Down
Loading

0 comments on commit c09f998

Please sign in to comment.