diff --git a/api/src/repositories/code-repository.ts b/api/src/repositories/code-repository.ts
index 615516c853..07c079cda4 100644
--- a/api/src/repositories/code-repository.ts
+++ b/api/src/repositories/code-repository.ts
@@ -62,7 +62,7 @@ export class CodeRepository extends BaseRepository {
SELECT
method_lookup_id as id,
name,
- description
+ description
FROM method_lookup
ORDER BY name ASC;
`;
diff --git a/app/src/features/surveys/sampling-information/techniques/components/general-information/TechniqueGeneralInformationForm.tsx b/app/src/features/surveys/sampling-information/techniques/components/general-information/TechniqueGeneralInformationForm.tsx
index 9decbb3db1..e4b74c7d62 100644
--- a/app/src/features/surveys/sampling-information/techniques/components/general-information/TechniqueGeneralInformationForm.tsx
+++ b/app/src/features/surveys/sampling-information/techniques/components/general-information/TechniqueGeneralInformationForm.tsx
@@ -30,11 +30,15 @@ export const TechniqueGeneralInformationForm = <
}, [codesContext.codesDataLoader]);
const methodOptions: ISelectWithSubtextFieldOption[] =
- codesContext.codesDataLoader.data?.sample_methods.map((option) => ({
- value: option.id,
- label: option.name,
- subText: option.description
- })) ?? [];
+ codesContext.codesDataLoader.data?.sample_methods
+ .map((option) => ({
+ value: option.id,
+ label: option.name,
+ subText: option.description
+ }))
+ // TODO https://apps.nrs.gov.bc.ca/int/jira/browse/SIMSBIOHUB-615 - Replace filter with more generic solution
+ // Undetermined is a possible option, but filter from the list to discourage its use
+ .filter((option) => option.label.toLowerCase() !== 'undetermined') ?? [];
if (!codesContext.codesDataLoader.data) {
return ;
diff --git a/database/src/migrations/20240911000011_method_lookup_updates.ts b/database/src/migrations/20240911000011_method_lookup_updates.ts
new file mode 100644
index 0000000000..de58f1d500
--- /dev/null
+++ b/database/src/migrations/20240911000011_method_lookup_updates.ts
@@ -0,0 +1,203 @@
+import { Knex } from 'knex';
+
+/**
+ * Update method_lookup values and associated attributes for SPI ETL.
+ *
+ * @export
+ * @param {Knex} knex
+ * @return {*} {Promise}
+ */
+export async function up(knex: Knex): Promise {
+ await knex.raw(`
+ SET SEARCH_PATH=biohub;
+
+ ----------------------------------------------------------------------------------------
+ -- Allow method lookup options to be soft deleted
+ ----------------------------------------------------------------------------------------
+ ALTER TABLE method_lookup ADD COLUMN record_end_date DATE;
+ ALTER TABLE method_lookup ADD COLUMN record_effective_date DATE DEFAULT now();
+
+ COMMENT ON COLUMN method_lookup.record_end_date IS 'Record level end date.';
+ COMMENT ON COLUMN method_lookup.record_effective_date IS 'Record level effective date.';
+
+ CREATE OR REPLACE VIEW biohub_dapi_v1.method_lookup AS SELECT * FROM biohub.method_lookup;
+
+ ----------------------------------------------------------------------------------------
+ -- Insert new method lookup values
+ ----------------------------------------------------------------------------------------
+ INSERT INTO method_lookup (name, description)
+ VALUES
+ ('Drone', 'Detecting species using cameras or sensors mounted to a drone.'),
+ ('Hair snag', 'Detecting species using barbs or similar devices that collect species hair or fur.'),
+ ('Undetermined', 'Insufficient information to determine the method.'),
+ ('Audio encounter', 'Detecting species by songs, calls, or other noises made by the species.');
+
+ ----------------------------------------------------------------------------------------
+ -- Insert quantitative attributes for the new method lookup values
+ ----------------------------------------------------------------------------------------
+ INSERT INTO technique_attribute_quantitative (name, description)
+ VALUES ('Altitude', 'Elevation above sea level.');
+
+ INSERT INTO method_lookup_attribute_quantitative (technique_attribute_quantitative_id, method_lookup_id, min, max, unit)
+ VALUES
+ (
+ (SELECT technique_attribute_quantitative_id FROM technique_attribute_quantitative WHERE name = 'Altitude'),
+ (SELECT method_lookup_id FROM method_lookup WHERE name = 'Drone'),
+ 0,
+ 10000,
+ 'meter'
+ ),
+ (
+ (SELECT technique_attribute_quantitative_id FROM technique_attribute_quantitative WHERE name = 'Height above ground'),
+ (SELECT method_lookup_id FROM method_lookup WHERE name = 'Hair snag'),
+ 0,
+ 1000,
+ 'centimeter'
+ );
+
+ ----------------------------------------------------------------------------------------
+ -- Insert qualitative attributes for the new method lookup values
+ ----------------------------------------------------------------------------------------
+ INSERT INTO technique_attribute_qualitative (name, description)
+ VALUES
+ ('Camera type', 'The type of camera mounted on the drone, such as RGB, thermal, or multispectral.'),
+ ('Trap type', 'The specific design or material of the hair snagging device.');
+
+ INSERT INTO method_lookup_attribute_qualitative (technique_attribute_qualitative_id, method_lookup_id)
+ VALUES
+ (
+ (SELECT technique_attribute_qualitative_id FROM technique_attribute_qualitative WHERE name = 'Camera type'),
+ (SELECT method_lookup_id FROM method_lookup WHERE name = 'Drone')
+ ),
+ (
+ (SELECT technique_attribute_qualitative_id FROM technique_attribute_qualitative WHERE name = 'Trap type'),
+ (SELECT method_lookup_id FROM method_lookup WHERE name = 'Hair snag')
+ );
+
+ INSERT INTO method_lookup_attribute_qualitative_option (method_lookup_attribute_qualitative_id, name, description)
+ VALUES
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Camera type' AND ml.name = 'Drone'
+ ),
+ 'RGB',
+ 'Captures images in the visible light spectrum using three color channels (red, green, blue).'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Camera type' AND ml.name = 'Drone'
+ ),
+ 'Thermal',
+ 'Captures infrared radiation emitted by objects.'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Camera type' AND ml.name = 'Drone'
+ ),
+ 'Multispectral',
+ 'Captures data across a limited number of spectral bands (typically between 3 and 15 bands) in the electromagnetic spectrum.'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Camera type' AND ml.name = 'Drone'
+ ),
+ 'Hyperspectral',
+ 'Captures data across numerous spectral bands, providing continuous coverage of a broad spectral range.'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Camera type' AND ml.name = 'Drone'
+ ),
+ 'LiDAR',
+ 'Uses laser pulses to measure distances to the Earth''s surface and other objects.'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Trap type' AND ml.name = 'Hair snag'
+ ),
+ 'Barbed wire',
+ 'A barbed wire used to collect hair from passing species.'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Trap type' AND ml.name = 'Hair snag'
+ ),
+ 'Adhesive strip',
+ 'A sticky strip used to collect hair from passing species.'
+ ),
+ (
+ (
+ SELECT method_lookup_attribute_qualitative_id
+ FROM method_lookup_attribute_qualitative mlaq
+ INNER JOIN technique_attribute_qualitative taq ON taq.technique_attribute_qualitative_id = mlaq.technique_attribute_qualitative_id
+ INNER JOIN method_lookup ml ON ml.method_lookup_id = mlaq.method_lookup_id
+ WHERE taq.name = 'Trap type' AND ml.name = 'Hair snag'
+ ),
+ 'Brush',
+ 'A brush used to collect hair from passing species.'
+ );
+
+ ----------------------------------------------------------------------------------------
+ -- Drop the radio signal tower option and reassign existing data to the radar option
+ ----------------------------------------------------------------------------------------
+
+ -- Reassign existing attributes for radio signal tower to the radar option
+ UPDATE method_technique
+ SET method_lookup_id = (SELECT method_lookup_id FROM method_lookup WHERE name = 'Radar')
+ WHERE method_lookup_id = (SELECT method_lookup_id FROM method_lookup WHERE name = 'Radio signal tower');
+
+ UPDATE method_lookup_attribute_qualitative
+ SET method_lookup_id = (SELECT method_lookup_id FROM method_lookup WHERE name = 'Radar')
+ WHERE method_lookup_id = (SELECT method_lookup_id FROM method_lookup WHERE name = 'Radio signal tower');
+
+ UPDATE method_lookup_attribute_quantitative
+ SET method_lookup_id = (SELECT method_lookup_id FROM method_lookup WHERE name = 'Radar')
+ WHERE method_lookup_id = (SELECT method_lookup_id FROM method_lookup WHERE name = 'Radio signal tower');
+
+ DELETE FROM method_lookup
+ WHERE name = 'Radio signal tower';
+
+ UPDATE technique_attribute_quantitative
+ SET name = 'Frequency',
+ description = 'The frequency at which a signal is transmitted or received.'
+ WHERE name = 'Radio frequency';
+
+ ----------------------------------------------------------------------------------------
+ -- Insert new subcount sign option
+ ----------------------------------------------------------------------------------------
+ INSERT INTO biohub.observation_subcount_sign (name, description)
+ VALUES ('Rub or scratch mark', 'A rubbing or scratch mark created by a species');
+ `);
+}
+
+export async function down(knex: Knex): Promise {
+ await knex.raw(``);
+}