diff --git a/dist/db.sample.tar.gz b/dist/db.sample.tar.gz index 1580cb0..7c2965f 100644 Binary files a/dist/db.sample.tar.gz and b/dist/db.sample.tar.gz differ diff --git a/src/sampleDB/addCrops.js b/src/sampleDB/addCrops.js index b53bc4e..c772c1d 100644 --- a/src/sampleDB/addCrops.js +++ b/src/sampleDB/addCrops.js @@ -3,7 +3,8 @@ import * as farmosUtil from "../library/farmosUtil/farmosUtil.js"; import { basename, dirname } from "path"; import { fileURLToPath } from "url"; -import { LocalStorage } from 'node-localstorage'; +import { LocalStorage } from "node-localstorage"; +import { symlinkSync } from "fs"; /* * Set the name of the CSV file to be processed and the @@ -28,7 +29,7 @@ const pass = "admin"; * Get a local storage object that we'll use to simulate the * browser's localStorage and sessionStorage when running in node. */ -let ls = new LocalStorage('scratch'); +let ls = new LocalStorage("scratch"); /* * Get a fully initialized and logged in instance of the farmOS.js @@ -39,7 +40,8 @@ const farm = await farmosUtil.getFarmOSInstance(URL, client, user, pass, ls); /* * Get any farmos id maps that we need for processing the data. */ -//const usernameMap = await farmosUtil.getUsernameToUserMap(farm); +farmosUtil.clearCachedUnits(); +const unitMap = await farmosUtil.getUnitToTermMap(); /* * Kick off the the pipeline that reads the csv file and passes @@ -83,6 +85,12 @@ async function processRow(row) { console.log( " Adding crop " + row[1] + " to crop family " + cropFamilyName + "..." ); + + const harvestUnit = await getHarvestUnit(row, 2); + const unitConversions = getUnitConversions(row, 3); + + + const crop = farm.term.create({ type: "taxonomy_term--plant_type", attributes: { @@ -92,6 +100,8 @@ async function processRow(row) { type: "taxonomy_term--crop_family", id: cropFamilyId, }, + fd2_harvest_unit: harvestUnit, + fd2_unit_conversions: unitConversions, }); try { @@ -107,15 +117,19 @@ async function processRow(row) { } else if (row[2] != "") { console.log( " Adding crop " + - parentCropName + - "-" + - row[2] + + parentCropName + + "-" + + row[2] + " to crop family " + cropFamilyName + " with parent crop " + parentCropName + "..." ); + + const harvestUnit = await getHarvestUnit(row, 3); + const unitConversions = getUnitConversions(row, 4); + const crop = farm.term.create({ type: "taxonomy_term--plant_type", attributes: { @@ -125,6 +139,8 @@ async function processRow(row) { type: "taxonomy_term--crop_family", id: cropFamilyId, }, + fd2_harvest_unit: harvestUnit, + fd2_unit_conversions: unitConversions, }); crop.relationships.parent.push({ type: "taxonomy_term--plant_type", @@ -145,3 +161,43 @@ async function processRow(row) { process.exit(1); } } + +async function getHarvestUnit(row, index) { + const harvestUnitName = row[index]; + console.log(" Getting harvest unit " + harvestUnitName + "..."); + let harvestUnit = unitMap.get(harvestUnitName); + if (!harvestUnit) { + harvestUnit = await makeUnit(harvestUnitName); + } + + const unit = { + type: "taxonomy_term--unit", + id: harvestUnit.id + }; + + console.log(" Gotten."); + + return unit; +} + +function getUnitConversions(row, startIndex) { + console.log(" Getting harvest unit conversions..."); + + const unitConversions = []; + while (row[startIndex]) { + const unitName= row[startIndex]; + const unitConversion = { + type: "taxonomy_term--unit", + id: unitMap.get(unitName).id, + meta: { + factor: Number(row[startIndex + 1]), + }, + } + + unitConversions.push(unitConversion); + startIndex += 2; + } + console.log(" Gotten."); + + return unitConversions; +} diff --git a/src/sampleDB/addUnits.js b/src/sampleDB/addUnits.js new file mode 100644 index 0000000..2b2a47f --- /dev/null +++ b/src/sampleDB/addUnits.js @@ -0,0 +1,104 @@ +import { processCsvFile } from "../library/cvsUtil/csvUtil.js"; +import * as farmosUtil from "../library/farmosUtil/farmosUtil.js"; + +import { basename, dirname } from "path"; +import { fileURLToPath } from "url"; +import { LocalStorage } from "node-localstorage"; +import { symlinkSync } from "fs"; + +/* + * Set the name of the CSV file to be processed and the + * messages to be printed before and after processing here. + * The CSV file is assumed to be in the sampleData directory. + */ +const csv_file = "units.csv"; +const startMsg = "Adding units from " + csv_file + "..."; +const endMsg = "Units added."; + +/* + * Setup the information for connecting to the farmOS instance + * in the FarmData2 development environment. Note: URL cannot + * have a trailing /. + */ +const URL = "http://farmos"; +const client = "farm"; +const user = "admin"; +const pass = "admin"; + +/* + * Get a local storage object that we'll use to simulate the + * browser's localStorage and sessionStorage when running in node. + */ +let ls = new LocalStorage("scratch"); + +/* + * Get a fully initialized and logged in instance of the farmOS.js + * farmOS object that will be used to write assets, logs, etc. + */ +const farm = await farmosUtil.getFarmOSInstance(URL, client, user, pass, ls); + +/* + * Get any farmos id maps that we need for processing the data. + */ +farmosUtil.clearCachedUnits(); +const unitMap = await farmosUtil.getUnitToTermMap(); + +/* + * Kick off the the pipeline that reads the csv file and passes + * each row of data from the file to the processRow function. + */ +const data_file = + dirname(fileURLToPath(import.meta.url)) + "/sampleData/" + csv_file; +processCsvFile(data_file, processRow, startMsg, endMsg); + +let unitCategoryId = null; +let unitCategoryName = null; + +/* + * Implement this function to processes each row of the CSV file. + * The contents of the row arrive as an array with each entry being + * a column from the line of the CSV file. + */ +async function processRow(row) { + if (row[0] != "") { + if (unitMap.get(row[0])) { + console.log(" Unit category " + row[0] + " already exists."); + } + else { + console.log(" Adding unit category " + row[0] + "..."); + await makeUnit(row[0],row[1]); + console.log(" Added."); + } + unitCategoryId = unitMap.get(row[0]).id; + unitCategoryName = row[0]; + } else if (row[1] != "") { + console.log( + " Adding unit " + row[1] + " to unit category " + unitCategoryName + "..."); + await makeUnit(row[1],row[2],unitCategoryId); + console.log(" Added."); + } +} + +async function makeUnit(unitName, description, parentId=null) { + const unit = farm.term.create({ + type: "taxonomy_term--unit", + attributes: { + name: unitName, + description: description, + }, + }); + + if (parentId) { + unit.relationships.parent.push({id: parentId, type: "taxonomy_term--unit"}); + } + + try { + const result = await farm.term.send(unit); + unitMap.set(unitName,result); + return result.id; + } catch (e) { + console.log("API error sending unit " + unitName); + console.log(e); + process.exit(1); + } +} diff --git a/src/sampleDB/buildSampleDB.bash b/src/sampleDB/buildSampleDB.bash index 338485c..f7230f1 100755 --- a/src/sampleDB/buildSampleDB.bash +++ b/src/sampleDB/buildSampleDB.bash @@ -53,6 +53,11 @@ node "$SCRIPT_DIR/addAreas.js" error_check echo "" +# Add units +node "$SCRIPT_DIR/addUnits.js" +error_check +echo "" + # Add the crop families and crops node "$SCRIPT_DIR/addCrops.js" error_check diff --git a/src/sampleDB/sampleData/crops.csv b/src/sampleDB/sampleData/crops.csv index 6517e44..541156e 100644 --- a/src/sampleDB/sampleData/crops.csv +++ b/src/sampleDB/sampleData/crops.csv @@ -23,13 +23,14 @@ # (e.g. BEANS-DRY, CORN-DRY) # # The line for each crop contains a comma delimited list with the following: -# - default units -# - a list of conversions for the crop (if any), each with 3 values: +# - default harvest units +# - a list of conversions for the crop (if any), each with 2 values: # - new units - the name of the unit to convert to from the default. # - factor - the conversion factor. # - default value * factor = quantity in new unit. +# NOTE: Units used for the harvest unit or the new units must appear in units.csv. # -# Crop families appear in farmOS in the oder listed in this file. +# Crop families appear in farmOS in the order listed in this file. # Crops appear in farmOS in alphabetical order in their families or overall. # # Any line starting with # is a comment. diff --git a/src/sampleDB/sampleData/units.csv b/src/sampleDB/sampleData/units.csv new file mode 100644 index 0000000..e79b8e6 --- /dev/null +++ b/src/sampleDB/sampleData/units.csv @@ -0,0 +1,25 @@ +# Sample Data for units. +# Note: Required units are created by farm_fd2.install in the farm_fd2 module. +# The units created here would not necessarily exits in all FD2 instances. +# +# Format: +# +# Each line represents either a unit category or a unit +# - Lines with no leading comma represent a unit category. +# - Unit categories that do not exist in farm_fd2.install will be created. +# - Lines with a leading comma represent a child unit of +# - the most recent unit category. +# +# Anything following a # on a line is a considered a comment. +# Thus, names and descriptions cannot contain # +# Blank Lines are ignored. +# +# Units are created as taxonomy_term--unit terms. + +Count,Already exists in farm_fd2.install +,BUNCH,A number of bunches. +,EACH,A number of items. +,HEAD,A number of heads. +,TRAY,A number of trays. +Weight,A parent term for units that are weights. +,POUND,A number of pounds.