diff --git a/api/src/database-models/vantage.ts b/api/src/database-models/vantage.ts index 9831b51213..013bde42d6 100644 --- a/api/src/database-models/vantage.ts +++ b/api/src/database-models/vantage.ts @@ -6,7 +6,8 @@ import { z } from 'zod'; * @description Data model for `vantage`. */ export const VantageModel = z.object({ - vantage_mode_category_id: z.number(), + vantage_id: z.number(), + vantage_category_id: z.number(), name: z.string(), description: z.string().nullable(), record_end_date: z.string().nullable(), diff --git a/api/src/database-models/vantage_category.ts b/api/src/database-models/vantage_category.ts new file mode 100644 index 0000000000..9440b0865c --- /dev/null +++ b/api/src/database-models/vantage_category.ts @@ -0,0 +1,35 @@ +import { z } from 'zod'; + +/** + * Vantage category model. + * + * @description Data model for `vantage_category`. + */ +export const VantageCategoryModel = z.object({ + vantage_category_id: z.number(), + name: z.string(), + description: z.string().nullable(), + record_end_date: z.string().nullable(), + create_date: z.string(), + create_user: z.number(), + update_date: z.string().nullable(), + update_user: z.number().nullable(), + revision_count: z.number() +}); + +export type VantageCategoryModel = z.infer; + +/** + * Vantage Category Record. + * + * @description Data record for `vantage_category`. + */ +export const VantageCategory = VantageCategoryModel.omit({ + create_date: true, + create_user: true, + update_date: true, + update_user: true, + revision_count: true +}); + +export type VantageCategory = z.infer; diff --git a/api/src/database-models/vantage_method.ts b/api/src/database-models/vantage_method.ts new file mode 100644 index 0000000000..7fe10a585f --- /dev/null +++ b/api/src/database-models/vantage_method.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; + +/** + * Vantage Method Model. + * + * @description Data model for `vantage_method`. + */ +export const VantageMethodModel = z.object({ + vantage_method_id: z.number(), + vantage_id: z.number(), + method_lookup_id: z.number(), + description: z.string().nullable(), + record_end_date: z.string().nullable(), + create_date: z.string(), + create_user: z.number(), + update_date: z.string().nullable(), + update_user: z.number().nullable(), + revision_count: z.number() +}); + +export type VantageMethodModel = z.infer; + +/** + * Vantage Method Record. + * + * @description Data record for `vantage_method`. + */ +export const VantageMethodRecord = VantageMethodModel.omit({ + create_date: true, + create_user: true, + update_date: true, + update_user: true, + revision_count: true +}); + +export type VantageMethodRecord = z.infer; diff --git a/api/src/database-models/vantage_mode.ts b/api/src/database-models/vantage_mode.ts deleted file mode 100644 index 837d78e22f..0000000000 --- a/api/src/database-models/vantage_mode.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { z } from 'zod'; - -/** - * Vantage Mode Model. - * - * @description Data model for `vantage_mode`. - */ -export const VantageModeModel = z.object({ - vantage_mode_id: z.number(), - vantage_mode_category_id: z.number(), - name: z.string(), - description: z.string().nullable(), - record_end_date: z.string().nullable(), - create_date: z.string(), - create_user: z.number(), - update_date: z.string().nullable(), - update_user: z.number().nullable(), - revision_count: z.number() -}); - -export type VantageModeModel = z.infer; - -/** - * Vantage Mode Record. - * - * @description Data record for `vantage_mode`. - */ -export const VantageModeRecord = VantageModeModel.omit({ - create_date: true, - create_user: true, - update_date: true, - update_user: true, - revision_count: true -}); - -export type VantageModeRecord = z.infer; diff --git a/api/src/database-models/vantage_mode_method.ts b/api/src/database-models/vantage_mode_method.ts deleted file mode 100644 index 5981a88dcc..0000000000 --- a/api/src/database-models/vantage_mode_method.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { z } from 'zod'; - -/** - * Vantage Mode Method Model. - * - * @description Data model for `vantage_mode_method`. - */ -export const VantageModeMethodModel = z.object({ - vantage_mode_method_id: z.number(), - vantage_mode_id: z.number(), - method_lookup_id: z.number(), - description: z.string().nullable(), - record_end_date: z.string().nullable(), - create_date: z.string(), - create_user: z.number(), - update_date: z.string().nullable(), - update_user: z.number().nullable(), - revision_count: z.number() -}); - -export type VantageModeMethodModel = z.infer; - -/** - * Vantage Mode Method Record. - * - * @description Data record for `vantage_mode_method`. - */ -export const VantageModeMethodRecord = VantageModeMethodModel.omit({ - create_date: true, - create_user: true, - update_date: true, - update_user: true, - revision_count: true -}); - -export type VantageModeMethodRecord = z.infer; diff --git a/api/src/openapi/schemas/technique.ts b/api/src/openapi/schemas/technique.ts index 8cb1994393..c6f8066018 100644 --- a/api/src/openapi/schemas/technique.ts +++ b/api/src/openapi/schemas/technique.ts @@ -83,18 +83,18 @@ export const techniqueVantagesSchema: OpenAPIV3.SchemaObject = { description: 'Vantages from which a method is done, like water, air, or ground.', items: { type: 'object', - required: ['vantage_mode_method_id', 'vantage_mode_category_id'], + required: ['vantage_method_id', 'vantage_category_id'], additionalProperties: false, properties: { - method_technique_vantage_mode_id: { + method_technique_vantage_id: { type: 'integer', minimum: 1 }, - vantage_mode_method_id: { + vantage_method_id: { type: 'integer', minimum: 1 }, - vantage_mode_category_id: { + vantage_category_id: { type: 'integer', minimum: 1 } @@ -133,7 +133,7 @@ export const techniqueCreateSchema: OpenAPIV3.SchemaObject = { 'distance_threshold', 'attractants', 'attributes', - 'vantage_mode_methods' + 'vantage_methods' ], additionalProperties: false, properties: { @@ -158,7 +158,7 @@ export const techniqueCreateSchema: OpenAPIV3.SchemaObject = { }, attractants: techniqueAttractantsSchema, attributes: techniqueAttributesSchema, - vantage_mode_methods: techniqueVantagesSchema + vantage_methods: techniqueVantagesSchema } }; @@ -191,11 +191,11 @@ export const vantageReferenceRecordsSchema: OpenAPIV3.SchemaObject = { description: 'Vantage reference records.', items: { type: 'object', - description: 'Vantage reference record and its associated vantage modes.', - required: ['vantage_mode_category_id', 'name', 'description', 'vantage_modes'], + description: 'Vantage category reference record and its associated vantages.', + required: ['vantage_category_id', 'name', 'description', 'vantages'], additionalProperties: false, properties: { - vantage_mode_category_id: { + vantage_category_id: { type: 'integer', minimum: 1 }, @@ -206,29 +206,29 @@ export const vantageReferenceRecordsSchema: OpenAPIV3.SchemaObject = { type: 'string', nullable: true }, - vantage_modes: { + vantages: { type: 'array', - description: 'Supported vantage mode for the vantage record.', + description: 'Supported vantage for the vantage record.', items: { type: 'object', - required: ['vantage_mode_method_id', 'name', 'vantage_mode_category_id', 'description'], + required: ['vantage_method_id', 'name', 'vantage_id', 'description'], additionalProperties: false, properties: { - vantage_mode_method_id: { + vantage_method_id: { type: 'integer', - description: 'The primary key of the vantage mode option.' + description: 'The primary key of the vantage method option.' }, - vantage_mode_category_id: { + vantage_id: { type: 'integer', - description: 'The vantage of the mode.' + description: 'The vantage of the record' }, name: { type: 'string', - description: 'The name of the vantage mode option.' + description: 'The name of the vantage method option.' }, description: { type: 'string', - description: 'The description of the mode option.' + description: 'The description of the vantage method option.' } } } diff --git a/api/src/paths/codes.ts b/api/src/paths/codes.ts index ebbf556be8..a881e7eadd 100644 --- a/api/src/paths/codes.ts +++ b/api/src/paths/codes.ts @@ -407,7 +407,7 @@ GET.apiDoc = { }, vantages: { type: 'array', - description: 'Vantages that vantage modes belong to.', + description: 'Vantages that vantages belong to.', items: { type: 'object', additionalProperties: false, diff --git a/api/src/paths/project/{projectId}/survey/{surveyId}/technique/index.test.ts b/api/src/paths/project/{projectId}/survey/{surveyId}/technique/index.test.ts index e1800102f0..50d9ca9776 100644 --- a/api/src/paths/project/{projectId}/survey/{surveyId}/technique/index.test.ts +++ b/api/src/paths/project/{projectId}/survey/{surveyId}/technique/index.test.ts @@ -55,9 +55,9 @@ describe('createTechniques', () => { attractant_lookup_id: 111 } ], - vantage_mode_methods: [ - { vantage_mode_method_id: 101, description: 'Mode 1' }, - { vantage_mode_method_id: 102, description: 'Mode 2' } + vantage_methods: [ + { vantage_method_id: 101, description: 'Mode 1' }, + { vantage_method_id: 102, description: 'Mode 2' } ] } ] @@ -118,9 +118,9 @@ describe('createTechniques', () => { attractant_lookup_id: 111 } ], - vantage_mode_methods: [ - { vantage_mode_method_id: 101, description: 'Mode 1' }, - { vantage_mode_method_id: 102, description: 'Mode 2' } + vantage_methods: [ + { vantage_method_id: 101, description: 'Mode 1' }, + { vantage_method_id: 102, description: 'Mode 2' } ] } ] @@ -181,16 +181,16 @@ describe('getTechniques', () => { } ] }, - vantage_mode_methods: [ + vantage_methods: [ { - method_technique_vantage_mode_id: 1, - vantage_mode_method_id: 101, - vantage_mode_category_id: 2 + method_technique_vantage_id: 1, + vantage_method_id: 101, + vantage_category_id: 2 }, { - method_technique_vantage_mode_id: 2, - vantage_mode_method_id: 102, - vantage_mode_category_id: 1 + method_technique_vantage_id: 2, + vantage_method_id: 102, + vantage_category_id: 1 } ] }; @@ -254,16 +254,16 @@ describe('getTechniques', () => { } ] }, - vantage_mode_methods: [ + vantage_methods: [ { - method_technique_vantage_mode_id: 1, - vantage_mode_method_id: 101, - vantage_mode_category_id: 2 + method_technique_vantage_id: 1, + vantage_method_id: 101, + vantage_category_id: 2 }, { - method_technique_vantage_mode_id: 2, - vantage_mode_method_id: 102, - vantage_mode_category_id: 1 + method_technique_vantage_id: 2, + vantage_method_id: 102, + vantage_category_id: 1 } ] }; diff --git a/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.test.ts b/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.test.ts index 9ab382dee5..00b8b1aef2 100644 --- a/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.test.ts +++ b/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.test.ts @@ -160,9 +160,9 @@ describe('updateTechnique', () => { attractant_lookup_id: 111 } ], - vantage_mode_methods: [ - { vantage_mode_method_id: 101, description: 'Mode 1' }, - { vantage_mode_method_id: 102, description: 'Mode 2' } + vantage_methods: [ + { vantage_method_id: 101, description: 'Mode 1' }, + { vantage_method_id: 102, description: 'Mode 2' } ] } }; @@ -231,9 +231,9 @@ describe('updateTechnique', () => { attractant_lookup_id: 111 } ], - vantage_mode_methods: [ - { vantage_mode_method_id: 101, description: 'Mode 1' }, - { vantage_mode_method_id: 102, description: 'Mode 2' } + vantage_methods: [ + { vantage_method_id: 101, description: 'Mode 1' }, + { vantage_method_id: 102, description: 'Mode 2' } ] } }; @@ -254,8 +254,8 @@ describe('updateTechnique', () => { .stub(TechniqueAttributeService.prototype, 'insertUpdateDeleteQuantitativeAttributesForTechnique') .resolves(); - const updateVantageModesForTechniqueStub = sinon - .stub(TechniqueVantageService.prototype, 'updateVantageModesForTechnique') + const updateVantagesForTechniqueStub = sinon + .stub(TechniqueVantageService.prototype, 'updateVantagesForTechnique') .resolves(); const requestHandler = updateTechnique(); @@ -280,11 +280,7 @@ describe('updateTechnique', () => { 3, requestBody.technique.attributes.quantitative_attributes ); - expect(updateVantageModesForTechniqueStub).to.have.been.calledOnceWith( - 2, - 3, - requestBody.technique.vantage_mode_methods - ); + expect(updateVantagesForTechniqueStub).to.have.been.calledOnceWith(2, 3, requestBody.technique.vantage_methods); expect(mockRes.statusValue).to.eql(200); }); diff --git a/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.ts b/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.ts index e28e0712ae..159a66213d 100644 --- a/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.ts +++ b/api/src/paths/project/{projectId}/survey/{surveyId}/technique/{techniqueId}/index.ts @@ -246,7 +246,7 @@ export function updateTechnique(): RequestHandler { try { await connection.open(); - const { attributes, attractants, vantage_mode_methods, ...techniqueRow } = technique; + const { attributes, attractants, vantage_methods, ...techniqueRow } = technique; // Update the technique record const techniqueService = new TechniqueService(connection); @@ -272,8 +272,8 @@ export function updateTechnique(): RequestHandler { methodTechniqueId, attributes.quantitative_attributes ), - // Update vantage modes - techniqueVantageService.updateVantageModesForTechnique(surveyId, methodTechniqueId, vantage_mode_methods) + // Update vantages + techniqueVantageService.updateVantagesForTechnique(surveyId, methodTechniqueId, vantage_methods) ]); await connection.commit(); diff --git a/api/src/paths/reference/get/vantage.test.ts b/api/src/paths/reference/get/vantage.test.ts index db3ca10ab0..e6c624ccfa 100644 --- a/api/src/paths/reference/get/vantage.test.ts +++ b/api/src/paths/reference/get/vantage.test.ts @@ -4,32 +4,32 @@ import sinon from 'sinon'; import sinonChai from 'sinon-chai'; import * as db from '../../../database/db'; import { HTTPError } from '../../../errors/http-error'; -import { VantageModeService } from '../../../services/vantage-mode-service'; +import { VantageService } from '../../../services/vantage-mode-service'; import { getMockDBConnection, getRequestHandlerMocks } from '../../../__mocks__/db'; import { getVantageReferenceRecords } from './vantage'; chai.use(sinonChai); -describe('getVantageModes', () => { +describe('getVantages', () => { afterEach(() => { sinon.restore(); }); - it('should return vantage modes for method lookup ids', async () => { - const mockVantageModeResponse = [ + it('should return vantages for method lookup ids', async () => { + const mockVantageResponse = [ { - vantage_mode_category_id: 101, + vantage_category_id: 101, name: 'Vantage A', description: 'Description for vantage A', - vantage_modes: [{ vantage_mode_method_id: 1, name: 'Mode A', description: 'Description' }] + vantages: [{ vantage_method_id: 1, name: 'Mode A', description: 'Description' }] }, { - vantage_mode_category_id: 102, + vantage_category_id: 102, name: 'Vantage B', description: 'Description for vantage B', - vantage_modes: [ - { vantage_mode_method_id: 2, name: 'Mode B', description: 'Description' }, - { vantage_mode_method_id: 3, name: 'Mode C', description: 'Description' } + vantages: [ + { vantage_method_id: 2, name: 'Mode B', description: 'Description' }, + { vantage_method_id: 3, name: 'Mode C', description: 'Description' } ] } ]; @@ -43,8 +43,8 @@ describe('getVantageModes', () => { sinon.stub(db, 'getDBConnection').returns(mockDBConnection); const getVantageReferenceRecordsByMethodLookupIdsStub = sinon - .stub(VantageModeService.prototype, 'getVantageReferenceRecordsByMethodLookupIds') - .resolves(mockVantageModeResponse); + .stub(VantageService.prototype, 'getVantageReferenceRecordsByMethodLookupIds') + .resolves(mockVantageResponse); const { mockReq, mockRes, mockNext } = getRequestHandlerMocks(); mockReq.query = { methodLookupId: ['1', '2'] }; @@ -54,7 +54,7 @@ describe('getVantageModes', () => { await requestHandler(mockReq, mockRes, mockNext); expect(getVantageReferenceRecordsByMethodLookupIdsStub).to.have.been.calledOnceWith([1, 2]); - expect(mockRes.jsonValue).to.eql(mockVantageModeResponse); + expect(mockRes.jsonValue).to.eql(mockVantageResponse); expect(mockDBConnection.open).to.have.been.calledOnce; expect(mockDBConnection.commit).to.have.been.calledOnce; @@ -72,7 +72,7 @@ describe('getVantageModes', () => { sinon.stub(db, 'getDBConnection').returns(mockDBConnection); const getVantageReferenceRecordsByMethodLookupIdsStub = sinon - .stub(VantageModeService.prototype, 'getVantageReferenceRecordsByMethodLookupIds') + .stub(VantageService.prototype, 'getVantageReferenceRecordsByMethodLookupIds') .rejects(new Error('Test database error')); const { mockReq, mockRes, mockNext } = getRequestHandlerMocks(); diff --git a/api/src/paths/reference/get/vantage.ts b/api/src/paths/reference/get/vantage.ts index b7716ef3eb..0e28b1b234 100644 --- a/api/src/paths/reference/get/vantage.ts +++ b/api/src/paths/reference/get/vantage.ts @@ -2,7 +2,7 @@ import { RequestHandler } from 'express'; import { Operation } from 'express-openapi'; import { getAPIUserDBConnection } from '../../../database/db'; import { vantageReferenceRecordsSchema } from '../../../openapi/schemas/technique'; -import { VantageModeService } from '../../../services/vantage-mode-service'; +import { VantageService } from '../../../services/vantage-mode-service'; import { getLogger } from '../../../utils/logger'; const defaultLog = getLogger('paths/reference/get/vantage-mode'); @@ -68,15 +68,15 @@ export function getVantageReferenceRecords(): RequestHandler { await connection.open(); - const vantageModeService = new VantageModeService(connection); + const vantageService = new VantageService(connection); - const response = await vantageModeService.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); + const response = await vantageService.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); await connection.commit(); return res.status(200).json(response); } catch (error) { - defaultLog.error({ label: 'getVantageModes', message: 'error', error }); + defaultLog.error({ label: 'getVantages', message: 'error', error }); await connection.rollback(); throw error; } finally { diff --git a/api/src/repositories/code-repository.ts b/api/src/repositories/code-repository.ts index 19cf9fbde1..7c4dad7fe4 100644 --- a/api/src/repositories/code-repository.ts +++ b/api/src/repositories/code-repository.ts @@ -494,7 +494,7 @@ export class CodeRepository extends BaseRepository { } /** - * Fetch vantages associated with vantage modes + * Fetch vantages associated with vantages * * @return {*} * @memberof CodeRepository @@ -502,7 +502,7 @@ export class CodeRepository extends BaseRepository { async getVantages() { const sqlStatement = SQL` SELECT - vantage_mode_category_id AS id, + vantage_category_id AS id, name, description FROM vantage diff --git a/api/src/repositories/technique-repository.test.ts b/api/src/repositories/technique-repository.test.ts index b57ca934fd..b3d950b391 100644 --- a/api/src/repositories/technique-repository.test.ts +++ b/api/src/repositories/technique-repository.test.ts @@ -30,7 +30,7 @@ describe('TechniqueRepository', () => { qualitative_attributes: [], quantitative_attributes: [] }, - vantage_mode_methods: [] + vantage_methods: [] }; const mockResponse = { rows: [mockRecord], rowCount: 1 } as any as Promise>; @@ -60,7 +60,7 @@ describe('TechniqueRepository', () => { qualitative_attributes: [], quantitative_attributes: [] }, - vantage_mode_methods: [] + vantage_methods: [] }; const mockResponse = { rows: [mockRecord], rowCount: 1 } as any as Promise>; diff --git a/api/src/repositories/technique-repository.ts b/api/src/repositories/technique-repository.ts index 4829d983e9..e96d3467f0 100644 --- a/api/src/repositories/technique-repository.ts +++ b/api/src/repositories/technique-repository.ts @@ -19,7 +19,7 @@ export interface ITechniquePostData { qualitative_attributes: IQualitativeAttributePostData[]; }; attractants: IAttractantPostData[]; - vantage_mode_methods: VantagePostData[]; + vantage_methods: VantagePostData[]; } export interface ITechniquePutData extends ITechniquePostData { @@ -64,7 +64,7 @@ export const TechniqueObject = z.object({ }) ) }), - vantage_mode_methods: z.array(TechniqueVantage) + vantage_methods: z.array(TechniqueVantage) }); export type TechniqueObject = z.infer; @@ -133,19 +133,15 @@ export class TechniqueRepository extends BaseRepository { 'method_technique_id', knex.raw(` json_agg(json_build_object( - 'method_technique_vantage_mode_id', method_technique_vantage_mode.method_technique_vantage_mode_id, - 'vantage_mode_method_id', method_technique_vantage_mode.vantage_mode_method_id, - 'vantage_mode_category_id', vantage_mode.vantage_mode_category_id - )) as vantage_mode_methods + 'method_technique_vantage_id', method_technique_vantage.method_technique_vantage_id, + 'vantage_method_id', method_technique_vantage.vantage_method_id, + 'vantage_category_id', vantage.vantage_category_id + )) as vantage_methods `) ) - .from('method_technique_vantage_mode') - .join( - 'vantage_mode_method', - 'vantage_mode_method.vantage_mode_method_id', - 'method_technique_vantage_mode.vantage_mode_method_id' - ) - .join('vantage_mode', 'vantage_mode.vantage_mode_id', 'vantage_mode_method.vantage_mode_id') + .from('method_technique_vantage') + .join('vantage_method', 'vantage_method.vantage_method_id', 'method_technique_vantage.vantage_method_id') + .join('vantage', 'vantage.vantage_id', 'vantage_method.vantage_id') .groupBy('method_technique_id') ) .select( @@ -164,7 +160,7 @@ export class TechniqueRepository extends BaseRepository { )) AS attributes `), knex.raw(` - COALESCE(w_vantages.vantage_mode_methods, '[]'::json) AS vantage_mode_methods + COALESCE(w_vantages.vantage_methods, '[]'::json) AS vantage_methods `) ) .from('method_technique as mt') diff --git a/api/src/repositories/technique-vantage-repository.test.ts b/api/src/repositories/technique-vantage-repository.test.ts index 2391a565b5..195d2cad56 100644 --- a/api/src/repositories/technique-vantage-repository.test.ts +++ b/api/src/repositories/technique-vantage-repository.test.ts @@ -23,13 +23,13 @@ describe('TechniqueVantageRepository', () => { sinon.restore(); }); - describe('getVantageModesForTechnique', () => { - it('should retrieve the correct vantage modes for a technique', async () => { + describe('getVantagesForTechnique', () => { + it('should retrieve the correct vantages for a technique', async () => { const mockRecord = [ { - method_technique_vantage_mode_id: 1, + method_technique_vantage_id: 1, method_technique_id: 2, - vantage_mode_method_id: 3, + vantage_method_id: 3, description: 'test description' } ]; @@ -40,7 +40,7 @@ describe('TechniqueVantageRepository', () => { const surveyId = 1; const methodTechniqueId = 2; - const result = await repository.getVantageModesForTechnique(surveyId, methodTechniqueId); + const result = await repository.getVantagesForTechnique(surveyId, methodTechniqueId); expect(knexStub).to.have.been.calledOnce; expect(result).to.deep.equal(mockRecord); @@ -50,7 +50,7 @@ describe('TechniqueVantageRepository', () => { sinon.stub(dbConnection, 'knex').throws(new Error('Query error')); try { - await repository.getVantageModesForTechnique(1, 2); + await repository.getVantagesForTechnique(1, 2); expect.fail('Expected error to be thrown'); } catch (error) { expect((error as HTTPError).message).to.equal('Query error'); @@ -58,11 +58,11 @@ describe('TechniqueVantageRepository', () => { }); }); - describe('insertVantageModesForTechnique', () => { - it('should insert the vantage modes successfully', async () => { - const mockRecord = [{ method_technique_vantage_mode_id: 1 }]; + describe('insertVantagesForTechnique', () => { + it('should insert the vantages successfully', async () => { + const mockRecord = [{ method_technique_vantage_id: 1 }]; - const vantageModeMethods: VantagePostData[] = [{ vantage_mode_method_id: 3 }]; + const vantageMethods: VantagePostData[] = [{ vantage_method_id: 3 }]; const mockResponse = { rows: mockRecord } as QueryResult; const knexStub = sinon.stub(dbConnection, 'knex').resolves(mockResponse); @@ -70,19 +70,19 @@ describe('TechniqueVantageRepository', () => { const surveyId = 1; const methodTechniqueId = 2; - const result = await repository.insertVantageModesForTechnique(surveyId, methodTechniqueId, vantageModeMethods); + const result = await repository.insertVantagesForTechnique(surveyId, methodTechniqueId, vantageMethods); expect(knexStub).to.have.been.calledOnce; expect(result).to.deep.equal(mockRecord); }); it('should throw an error if insertion fails', async () => { - const vantageModeMethods: VantagePostData[] = [{ vantage_mode_method_id: 3 }]; + const vantageMethods: VantagePostData[] = [{ vantage_method_id: 3 }]; sinon.stub(dbConnection, 'knex').throws(new Error('Insert error')); try { - await repository.insertVantageModesForTechnique(1, 2, vantageModeMethods); + await repository.insertVantagesForTechnique(1, 2, vantageMethods); expect.fail('Expected error to be thrown'); } catch (error) { expect((error as HTTPError).message).to.equal('Insert error'); @@ -90,9 +90,9 @@ describe('TechniqueVantageRepository', () => { }); }); - describe('deleteVantageModesForTechnique', () => { - it('should delete the vantage modes successfully', async () => { - const vantageModeMethods: VantagePostData[] = [{ vantage_mode_method_id: 3 }]; + describe('deleteVantagesForTechnique', () => { + it('should delete the vantages successfully', async () => { + const vantageMethods: VantagePostData[] = [{ vantage_method_id: 3 }]; const mockResponse = { rows: [], rowCount: 0 } as any as Promise>; const knexStub = sinon.stub(dbConnection, 'knex').resolves(mockResponse); @@ -100,28 +100,28 @@ describe('TechniqueVantageRepository', () => { const surveyId = 1; const methodTechniqueId = 2; - await repository.deleteVantageModesForTechnique(surveyId, methodTechniqueId, vantageModeMethods); + await repository.deleteVantagesForTechnique(surveyId, methodTechniqueId, vantageMethods); expect(knexStub).to.have.been.calledOnce; }); it('should throw an error if deletion fails', async () => { - const vantageModeMethods: VantagePostData[] = [{ vantage_mode_method_id: 3 }]; + const vantageMethods: VantagePostData[] = [{ vantage_method_id: 3 }]; sinon.stub(dbConnection, 'knex').throws(new Error('Delete error')); try { - await repository.deleteVantageModesForTechnique(1, 2, vantageModeMethods); + await repository.deleteVantagesForTechnique(1, 2, vantageMethods); expect.fail('Expected error to be thrown'); } catch (error) { expect((error as HTTPError).message).to.equal('Delete error'); } }); - it('should do nothing if no vantage mode methods are provided', async () => { + it('should do nothing if no vantage methods are provided', async () => { const knexStub = sinon.stub(dbConnection, 'knex'); - await repository.deleteVantageModesForTechnique(1, 2, []); + await repository.deleteVantagesForTechnique(1, 2, []); expect(knexStub).to.not.have.been.called; }); diff --git a/api/src/repositories/technique-vantage-repository.ts b/api/src/repositories/technique-vantage-repository.ts index d7978e79c7..67b48215be 100644 --- a/api/src/repositories/technique-vantage-repository.ts +++ b/api/src/repositories/technique-vantage-repository.ts @@ -8,9 +8,9 @@ import { VantagePostData } from './vantage-mode-repository'; const defaultLog = getLogger('repositories/technique-vantage-repository'); export const TechniqueVantage = z.object({ - method_technique_vantage_mode_id: z.number(), - vantage_mode_method_id: z.number(), - vantage_mode_category_id: z.number() + method_technique_vantage_id: z.number(), + vantage_method_id: z.number(), + vantage_category_id: z.number() }); export type TechniqueVantage = z.infer; @@ -24,87 +24,72 @@ export type TechniqueVantage = z.infer; */ export class TechniqueVantageRepository extends BaseRepository { /** - * Get vantage modes for a technique + * Get vantages for a technique * * @param {number} surveyId * @param {number} methodTechniqueId * @return {*} Promise } - * @memberof VantageModeRepository + * @memberof VantageRepository */ - async getVantageModesForTechnique(surveyId: number, methodTechniqueId: number): Promise { - defaultLog.debug({ label: 'getVantageModesForTechnique', methodTechniqueId }); + async getVantagesForTechnique(surveyId: number, methodTechniqueId: number): Promise { + defaultLog.debug({ label: 'getVantagesForTechnique', methodTechniqueId }); const queryBuilder = getKnex() .select( - 'method_technique_vantage_mode.method_technique_vantage_mode_id', - 'method_technique_vantage_mode.vantage_mode_method_id', - 'vantage_mode.vantage_mode_category_id' + 'method_technique_vantage.method_technique_vantage_id', + 'method_technique_vantage.vantage_method_id', + 'vantage.vantage_category_id' ) - .from('method_technique_vantage_mode') - .join( - 'method_technique', - 'method_technique_vantage_mode.method_technique_id', - 'method_technique.method_technique_id' - ) - .join( - 'vantage_mode_method', - 'method_technique_vantage_mode.vantage_mode_method_id', - 'vantage_mode_method.vantage_mode_method_id' - ) - .join('vantage_mode', 'vantage_mode_method.vantage_mode_id', 'vantage_mode.vantage_mode_id') + .from('method_technique_vantage') + .join('method_technique', 'method_technique_vantage.method_technique_id', 'method_technique.method_technique_id') + .join('vantage_method', 'method_technique_vantage.vantage_method_id', 'vantage_method.vantage_method_id') + .join('vantage', 'vantage_method.vantage_id', 'vantage.vantage_id') .join('survey', 'method_technique.survey_id', 'survey.survey_id') .where('survey.survey_id', surveyId) - .where('method_technique_vantage_mode.method_technique_id', methodTechniqueId); + .where('method_technique_vantage.method_technique_id', methodTechniqueId); const response = await this.connection.knex(queryBuilder, TechniqueVantage); return response.rows; } /** - * Insert vantage modes for a technique. + * Insert vantages for a technique. * * @param {number} surveyId * @param {number} methodTechniqueId - * @param {VantagePostData[]} vantageModeMethods - * @return {*} {(Promise<{ method_technique_vantage_mode_id: number }[] | undefined>)} - * @memberof VantageModeRepository + * @param {VantagePostData[]} vantageMethods + * @return {*} {(Promise<{ method_technique_vantage_id: number }[] | undefined>)} + * @memberof VantageRepository */ - async insertVantageModesForTechnique( + async insertVantagesForTechnique( surveyId: number, methodTechniqueId: number, - vantageModeMethods: VantagePostData[] - ): Promise<{ method_technique_vantage_mode_id: number }[] | undefined> { - defaultLog.debug({ label: 'insertVantageModesForTechnique', methodTechniqueId }); + vantageMethods: VantagePostData[] + ): Promise<{ method_technique_vantage_id: number }[] | undefined> { + defaultLog.debug({ label: 'insertVantagesForTechnique', methodTechniqueId }); - if (!vantageModeMethods.length) { + if (!vantageMethods.length) { return; } const queryBuilder = getKnex() .insert( - vantageModeMethods.map((vantageModeMethodId) => ({ + vantageMethods.map((vantageMethodId) => ({ method_technique_id: methodTechniqueId, - vantage_mode_method_id: vantageModeMethodId.vantage_mode_method_id + vantage_method_id: vantageMethodId.vantage_method_id })) ) - .into('method_technique_vantage_mode') - .join( - 'method_technique', - 'method_technique_vantage_mode.method_technique_id', - 'method_technique.method_technique_id' - ) + .into('method_technique_vantage') + .join('method_technique', 'method_technique_vantage.method_technique_id', 'method_technique.method_technique_id') .join('survey', 'method_technique.survey_id', 'survey.survey_id') .where('survey.survey_id', surveyId) - .returning('method_technique_vantage_mode_id'); + .returning('method_technique_vantage_id'); - const response = await this.connection.knex( - queryBuilder, - z.object({ method_technique_vantage_mode_id: z.number() }) - ); + const response = await this.connection.knex(queryBuilder, z.object({ method_technique_vantage_id: z.number() })); - if (!response.rows || response.rows.length !== vantageModeMethods.length) { - throw new ApiExecuteSQLError('Failed to insert vantage modes for technique', [ - 'TechniqueVantageRepository->insertVantageModesForTechnique', + if (!response.rows || response.rows.length !== vantageMethods.length) { + throw new ApiExecuteSQLError('Failed to insert vantages for technique', [ + 'TechniqueVantageRepository->insertVantagesForTechnique', 'rows was null or undefined, expected rows != null' ]); } @@ -113,79 +98,71 @@ export class TechniqueVantageRepository extends BaseRepository { } /** - * Delete vantage modes for a technique + * Delete vantages for a technique * * @param {number} surveyId * @param {number} methodTechniqueId - * @param {VantagePostData[]} vantageModeMethods + * @param {VantagePostData[]} vantageMethods * @return {*} {Promise} - * @memberof VantageModeRepository + * @memberof VantageRepository */ - async deleteVantageModesForTechnique( + async deleteVantagesForTechnique( surveyId: number, methodTechniqueId: number, - vantageModeMethods: VantagePostData[] + vantageMethods: VantagePostData[] ): Promise { - defaultLog.debug({ label: 'deleteVantageModesForTechnique', methodTechniqueId }); + defaultLog.debug({ label: 'deleteVantagesForTechnique', methodTechniqueId }); - if (!vantageModeMethods.length) { + if (!vantageMethods.length) { return; } const queryBuilder = getKnex() - .table('method_technique_vantage_mode') + .table('method_technique_vantage') .delete() - .join( - 'method_technique', - 'method_technique_vantage_mode.method_technique_id', - 'method_technique.method_technique_id' - ) + .join('method_technique', 'method_technique_vantage.method_technique_id', 'method_technique.method_technique_id') .join('survey', 'method_technique.survey_id', 'survey.survey_id') .where('survey.survey_id', surveyId) - .where('method_technique_vantage_mode.method_technique_id', methodTechniqueId) + .where('method_technique_vantage.method_technique_id', methodTechniqueId) .whereIn( - 'method_technique_vantage_mode.vantage_mode_method_id', - vantageModeMethods.map((vantageModeMethod) => vantageModeMethod.vantage_mode_method_id) + 'method_technique_vantage.vantage_method_id', + vantageMethods.map((vantageMethod) => vantageMethod.vantage_method_id) ); const response = await this.connection.knex(queryBuilder); if (!response.rows) { - throw new ApiExecuteSQLError('Failed to delete vantage modes for technique', [ - 'TechniqueVantageRepository->deleteVantageModesForTechnique', + throw new ApiExecuteSQLError('Failed to delete vantages for technique', [ + 'TechniqueVantageRepository->deleteVantagesForTechnique', 'rows was null or undefined, expected rows != null' ]); } } /** - * Delete all vantage modes for a technique + * Delete all vantages for a technique * * @param {number} surveyId * @param {number} methodTechniqueId * @return {*} {Promise} - * @memberof VantageModeRepository + * @memberof VantageRepository */ - async deleteAllVantageModesForTechnique(surveyId: number, methodTechniqueId: number): Promise { - defaultLog.debug({ label: 'deleteAllVantageModesForTechnique', methodTechniqueId }); + async deleteAllVantagesForTechnique(surveyId: number, methodTechniqueId: number): Promise { + defaultLog.debug({ label: 'deleteAllVantagesForTechnique', methodTechniqueId }); const queryBuilder = getKnex() - .table('method_technique_vantage_mode') + .table('method_technique_vantage') .delete() - .join( - 'method_technique', - 'method_technique_vantage_mode.method_technique_id', - 'method_technique.method_technique_id' - ) + .join('method_technique', 'method_technique_vantage.method_technique_id', 'method_technique.method_technique_id') .join('survey', 'method_technique.survey_id', 'survey.survey_id') .where('survey.survey_id', surveyId) - .where('method_technique_vantage_mode.method_technique_id', methodTechniqueId); + .where('method_technique_vantage.method_technique_id', methodTechniqueId); const response = await this.connection.knex(queryBuilder); if (!response.rows) { - throw new ApiExecuteSQLError('Failed to delete all vantage modes for technique', [ - 'TechniqueVantageRepository->deleteAllVantageModesForTechnique', + throw new ApiExecuteSQLError('Failed to delete all vantages for technique', [ + 'TechniqueVantageRepository->deleteAllVantagesForTechnique', 'rows was null or undefined, expected rows != null' ]); } diff --git a/api/src/repositories/vantage-mode-repository.test.ts b/api/src/repositories/vantage-mode-repository.test.ts index 7ddd2140fd..e0881a054f 100644 --- a/api/src/repositories/vantage-mode-repository.test.ts +++ b/api/src/repositories/vantage-mode-repository.test.ts @@ -4,26 +4,26 @@ import { QueryResult } from 'pg'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; import { getMockDBConnection } from '../__mocks__/db'; -import { VantageModeRepository, VantageReferenceRecord } from './vantage-mode-repository'; +import { VantageReferenceRecord, VantageRepository } from './vantage-mode-repository'; chai.use(sinonChai); -describe('VantageModeRepository', () => { +describe('VantageRepository', () => { afterEach(() => { sinon.restore(); }); - describe('getVantageModesByMethodLookupIds', () => { - it('should successfully return vantage modes for provided method lookup ids', async () => { - const mockVantageMode: VantageReferenceRecord = { - vantage_mode_category_id: 101, + describe('getVantagesByMethodLookupIds', () => { + it('should successfully return vantages for provided method lookup ids', async () => { + const mockVantage: VantageReferenceRecord = { + vantage_category_id: 101, name: 'Vantage A', description: 'Description for vantage A', - vantage_modes: [{ vantage_mode_method_id: 1, name: 'Mode A', description: 'Description' }] + vantages: [{ vantage_method_id: 1, name: 'Mode A', description: 'Description' }] }; const mockResponse = { - rows: [mockVantageMode], + rows: [mockVantage], rowCount: 1 } as any as Promise>; @@ -31,15 +31,15 @@ describe('VantageModeRepository', () => { knex: () => mockResponse }); - const repository = new VantageModeRepository(dbConnection); + const repository = new VantageRepository(dbConnection); const methodLookupIds = [1, 2, 3]; const response = await repository.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); - expect(response).to.eql([mockVantageMode]); + expect(response).to.eql([mockVantage]); }); - it('should return an empty array if no vantage modes are found for provided method lookup ids', async () => { + it('should return an empty array if no vantages are found for provided method lookup ids', async () => { const mockResponse = { rows: [], rowCount: 0 @@ -49,7 +49,7 @@ describe('VantageModeRepository', () => { knex: () => mockResponse }); - const repository = new VantageModeRepository(dbConnection); + const repository = new VantageRepository(dbConnection); const methodLookupIds = [10, 20, 30]; const response = await repository.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); diff --git a/api/src/repositories/vantage-mode-repository.ts b/api/src/repositories/vantage-mode-repository.ts index 2c20de82ca..45fa038c5c 100644 --- a/api/src/repositories/vantage-mode-repository.ts +++ b/api/src/repositories/vantage-mode-repository.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { VantageRecord } from '../database-models/vantage'; -import { VantageModeRecord } from '../database-models/vantage_mode'; -import { VantageModeMethodRecord } from '../database-models/vantage_mode_method'; +import { VantageCategory } from '../database-models/vantage_category'; +import { VantageMethodRecord } from '../database-models/vantage_method'; import { getKnex } from '../database/db'; import { getLogger } from '../utils/logger'; import { BaseRepository } from './base-repository'; @@ -9,40 +9,40 @@ import { BaseRepository } from './base-repository'; const defaultLog = getLogger('repositories/technique-vantage-repository'); export type VantagePostData = { - vantage_mode_method_id: number; + vantage_method_id: number; }; -export const VantageReferenceRecord = VantageRecord.omit({ +export const VantageReferenceRecord = VantageCategory.omit({ record_end_date: true }).extend({ - vantage_modes: z.array( - VantageModeMethodRecord.omit({ + vantages: z.array( + VantageMethodRecord.omit({ record_end_date: true, method_lookup_id: true, - vantage_mode_id: true, + vantage_id: true, description: true }).merge( - // The name and description returned come from the VantageModeRecord - VantageModeRecord.pick({ name: true, description: true }) + // The name and description returned come from the VantageRecord + VantageRecord.pick({ name: true, description: true }) ) ) }); export type VantageReferenceRecord = z.infer; -export class VantageModeRepository extends BaseRepository { +export class VantageRepository extends BaseRepository { /** * Insert vantage records for a technique. * * @param {number} methodTechniqueId * @param {VantagePostData[]} vantages - * @return {*} {(Promise<{ method_technique_vantage_mode_id: number }[] | undefined>)} - * @memberof VantageModeRepository + * @return {*} {(Promise<{ method_technique_vantage_id: number }[] | undefined>)} + * @memberof VantageRepository */ async insertVantagesForTechnique( methodTechniqueId: number, vantages: VantagePostData[] - ): Promise<{ method_technique_vantage_mode_id: number }[] | undefined> { + ): Promise<{ method_technique_vantage_id: number }[] | undefined> { defaultLog.debug({ label: 'insertVantagesForTechnique', methodTechniqueId }); if (!vantages.length) { @@ -53,16 +53,13 @@ export class VantageModeRepository extends BaseRepository { .insert( vantages.map((vantage) => ({ method_technique_id: methodTechniqueId, - vantage_mode_method_id: vantage.vantage_mode_method_id + vantage_method_id: vantage.vantage_method_id })) ) - .into('method_technique_vantage_mode') - .returning('method_technique_vantage_mode_id'); + .into('method_technique_vantage') + .returning('method_technique_vantage_id'); - const response = await this.connection.knex( - queryBuilder, - z.object({ method_technique_vantage_mode_id: z.number() }) - ); + const response = await this.connection.knex(queryBuilder, z.object({ method_technique_vantage_id: z.number() })); return response.rows; } @@ -72,35 +69,35 @@ export class VantageModeRepository extends BaseRepository { * * @param {number[]} methodLookupIds * @return {*} {Promise} - * @memberof VantageModeRepository + * @memberof VantageRepository */ async getVantageReferenceRecordsByMethodLookupIds(methodLookupIds: number[]): Promise { - defaultLog.debug({ label: 'getVantageModesByMethodLookupIds', methodLookupIds }); + defaultLog.debug({ label: 'getVantagesByMethodLookupIds', methodLookupIds }); const knex = getKnex(); const queryBuilder = knex .select( - 'v.vantage_mode_category_id', - 'v.name', - 'v.description', + 'vc.vantage_category_id', + 'vc.name', + 'vc.description', knex.raw(` json_agg( json_build_object( - 'vantage_mode_method_id', vmm.vantage_mode_method_id, - 'vantage_mode_category_id', vm.vantage_mode_category_id, - 'name', vm.name, - 'description', vm.description + 'vantage_method_id', vm.vantage_method_id, + 'vantage_id', v.vantage_id, + 'name', v.name, + 'description', v.description ) - ) as vantage_modes + ) as vantages `) ) - .from('vantage_mode_method as vmm') - .join('vantage_mode as vm', 'vmm.vantage_mode_id', 'vm.vantage_mode_id') - .join('vantage as v', 'v.vantage_mode_category_id', 'vm.vantage_mode_category_id') - .whereIn('vmm.method_lookup_id', methodLookupIds) - .whereNull('vmm.record_end_date') - .groupBy('v.vantage_mode_category_id', 'v.name', 'v.description'); + .from('vantage_method as vm') + .join('vantage as v', 'vm.vantage_id', 'v.vantage_id') + .join('vantage_category as vc', 'v.vantage_category_id', 'vc.vantage_category_id') + .whereIn('vm.method_lookup_id', methodLookupIds) + .whereNull('vm.record_end_date') + .groupBy('vc.vantage_category_id', 'vc.name', 'vc.description'); const response = await this.connection.knex(queryBuilder, VantageReferenceRecord); diff --git a/api/src/services/technique-service.test.ts b/api/src/services/technique-service.test.ts index 696a8cbb16..85a16dfce0 100644 --- a/api/src/services/technique-service.test.ts +++ b/api/src/services/technique-service.test.ts @@ -35,7 +35,7 @@ describe('TechniqueService', () => { qualitative_attributes: [], quantitative_attributes: [] }, - vantage_mode_methods: [] + vantage_methods: [] }; sinon.stub(TechniqueRepository.prototype, 'getTechniqueById').resolves(mockRecord); @@ -66,7 +66,7 @@ describe('TechniqueService', () => { qualitative_attributes: [], quantitative_attributes: [] }, - vantage_mode_methods: [] + vantage_methods: [] }; sinon.stub(TechniqueRepository.prototype, 'getTechniquesForSurveyId').resolves([mockRecord]); @@ -149,7 +149,7 @@ describe('TechniqueService', () => { } ] }, - vantage_mode_methods: [] + vantage_methods: [] } ]; @@ -210,8 +210,8 @@ describe('TechniqueService', () => { const deleteAllTechniqueAttributesStub = sinon .stub(TechniqueAttributeService.prototype, 'deleteAllTechniqueAttributes') .resolves(); - const deleteAllVantageModesForTechniqueStub = sinon - .stub(TechniqueVantageService.prototype, 'deleteAllVantageModesForTechnique') + const deleteAllVantagesForTechniqueStub = sinon + .stub(TechniqueVantageService.prototype, 'deleteAllVantagesForTechnique') .resolves(); const deleteTechniqueStub = sinon.stub(TechniqueRepository.prototype, 'deleteTechnique').resolves(mockRecord); @@ -226,7 +226,7 @@ describe('TechniqueService', () => { expect(deleteAllTechniqueAttractantsStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); expect(deleteAllTechniqueAttributesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); - expect(deleteAllVantageModesForTechniqueStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); + expect(deleteAllVantagesForTechniqueStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); expect(deleteTechniqueStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); expect(response).to.eql(mockRecord); diff --git a/api/src/services/technique-service.ts b/api/src/services/technique-service.ts index 0193a79c0b..732399d166 100644 --- a/api/src/services/technique-service.ts +++ b/api/src/services/technique-service.ts @@ -123,12 +123,12 @@ export class TechniqueService extends DBService { } // Insert vantages - if (technique.vantage_mode_methods.length) { + if (technique.vantage_methods.length) { promises.push( - this.techniqueVantageService.insertVantageModesForTechnique( + this.techniqueVantageService.insertVantagesForTechnique( surveyId, method_technique_id, - technique.vantage_mode_methods + technique.vantage_methods ) ); } @@ -171,8 +171,8 @@ export class TechniqueService extends DBService { // Delete any attributes on the technique await this.techniqueAttributeService.deleteAllTechniqueAttributes(surveyId, methodTechniqueId); - // Delete any vantage modes on the technique - await this.techniqueVantageService.deleteAllVantageModesForTechnique(surveyId, methodTechniqueId); + // Delete any vantages on the technique + await this.techniqueVantageService.deleteAllVantagesForTechnique(surveyId, methodTechniqueId); // Delete the technique return this.techniqueRepository.deleteTechnique(surveyId, methodTechniqueId); diff --git a/api/src/services/technique-vantage-service.test.ts b/api/src/services/technique-vantage-service.test.ts index 9a647fb06c..7164725d55 100644 --- a/api/src/services/technique-vantage-service.test.ts +++ b/api/src/services/technique-vantage-service.test.ts @@ -13,150 +13,146 @@ describe('TechniqueVantageService', () => { sinon.restore(); }); - describe('insertVantageModesForTechnique', () => { - it('should insert vantage modes successfully', async () => { + describe('insertVantagesForTechnique', () => { + it('should insert vantages successfully', async () => { const surveyId = 1; const methodTechniqueId = 2; - const vantageModeMethods = [ - { vantage_mode_method_id: 101, description: 'Mode 1' }, - { vantage_mode_method_id: 102, description: 'Mode 2' } + const vantageMethods = [ + { vantage_method_id: 101, description: 'Mode 1' }, + { vantage_method_id: 102, description: 'Mode 2' } ]; - const mockInsertResponse = [{ method_technique_vantage_mode_id: 1 }, { method_technique_vantage_mode_id: 2 }]; - const insertVantageModesStub = sinon - .stub(TechniqueVantageRepository.prototype, 'insertVantageModesForTechnique') + const mockInsertResponse = [{ method_technique_vantage_id: 1 }, { method_technique_vantage_id: 2 }]; + const insertVantagesStub = sinon + .stub(TechniqueVantageRepository.prototype, 'insertVantagesForTechnique') .resolves(mockInsertResponse); const dbConnection = getMockDBConnection(); const service = new TechniqueVantageService(dbConnection); - const response = await service.insertVantageModesForTechnique(surveyId, methodTechniqueId, vantageModeMethods); + const response = await service.insertVantagesForTechnique(surveyId, methodTechniqueId, vantageMethods); expect(response).to.eql(mockInsertResponse); - expect(insertVantageModesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId, vantageModeMethods); + expect(insertVantagesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId, vantageMethods); }); - it('should handle empty vantage modes gracefully', async () => { + it('should handle empty vantages gracefully', async () => { const surveyId = 1; const methodTechniqueId = 2; - const vantageModeMethods: any[] = []; + const vantageMethods: any[] = []; const dbConnection = getMockDBConnection(); const techniqueVantageService = new TechniqueVantageService(dbConnection); - const response = await techniqueVantageService.insertVantageModesForTechnique( + const response = await techniqueVantageService.insertVantagesForTechnique( surveyId, methodTechniqueId, - vantageModeMethods + vantageMethods ); expect(response).to.be.undefined; }); }); - describe('updateVantageModesForTechnique', () => { - it('should update vantage modes successfully', async () => { + describe('updateVantagesForTechnique', () => { + it('should update vantages successfully', async () => { const surveyId = 1; const methodTechniqueId = 2; - const mockVantageModeMethods = [{ vantage_mode_method_id: 101 }]; + const mockVantageMethods = [{ vantage_method_id: 101 }]; - const existingVantageModes = [ + const existingVantages = [ { - method_technique_vantage_mode_id: 2, - vantage_mode_method_id: 102, - vantage_mode_category_id: 1 + method_technique_vantage_id: 2, + vantage_method_id: 102, + vantage_category_id: 1 } ]; - sinon.stub(TechniqueVantageRepository.prototype, 'getVantageModesForTechnique').resolves(existingVantageModes); + sinon.stub(TechniqueVantageRepository.prototype, 'getVantagesForTechnique').resolves(existingVantages); - const deleteVantageModesStub = sinon - .stub(TechniqueVantageRepository.prototype, 'deleteVantageModesForTechnique') + const deleteVantagesStub = sinon + .stub(TechniqueVantageRepository.prototype, 'deleteVantagesForTechnique') .resolves(); - const insertVantageModesStub = sinon - .stub(TechniqueVantageRepository.prototype, 'insertVantageModesForTechnique') + const insertVantagesStub = sinon + .stub(TechniqueVantageRepository.prototype, 'insertVantagesForTechnique') .resolves(); const dbConnection = getMockDBConnection(); const techniqueVantageService = new TechniqueVantageService(dbConnection); - await techniqueVantageService.updateVantageModesForTechnique(surveyId, methodTechniqueId, mockVantageModeMethods); + await techniqueVantageService.updateVantagesForTechnique(surveyId, methodTechniqueId, mockVantageMethods); - expect(deleteVantageModesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId, [ - { vantage_mode_method_id: 102 } - ]); - expect(insertVantageModesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId, [ - { vantage_mode_method_id: 101 } - ]); + expect(deleteVantagesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId, [{ vantage_method_id: 102 }]); + expect(insertVantagesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId, [{ vantage_method_id: 101 }]); }); - it('should not update if no changes in vantage modes', async () => { + it('should not update if no changes in vantages', async () => { const surveyId = 1; const methodTechniqueId = 2; - const vantageModeMethods = [{ vantage_mode_method_id: 101 }, { vantage_mode_method_id: 102 }]; + const vantageMethods = [{ vantage_method_id: 101 }, { vantage_method_id: 102 }]; - const existingVantageModes = [ + const existingVantages = [ { - method_technique_vantage_mode_id: 1, - vantage_mode_method_id: 101, - vantage_mode_category_id: 2 + method_technique_vantage_id: 1, + vantage_method_id: 101, + vantage_category_id: 2 }, { - method_technique_vantage_mode_id: 2, - vantage_mode_method_id: 102, - vantage_mode_category_id: 1 + method_technique_vantage_id: 2, + vantage_method_id: 102, + vantage_category_id: 1 } ]; - sinon.stub(TechniqueVantageRepository.prototype, 'getVantageModesForTechnique').resolves(existingVantageModes); - const deleteVantageModesStub = sinon.stub(TechniqueVantageRepository.prototype, 'deleteVantageModesForTechnique'); - const insertVantageModesStub = sinon.stub(TechniqueVantageRepository.prototype, 'insertVantageModesForTechnique'); + sinon.stub(TechniqueVantageRepository.prototype, 'getVantagesForTechnique').resolves(existingVantages); + const deleteVantagesStub = sinon.stub(TechniqueVantageRepository.prototype, 'deleteVantagesForTechnique'); + const insertVantagesStub = sinon.stub(TechniqueVantageRepository.prototype, 'insertVantagesForTechnique'); const dbConnection = getMockDBConnection(); const techniqueVantageService = new TechniqueVantageService(dbConnection); - await techniqueVantageService.updateVantageModesForTechnique(surveyId, methodTechniqueId, vantageModeMethods); + await techniqueVantageService.updateVantagesForTechnique(surveyId, methodTechniqueId, vantageMethods); - expect(deleteVantageModesStub).to.not.have.been.called; - expect(insertVantageModesStub).to.not.have.been.called; + expect(deleteVantagesStub).to.not.have.been.called; + expect(insertVantagesStub).to.not.have.been.called; }); - it('should handle empty current and new vantage modes gracefully', async () => { + it('should handle empty current and new vantages gracefully', async () => { const surveyId = 1; const methodTechniqueId = 2; - const vantageModeMethods: any[] = []; + const vantageMethods: any[] = []; - const existingVantageModes: any[] = []; + const existingVantages: any[] = []; - sinon.stub(TechniqueVantageRepository.prototype, 'getVantageModesForTechnique').resolves(existingVantageModes); - const deleteVantageModesStub = sinon.stub(TechniqueVantageRepository.prototype, 'deleteVantageModesForTechnique'); - const insertVantageModesStub = sinon.stub(TechniqueVantageRepository.prototype, 'insertVantageModesForTechnique'); + sinon.stub(TechniqueVantageRepository.prototype, 'getVantagesForTechnique').resolves(existingVantages); + const deleteVantagesStub = sinon.stub(TechniqueVantageRepository.prototype, 'deleteVantagesForTechnique'); + const insertVantagesStub = sinon.stub(TechniqueVantageRepository.prototype, 'insertVantagesForTechnique'); const dbConnection = getMockDBConnection(); const techniqueVantageService = new TechniqueVantageService(dbConnection); - await techniqueVantageService.updateVantageModesForTechnique(surveyId, methodTechniqueId, vantageModeMethods); + await techniqueVantageService.updateVantagesForTechnique(surveyId, methodTechniqueId, vantageMethods); - expect(deleteVantageModesStub).to.not.have.been.called; - expect(insertVantageModesStub).to.not.have.been.called; + expect(deleteVantagesStub).to.not.have.been.called; + expect(insertVantagesStub).to.not.have.been.called; }); }); - describe('deleteAllVantageModesForTechnique', () => { - it('should delete all vantage modes for a technique successfully', async () => { + describe('deleteAllVantagesForTechnique', () => { + it('should delete all vantages for a technique successfully', async () => { const surveyId = 1; const methodTechniqueId = 2; - const deleteAllVantageModesStub = sinon - .stub(TechniqueVantageRepository.prototype, 'deleteAllVantageModesForTechnique') + const deleteAllVantagesStub = sinon + .stub(TechniqueVantageRepository.prototype, 'deleteAllVantagesForTechnique') .resolves(); const dbConnection = getMockDBConnection(); const techniqueVantageService = new TechniqueVantageService(dbConnection); - const response = await techniqueVantageService.deleteAllVantageModesForTechnique(surveyId, methodTechniqueId); + const response = await techniqueVantageService.deleteAllVantagesForTechnique(surveyId, methodTechniqueId); - expect(deleteAllVantageModesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); + expect(deleteAllVantagesStub).to.have.been.calledOnceWith(surveyId, methodTechniqueId); expect(response).to.be.undefined; }); }); diff --git a/api/src/services/technique-vantage-service.ts b/api/src/services/technique-vantage-service.ts index 6e3c775d8b..b2b5e6cb4c 100644 --- a/api/src/services/technique-vantage-service.ts +++ b/api/src/services/technique-vantage-service.ts @@ -20,83 +20,66 @@ export class TechniqueVantageService extends DBService { } /** - * Insert vantage modes for a technique. + * Insert vantages for a technique. * * @param {number} surveyId * @param {number} methodTechniqueId - * @param {VantagePostData[]} vantageModeMethods - * @return {*} {(Promise<{ method_technique_vantage_mode_id: number }[] | undefined>)} + * @param {VantagePostData[]} vantageMethods + * @return {*} {(Promise<{ method_technique_vantage_id: number }[] | undefined>)} * @memberof TechniqueVantageService */ - async insertVantageModesForTechnique( + async insertVantagesForTechnique( surveyId: number, methodTechniqueId: number, - vantageModeMethods: VantagePostData[] - ): Promise<{ method_technique_vantage_mode_id: number }[] | undefined> { - return this.techniqueVantageRepository.insertVantageModesForTechnique( - surveyId, - methodTechniqueId, - vantageModeMethods - ); + vantageMethods: VantagePostData[] + ): Promise<{ method_technique_vantage_id: number }[] | undefined> { + return this.techniqueVantageRepository.insertVantagesForTechnique(surveyId, methodTechniqueId, vantageMethods); } /** - * Update vantage modes for a technique by inserting new vantage modes and - * deleting existing vantage modes not included in the request. + * Update vantages for a technique by inserting new vantages and + * deleting existing vantages not included in the request. * * @param {number} surveyId * @param {number} methodTechniqueId - * @param {VantagePostData[]} vantageModeMethods + * @param {VantagePostData[]} vantageMethods * @return {*} {(Promise} * @memberof TechniqueVantageService */ - async updateVantageModesForTechnique( + async updateVantagesForTechnique( surveyId: number, methodTechniqueId: number, - vantageModeMethods: VantagePostData[] + vantageMethods: VantagePostData[] ): Promise { - const existingVantageModes = await this.techniqueVantageRepository.getVantageModesForTechnique( - surveyId, - methodTechniqueId - ); + const existingVantages = await this.techniqueVantageRepository.getVantagesForTechnique(surveyId, methodTechniqueId); - if (!existingVantageModes.length && !vantageModeMethods.length) return; + if (!existingVantages.length && !vantageMethods.length) return; - // Map of existing vantage modes - const existingVantageModesMap = new Map(existingVantageModes.map((mode) => [mode.vantage_mode_method_id, mode])); + // Map of existing vantages + const existingVantagesMap = new Map(existingVantages.map((mode) => [mode.vantage_method_id, mode])); - // Set of incoming vantage modes - const incomingVantageModesSet = new Set(vantageModeMethods.map((mode) => mode.vantage_mode_method_id)); + // Set of incoming vantages + const incomingVantagesSet = new Set(vantageMethods.map((mode) => mode.vantage_method_id)); // Determine which records need to be deleted (those that exist but are not in the incoming request) - const vantageModesToDelete = existingVantageModes - .filter((existing) => !incomingVantageModesSet.has(existing.vantage_mode_method_id)) - .map((existing) => ({ vantage_mode_method_id: existing.vantage_mode_method_id })); + const vantagesToDelete = existingVantages + .filter((existing) => !incomingVantagesSet.has(existing.vantage_method_id)) + .map((existing) => ({ vantage_method_id: existing.vantage_method_id })); // Determine which records need to be inserted (those in the incoming request but not in the existing ones) - const vantageModesToInsert = vantageModeMethods.filter( - (incoming) => !existingVantageModesMap.has(incoming.vantage_mode_method_id) - ); + const vantagesToInsert = vantageMethods.filter((incoming) => !existingVantagesMap.has(incoming.vantage_method_id)); const promises = []; - if (vantageModesToDelete.length) { + if (vantagesToDelete.length) { promises.push( - this.techniqueVantageRepository.deleteVantageModesForTechnique( - surveyId, - methodTechniqueId, - vantageModesToDelete - ) + this.techniqueVantageRepository.deleteVantagesForTechnique(surveyId, methodTechniqueId, vantagesToDelete) ); } - if (vantageModesToInsert.length) { + if (vantagesToInsert.length) { promises.push( - this.techniqueVantageRepository.insertVantageModesForTechnique( - surveyId, - methodTechniqueId, - vantageModesToInsert - ) + this.techniqueVantageRepository.insertVantagesForTechnique(surveyId, methodTechniqueId, vantagesToInsert) ); } @@ -106,14 +89,14 @@ export class TechniqueVantageService extends DBService { } /** - * Delete all vantage modes for a technique. + * Delete all vantages for a technique. * * @param {number} surveyId * @param {number} methodTechniqueId * @return {*} {Promise} * @memberof TechniqueVantageService */ - async deleteAllVantageModesForTechnique(surveyId: number, methodTechniqueId: number): Promise { - await this.techniqueVantageRepository.deleteAllVantageModesForTechnique(surveyId, methodTechniqueId); + async deleteAllVantagesForTechnique(surveyId: number, methodTechniqueId: number): Promise { + await this.techniqueVantageRepository.deleteAllVantagesForTechnique(surveyId, methodTechniqueId); } } diff --git a/api/src/services/vantage-mode-service.test.ts b/api/src/services/vantage-mode-service.test.ts index d25c31b446..f6a2c67ebc 100644 --- a/api/src/services/vantage-mode-service.test.ts +++ b/api/src/services/vantage-mode-service.test.ts @@ -3,44 +3,42 @@ import { describe } from 'mocha'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; import { ApiGeneralError } from '../errors/api-error'; -import { VantageModeRepository, VantageReferenceRecord } from '../repositories/vantage-mode-repository'; +import { VantageReferenceRecord, VantageRepository } from '../repositories/vantage-mode-repository'; import { getMockDBConnection } from '../__mocks__/db'; -import { VantageModeService } from './vantage-mode-service'; +import { VantageService } from './vantage-mode-service'; chai.use(sinonChai); -describe('VantageModeService', () => { +describe('VantageService', () => { afterEach(() => { sinon.restore(); }); describe('getVantageReferenceRecordsByMethodLookupIds', () => { - it('should run successfully and return vantage modes for the provided method lookup ids', async () => { - const mockVantageMode: VantageReferenceRecord = { - vantage_mode_category_id: 101, + it('should run successfully and return vantages for the provided method lookup ids', async () => { + const mockVantage: VantageReferenceRecord = { + vantage_category_id: 101, name: 'Vantage A', description: 'Description for vantage A', - vantage_modes: [{ vantage_mode_method_id: 1, name: 'Mode A', description: 'Description' }] + vantages: [{ vantage_method_id: 1, name: 'Mode A', description: 'Description' }] }; - sinon - .stub(VantageModeRepository.prototype, 'getVantageReferenceRecordsByMethodLookupIds') - .resolves([mockVantageMode]); + sinon.stub(VantageRepository.prototype, 'getVantageReferenceRecordsByMethodLookupIds').resolves([mockVantage]); const dbConnection = getMockDBConnection(); - const service = new VantageModeService(dbConnection); + const service = new VantageService(dbConnection); const methodLookupIds = [1, 2, 3]; const response = await service.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); - expect(response).to.eql([mockVantageMode]); + expect(response).to.eql([mockVantage]); }); - it('should return an empty array when no vantage modes are found for the provided method lookup ids', async () => { - sinon.stub(VantageModeRepository.prototype, 'getVantageReferenceRecordsByMethodLookupIds').resolves([]); + it('should return an empty array when no vantages are found for the provided method lookup ids', async () => { + sinon.stub(VantageRepository.prototype, 'getVantageReferenceRecordsByMethodLookupIds').resolves([]); const dbConnection = getMockDBConnection(); - const service = new VantageModeService(dbConnection); + const service = new VantageService(dbConnection); const methodLookupIds = [10, 20, 30]; const response = await service.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); @@ -50,11 +48,11 @@ describe('VantageModeService', () => { it('should handle errors gracefully when repository method fails', async () => { sinon - .stub(VantageModeRepository.prototype, 'getVantageReferenceRecordsByMethodLookupIds') + .stub(VantageRepository.prototype, 'getVantageReferenceRecordsByMethodLookupIds') .rejects(new Error('Query error')); const dbConnection = getMockDBConnection(); - const service = new VantageModeService(dbConnection); + const service = new VantageService(dbConnection); try { await service.getVantageReferenceRecordsByMethodLookupIds([1, 2, 3]); diff --git a/api/src/services/vantage-mode-service.ts b/api/src/services/vantage-mode-service.ts index 6df31d4301..3ef098ec6a 100644 --- a/api/src/services/vantage-mode-service.ts +++ b/api/src/services/vantage-mode-service.ts @@ -1,31 +1,31 @@ import { IDBConnection } from '../database/db'; -import { VantageModeRepository, VantageReferenceRecord } from '../repositories/vantage-mode-repository'; +import { VantageReferenceRecord, VantageRepository } from '../repositories/vantage-mode-repository'; import { DBService } from './db-service'; /** - * Service layer for vantage mode related information + * Service layer for vantage related information * * @export - * @class VantageModeService + * @class VantageService * @extends {DBService} */ -export class VantageModeService extends DBService { - vantageModeRepository: VantageModeRepository; +export class VantageService extends DBService { + vantageRepository: VantageRepository; constructor(connection: IDBConnection) { super(connection); - this.vantageModeRepository = new VantageModeRepository(connection); + this.vantageRepository = new VantageRepository(connection); } /** - * Get vantage modes for a set of method lookup ids + * Get vantages for a set of method lookup ids * * @param {number[]} methodLookupIds * @return {*} {Promise} - * @memberof VantageModeService + * @memberof VantageService */ async getVantageReferenceRecordsByMethodLookupIds(methodLookupIds: number[]): Promise { - return this.vantageModeRepository.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); + return this.vantageRepository.getVantageReferenceRecordsByMethodLookupIds(methodLookupIds); } } diff --git a/app/src/features/surveys/sampling-information/techniques/components/TechniqueFormContainer.tsx b/app/src/features/surveys/sampling-information/techniques/components/TechniqueFormContainer.tsx index 256262e3e0..286147ddaf 100644 --- a/app/src/features/surveys/sampling-information/techniques/components/TechniqueFormContainer.tsx +++ b/app/src/features/surveys/sampling-information/techniques/components/TechniqueFormContainer.tsx @@ -32,22 +32,22 @@ export type TechniqueAttributeFormValues = }; export type TechniqueVantagesFormValues = { - vantage_mode_category_id: number; - vantage_mode_method_id: number; + vantage_category_id: number; + vantage_method_id: number; // internal ID used for form control keys. Not to be sent to API. _id?: string; }; -export type CreateTechniqueFormValues = Omit & { +export type CreateTechniqueFormValues = Omit & { // Overwrite the default attributes field to include additional fields used only by the form controls attributes: TechniqueAttributeFormValues[]; - vantage_mode_methods: TechniqueVantagesFormValues[]; + vantage_methods: TechniqueVantagesFormValues[]; }; -export type UpdateTechniqueFormValues = Omit & { +export type UpdateTechniqueFormValues = Omit & { // Overwrite the default attributes field to include additional fields used only by the form controls attributes: TechniqueAttributeFormValues[]; - vantage_mode_methods: TechniqueVantagesFormValues[]; + vantage_methods: TechniqueVantagesFormValues[]; }; type ITechniqueFormProps = { @@ -94,10 +94,10 @@ const TechniqueFormContainer = diff --git a/app/src/features/surveys/sampling-information/techniques/components/vantages/TechniqueVantagesForm.tsx b/app/src/features/surveys/sampling-information/techniques/components/vantages/TechniqueVantagesForm.tsx index f973d7e66f..61b4b9c5c5 100644 --- a/app/src/features/surveys/sampling-information/techniques/components/vantages/TechniqueVantagesForm.tsx +++ b/app/src/features/surveys/sampling-information/techniques/components/vantages/TechniqueVantagesForm.tsx @@ -14,8 +14,8 @@ import { UpdateTechniqueFormValues } from '../TechniqueFormContainer'; -const initialVantagesFormValues: Partial> = { - vantage_mode_method_id: undefined +const initialVantagesFormValues: Partial> = { + vantage_method_id: undefined }; interface ITechniqueVantageFormProps { @@ -28,47 +28,47 @@ export const TechniqueVantageForm = (); - const getUnitOptions = (vantageModeMethodId: number, categoryId: number) => { - const selectedVantage = vantageReferenceRecords.find((record) => record.vantage_mode_category_id === categoryId); + const getUnitOptions = (vantageMethodId: number, categoryId: number) => { + const selectedVantage = vantageReferenceRecords.find((record) => record.vantage_category_id === categoryId); - if (!selectedVantage || !selectedVantage.vantage_modes) { + if (!selectedVantage || !selectedVantage.vantages) { return []; } - // Filter out already selected vantage modes - const availableModes = selectedVantage.vantage_modes.filter((mode) => { - const isAlreadySelected = values.vantage_mode_methods.some( - (existing) => existing.vantage_mode_method_id === mode.vantage_mode_method_id + // Filter out already selected vantages + const availableModes = selectedVantage.vantages.filter((mode) => { + const isAlreadySelected = values.vantage_methods.some( + (existing) => existing.vantage_method_id === mode.vantage_method_id ); // Keep the option if not already selected, or if it's the one currently being edited - return !isAlreadySelected || vantageModeMethodId === mode.vantage_mode_method_id; + return !isAlreadySelected || vantageMethodId === mode.vantage_method_id; }); return availableModes.map((mode) => ({ - value: mode.vantage_mode_method_id, + value: mode.vantage_method_id, label: mode.name })); }; return ( ( <> - {values.vantage_mode_methods.map((vantage, index) => ( + {values.vantage_methods.map((vantage, index) => ( ({ - value: record.vantage_mode_category_id, + value: record.vantage_category_id, label: record.name }))} - getUnitOptions={(categoryId: number) => getUnitOptions(vantage.vantage_mode_method_id, categoryId)} - formikCategoryFieldName={`vantage_mode_methods.[${index}].vantage_mode_category_id`} - formikUnitFieldName={`vantage_mode_methods.[${index}].vantage_mode_method_id`} + getUnitOptions={(categoryId: number) => getUnitOptions(vantage.vantage_method_id, categoryId)} + formikCategoryFieldName={`vantage_methods.[${index}].vantage_category_id`} + formikUnitFieldName={`vantage_methods.[${index}].vantage_method_id`} onDelete={() => arrayHelpers.remove(index)} /> diff --git a/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx b/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx index 1412b8fc49..e7950948ad 100644 --- a/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx +++ b/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx @@ -29,7 +29,7 @@ const initialTechniqueFormValues: CreateTechniqueFormValues = { method_lookup_id: null, attractants: [], attributes: [], - vantage_mode_methods: [] + vantage_methods: [] }; /** @@ -79,9 +79,9 @@ export const CreateTechniquePage = () => { value: item.attribute_value as number })) }, - vantage_mode_methods: values.vantage_mode_methods.map((vantage_mode_method) => ({ - vantage_mode_method_id: vantage_mode_method.vantage_mode_method_id, - vantage_mode_category_id: vantage_mode_method.vantage_mode_category_id + vantage_methods: values.vantage_methods.map((vantage_method) => ({ + vantage_method_id: vantage_method.vantage_method_id, + vantage_category_id: vantage_method.vantage_category_id })) }; diff --git a/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx b/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx index b84c52379a..ccf87836ba 100644 --- a/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx +++ b/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx @@ -88,10 +88,10 @@ export const EditTechniquePage = () => { attribute_type: 'quantitative' as const })) ?? []) ], - vantage_mode_methods: technique.vantage_mode_methods.map((vantage_mode_method) => ({ + vantage_methods: technique.vantage_methods.map((vantage_method) => ({ _id: v4(), // A temporary unique id for react keys, etc, as the attribute_id is not unique - vantage_mode_category_id: vantage_mode_method.vantage_mode_category_id, - vantage_mode_method_id: vantage_mode_method.vantage_mode_method_id + vantage_category_id: vantage_method.vantage_category_id, + vantage_method_id: vantage_method.vantage_method_id })) }; @@ -118,9 +118,9 @@ export const EditTechniquePage = () => { method_lookup_attribute_qualitative_option_id: attribute.attribute_value as string })) }, - vantage_mode_methods: values.vantage_mode_methods.map((vantage_mode_method) => ({ - vantage_mode_method_id: vantage_mode_method.vantage_mode_method_id, - vantage_mode_category_id: vantage_mode_method.vantage_mode_category_id + vantage_methods: values.vantage_methods.map((vantage_method) => ({ + vantage_method_id: vantage_method.vantage_method_id, + vantage_category_id: vantage_method.vantage_category_id })) }; diff --git a/app/src/hooks/api/useReferenceApi.ts b/app/src/hooks/api/useReferenceApi.ts index 59c563a8b8..6967d8a093 100644 --- a/app/src/hooks/api/useReferenceApi.ts +++ b/app/src/hooks/api/useReferenceApi.ts @@ -39,7 +39,7 @@ const useReferenceApi = (axios: AxiosInstance) => { }; /** - * Get vantage modes available for a method_lookup_id. + * Get vantages available for a method_lookup_id. * * @param {number[]} methodLookupIds * @return {*} {Promise} diff --git a/app/src/interfaces/useReferenceApi.interface.ts b/app/src/interfaces/useReferenceApi.interface.ts index fb3acc8b0d..cc87a24160 100644 --- a/app/src/interfaces/useReferenceApi.interface.ts +++ b/app/src/interfaces/useReferenceApi.interface.ts @@ -88,19 +88,19 @@ export interface IGetTechniqueAttributes { qualitative_attributes: ITechniqueAttributeQualitative[]; } -export type Vantage = { - vantage_mode_category_id: number; +export type VantageCategory = { + vantage_category_id: number; name: string; description: string | null; }; -export type VantageMode = { - vantage_mode_method_id: number; - vantage_mode_category_id: number; +export type Vantage = { + vantage_method_id: number; + vantage_category_id: number; name: string; }; /** * Response for fetching vantage reference records for a method lookup id */ -export type GetVantageReferenceRecord = Vantage & { vantage_modes: VantageMode[] }; +export type GetVantageReferenceRecord = Vantage & { vantages: Vantage[] }; diff --git a/app/src/interfaces/useTechniqueApi.interface.ts b/app/src/interfaces/useTechniqueApi.interface.ts index c3c652ab44..ca220d2248 100644 --- a/app/src/interfaces/useTechniqueApi.interface.ts +++ b/app/src/interfaces/useTechniqueApi.interface.ts @@ -1,5 +1,5 @@ import { ApiPaginationResponseParams } from 'types/misc'; -import { VantageMode } from './useReferenceApi.interface'; +import { Vantage } from './useReferenceApi.interface'; export type TechniqueAttractant = { attractant_lookup_id: number; @@ -17,12 +17,12 @@ export type TechniqueQuantitativeAttribute = { value: number; }; -export type TechniqueVantageModeMethod = { - vantage_mode_category_id: number; - vantage_mode_method_id: number; +export type TechniqueVantageMethod = { + vantage_category_id: number; + vantage_method_id: number; }; -type PostVantageMode = Omit; +type PostVantage = Omit; export interface ICreateTechniqueRequest { name: string; @@ -34,7 +34,7 @@ export interface ICreateTechniqueRequest { qualitative_attributes: TechniqueQualitativeAttribute[]; quantitative_attributes: TechniqueQuantitativeAttribute[]; }; - vantage_mode_methods: PostVantageMode[]; + vantage_methods: PostVantage[]; } export interface IUpdateTechniqueRequest extends ICreateTechniqueRequest { @@ -52,7 +52,7 @@ export interface IGetTechniqueResponse { quantitative_attributes: TechniqueQuantitativeAttribute[]; qualitative_attributes: TechniqueQualitativeAttribute[]; }; - vantage_mode_methods: VantageMode[]; + vantage_methods: Vantage[]; } export interface IGetTechniquesResponse { diff --git a/database/src/migrations/20241213161700_rename_vantage.ts b/database/src/migrations/20241213161700_rename_vantage.ts index e9bbcbdf27..03b717dac2 100644 --- a/database/src/migrations/20241213161700_rename_vantage.ts +++ b/database/src/migrations/20241213161700_rename_vantage.ts @@ -11,51 +11,391 @@ import { Knex } from 'knex'; export async function up(knex: Knex): Promise { await knex.raw(` - DROP VIEW biohub_dapi_v1.vantage; - DROP VIEW biohub_dapi_v1.vantage_mode; - - SET SEARCH_PATH = biohub; - ---------------------------------------------------------------------------------------- - -- RENAME VANTAGE TO VANTAGE_MODE_CATEGORY + -- DROP TABLES CREATED IN PREVIOUS MIGRATION (simpler to just drop and recreate instead of rename everything) ---------------------------------------------------------------------------------------- - ALTER TABLE vantage RENAME COLUMN vantage_id TO vantage_mode_category_id; - ALTER TABLE vantage RENAME TO vantage_mode_category; - ALTER TABLE vantage_mode RENAME COLUMN vantage_id TO vantage_mode_category_id; + -- Drop the triggers first + DROP TRIGGER IF EXISTS audit_vantage ON biohub.vantage; + DROP TRIGGER IF EXISTS journal_vantage ON biohub.vantage; + DROP TRIGGER IF EXISTS audit_vantage_mode ON biohub.vantage_mode; + DROP TRIGGER IF EXISTS journal_vantage_mode ON biohub.vantage_mode; + DROP TRIGGER IF EXISTS audit_vantage_mode_method ON biohub.vantage_mode_method; + DROP TRIGGER IF EXISTS journal_vantage_mode_method ON biohub.vantage_mode_method; + DROP TRIGGER IF EXISTS audit_method_technique_vantage_mode ON biohub.method_technique_vantage_mode; + DROP TRIGGER IF EXISTS journal_method_technique_vantage_mode ON biohub.method_technique_vantage_mode; + + -- Drop the indexes + DROP INDEX IF EXISTS biohub.vantage_nuk1; + DROP INDEX IF EXISTS biohub.vantage_mode_nuk1; + DROP INDEX IF EXISTS biohub.vantage_mode_method_nuk1; + DROP INDEX IF EXISTS biohub.method_technique_vantage_mode_uk1; + + -- Drop the foreign key constraints + ALTER TABLE biohub.vantage_mode_method DROP CONSTRAINT IF EXISTS vantage_mode_method_fk1; + ALTER TABLE biohub.vantage_mode_method DROP CONSTRAINT IF EXISTS vantage_mode_method_fk2; + ALTER TABLE biohub.method_technique_vantage_mode DROP CONSTRAINT IF EXISTS method_technique_vantage_mode_fk1; + ALTER TABLE biohub.method_technique_vantage_mode DROP CONSTRAINT IF EXISTS method_technique_vantage_mode_fk2; + + -- Drop the tables + DROP TABLE IF EXISTS biohub.vantage_mode_method CASCADE; + DROP TABLE IF EXISTS biohub.vantage_mode CASCADE; + DROP TABLE IF EXISTS biohub.vantage CASCADE; + DROP TABLE IF EXISTS biohub.method_technique_vantage_mode CASCADE; + + -- Drop the views + DROP VIEW IF EXISTS biohub_dapi_v1.vantage CASCADE; + DROP VIEW IF EXISTS biohub_dapi_v1.vantage_mode CASCADE; + DROP VIEW IF EXISTS biohub_dapi_v1.vantage_mode_method CASCADE; + DROP VIEW IF EXISTS biohub_dapi_v1.method_technique CASCADE; + DROP VIEW IF EXISTS biohub_dapi_v1.method_technique_vantage_mode CASCADE; ---------------------------------------------------------------------------------------- - -- UPDATE FOREIGN KEYS + -- ADD NEW VANTAGE-RELATED TABLES (same as previous migration, but updated names) ---------------------------------------------------------------------------------------- + SET SEARCH_PATH=biohub; + + CREATE TABLE vantage_category ( + vantage_category_id integer GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), + name varchar(50) NOT NULL, + description varchar(1000), + record_end_date date, + create_date timestamptz(6) DEFAULT now() NOT NULL, + create_user integer NOT NULL, + update_date timestamptz(6), + update_user integer, + revision_count integer DEFAULT 0 NOT NULL, + CONSTRAINT vantage_category_pk PRIMARY KEY (vantage_category_id) + ); + + COMMENT ON TABLE vantage_category IS 'vantage_categorys that vantage_category_mode records belong to, like categories of modes.'; + COMMENT ON COLUMN vantage_category.vantage_category_id IS 'System generated surrogate primary key identifier.'; + COMMENT ON COLUMN vantage_category.name IS 'The name of the record.'; + COMMENT ON COLUMN vantage_category.description IS 'The description of the record.'; + COMMENT ON COLUMN vantage_category.record_end_date IS 'Record level end date.'; + COMMENT ON COLUMN vantage_category.create_date IS 'The datetime the record was created.'; + COMMENT ON COLUMN vantage_category.create_user IS 'The id of the user who created the record as identified in the system user table.'; + COMMENT ON COLUMN vantage_category.update_date IS 'The datetime the record was updated.'; + COMMENT ON COLUMN vantage_category.update_user IS 'The id of the user who updated the record as identified in the system user table.'; + COMMENT ON COLUMN vantage_category.revision_count IS 'Revision count used for concurrency control.'; + + -- Triggers, indexes + + -- Add unique end-date key constraint (don't allow 2 records with the same name and a NULL record_end_date) + CREATE UNIQUE INDEX vantage_category_nuk1 ON vantage_category(name, (record_end_date is NULL)) where record_end_date is null; + + -- Add audit/journal triggers + CREATE TRIGGER audit_vantage_category BEFORE INSERT OR UPDATE OR DELETE ON vantage_category for each ROW EXECUTE PROCEDURE tr_audit_trigger(); + CREATE TRIGGER journal_vantage_category AFTER INSERT OR UPDATE OR DELETE ON vantage_category for each ROW EXECUTE PROCEDURE tr_journal_trigger(); + + ------- + + CREATE TABLE vantage ( + vantage_id integer GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), + vantage_category_id integer NOT NULL, + name varchar(50) NOT NULL, + description varchar(1000), + record_end_date date, + create_date timestamptz(6) DEFAULT now() NOT NULL, + create_user integer NOT NULL, + update_date timestamptz(6), + update_user integer, + revision_count integer DEFAULT 0 NOT NULL, + CONSTRAINT vantage_pk PRIMARY KEY (vantage_id) + ); + + COMMENT ON TABLE vantage IS 'Vantage mode options that can be made available for method lookup options.'; + COMMENT ON COLUMN vantage.vantage_id IS 'System generated surrogate primary key identifier.'; + COMMENT ON COLUMN vantage.vantage_category_id IS 'The vantage category of the record.'; + COMMENT ON COLUMN vantage.name IS 'The name of the record.'; + COMMENT ON COLUMN vantage.description IS 'The description of the record.'; + COMMENT ON COLUMN vantage.record_end_date IS 'Record level end date.'; + COMMENT ON COLUMN vantage.create_date IS 'The datetime the record was created.'; + COMMENT ON COLUMN vantage.create_user IS 'The id of the user who created the record as identified in the system user table.'; + COMMENT ON COLUMN vantage.update_date IS 'The datetime the record was updated.'; + COMMENT ON COLUMN vantage.update_user IS 'The id of the user who updated the record as identified in the system user table.'; + COMMENT ON COLUMN vantage.revision_count IS 'Revision count used for concurrency control.'; + + -- Add unique end-date key constraint (don't allow 2 records with the same name and a NULL record_end_date) + CREATE UNIQUE INDEX vantage_nuk1 ON vantage(vantage_id, name, (record_end_date is NULL)) where record_end_date is null; + + -- Add indexes for foreign keys + ALTER TABLE vantage ADD CONSTRAINT vantage_fk1 + FOREIGN KEY (vantage_category_id) + REFERENCES vantage_category(vantage_category_id); + + -- Add foreign key index + CREATE INDEX vantage_idx1 ON vantage_category(vantage_category_id); + + -- Add audit/journal triggers + CREATE TRIGGER audit_vantage BEFORE INSERT OR UPDATE OR DELETE ON vantage for each ROW EXECUTE PROCEDURE tr_audit_trigger(); + CREATE TRIGGER journal_vantage AFTER INSERT OR UPDATE OR DELETE ON vantage for each ROW EXECUTE PROCEDURE tr_journal_trigger(); + + ------- + + CREATE TABLE vantage_method ( + vantage_method_id integer GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), + vantage_id integer NOT NULL, + method_lookup_id integer NOT NULL, + description varchar(1000), + record_end_date date, + create_date timestamptz(6) DEFAULT now() NOT NULL, + create_user integer NOT NULL, + update_date timestamptz(6), + update_user integer, + revision_count integer DEFAULT 0 NOT NULL, + CONSTRAINT vantage_method_pk PRIMARY KEY (vantage_method_id) + ); + + COMMENT ON TABLE vantage_method IS 'Join table indicating which vantage modes apply to which method lookup options.'; + COMMENT ON COLUMN vantage_method.vantage_method_id IS 'System generated surrogate primary key identifier.'; + COMMENT ON COLUMN vantage_method.vantage_id IS 'The vantage mode option of the record.'; + COMMENT ON COLUMN vantage_method.method_lookup_id IS 'The method lookup option of the record.'; + COMMENT ON COLUMN vantage_method.description IS 'The description of the record.'; + COMMENT ON COLUMN vantage_method.record_end_date IS 'Record level end date.'; + COMMENT ON COLUMN vantage_method.create_date IS 'The datetime the record was created.'; + COMMENT ON COLUMN vantage_method.create_user IS 'The id of the user who created the record as identified in the system user table.'; + COMMENT ON COLUMN vantage_method.update_date IS 'The datetime the record was updated.'; + COMMENT ON COLUMN vantage_method.update_user IS 'The id of the user who updated the record as identified in the system user table.'; + COMMENT ON COLUMN vantage_method.revision_count IS 'Revision count used for concurrency control.'; + + -- Add unique end-date key constraint (don't allow 2 records with the same vantage_id, method_lookup_id and a NULL record_end_date) + CREATE UNIQUE INDEX vantage_method_nuk1 ON vantage_method (vantage_id, method_lookup_id, (record_end_date is NULL)) where record_end_date is null; + + -- Add foreign key constraints + ALTER TABLE vantage_method ADD CONSTRAINT vantage_method_fk1 + FOREIGN KEY (method_lookup_id) + REFERENCES method_lookup (method_lookup_id); + + ALTER TABLE vantage_method ADD CONSTRAINT vantage_method_fk2 + FOREIGN KEY (vantage_id) + REFERENCES vantage (vantage_id); + + -- Add indexes for foreign keys + CREATE INDEX vantage_method_idx1 ON vantage_method(method_lookup_id); + + CREATE INDEX vantage_method_idx2 ON vantage_method(vantage_id); - ALTER TABLE vantage_mode DROP CONSTRAINT vantage_mode_fk1; + -- Add audit/journal triggers + CREATE TRIGGER audit_vantage_method BEFORE INSERT OR UPDATE OR DELETE ON vantage_method for each ROW EXECUTE PROCEDURE tr_audit_trigger(); + CREATE TRIGGER journal_vantage_method AFTER INSERT OR UPDATE OR DELETE ON vantage_method for each ROW EXECUTE PROCEDURE tr_journal_trigger(); - ALTER TABLE vantage_mode ADD CONSTRAINT vantage_mode_fk1 - FOREIGN KEY (vantage_mode_category_id) - REFERENCES vantage_mode_category(vantage_mode_category_id); + ------- + + CREATE TABLE method_technique_vantage ( + method_technique_vantage_id integer GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), + method_technique_id integer NOT NULL, + vantage_method_id integer NOT NULL, + description varchar(1000), + record_end_date date, + create_date timestamptz(6) DEFAULT now() NOT NULL, + create_user integer NOT NULL, + update_date timestamptz(6), + update_user integer, + revision_count integer DEFAULT 0 NOT NULL, + CONSTRAINT method_technique_vantage_pk PRIMARY KEY (method_technique_vantage_id) + ); + + COMMENT ON TABLE method_technique_vantage IS 'Join table applying vantage modes to techniques.'; + COMMENT ON COLUMN method_technique_vantage.method_technique_vantage_id IS 'System generated surrogate primary key identifier.'; + COMMENT ON COLUMN method_technique_vantage.method_technique_id IS 'The method technique of the record.'; + COMMENT ON COLUMN method_technique_vantage.vantage_method_id IS 'The vantage mode of the record.'; + COMMENT ON COLUMN method_technique_vantage.description IS 'The description of the record.'; + COMMENT ON COLUMN method_technique_vantage.record_end_date IS 'Record level end date.'; + COMMENT ON COLUMN method_technique_vantage.create_date IS 'The datetime the record was created.'; + COMMENT ON COLUMN method_technique_vantage.create_user IS 'The id of the user who created the record as identified in the system user table.'; + COMMENT ON COLUMN method_technique_vantage.update_date IS 'The datetime the record was updated.'; + COMMENT ON COLUMN method_technique_vantage.update_user IS 'The id of the user who updated the record as identified in the system user table.'; + COMMENT ON COLUMN method_technique_vantage.revision_count IS 'Revision count used for concurrency control.'; + + -- Add unique index + CREATE UNIQUE INDEX method_technique_vantage_uk1 ON method_technique_vantage (method_technique_id, vantage_method_id); + + -- Add foreign key constraints + ALTER TABLE method_technique_vantage ADD CONSTRAINT method_technique_vantage_fk1 + FOREIGN KEY (method_technique_id) + REFERENCES method_technique (method_technique_id); + + ALTER TABLE method_technique_vantage ADD CONSTRAINT method_technique_vantage_fk2 + FOREIGN KEY (vantage_method_id) + REFERENCES vantage_method (vantage_method_id); + + -- Add indexes for foreign keys + CREATE INDEX method_technique_vantage_idx1 ON method_technique_vantage(method_technique_id); + + CREATE INDEX method_technique_vantage_idx2 ON method_technique_vantage(vantage_method_id); + + -- Add audit/journal triggers + CREATE TRIGGER audit_method_technique_vantage BEFORE INSERT OR UPDATE OR DELETE ON method_technique_vantage for each ROW EXECUTE PROCEDURE tr_audit_trigger(); + CREATE TRIGGER journal_method_technique_vantage AFTER INSERT OR UPDATE OR DELETE ON method_technique_vantage for each ROW EXECUTE PROCEDURE tr_journal_trigger(); ---------------------------------------------------------------------------------------- - -- UPDATE INDEXES + -- POPULATE INITIAL VANTAGE TABLE VALUES ---------------------------------------------------------------------------------------- - DROP INDEX IF EXISTS vantage_mode_idx1; - DROP INDEX IF EXISTS vantage_mode_nuk1; + INSERT INTO + vantage_category (name, description) + VALUES + ('air', 'View from an aircraft or drone.'), + ('arboreal', 'View from the tree canopy.'), + ('water', 'View from a body of water.'), + ('benthic', 'View from the bottom of a waterbody.'), + ('ground', 'View from the ground.'); + + INSERT INTO + vantage (vantage_category_id, name, description) + VALUES + -- Air Vantage_category Modes + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'air'), 'helicopter', 'View from a helicopter.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'air'), 'plane', 'View from a plane.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'air'), 'drone', 'View from a drone.'), + + -- Arboreal Vantage_category Modes + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'arboreal'), 'stationary fixture', 'View from a stationary fixture in the tree canopy.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'arboreal'), 'climbing', 'View from climbing in the tree canopy.'), + + -- Water Vantage_category Modes + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'water'), 'stationary fixture', 'At a fixed position in or under the water.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'water'), 'boat', 'View from a boat or canoe.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'water'), 'kayak or canoe', 'View from a kayak or canoe.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'water'), 'submersible', 'View from an underwater submersible.'), + + -- Ground Vantage_category Modes + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'stationary fixture', 'At a fixed position on the ground.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'foot', 'On foot.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'on-road vehicle', 'In a truck, car, or similar on-road vehicle.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'off-road vehicle', 'On a quad, dirtbike, or similar all-terrain vehicle.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'horseback', 'On horseback.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'snowmobile', 'On a snowmobile.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'ground'), 'bike', 'On a bicycle.'), + + -- Benthic Vantage_category Modes + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'benthic'), 'stationary fixture', 'At a fixed position on the bottom of a waterbody.'), + ((SELECT vantage_category_id FROM vantage_category WHERE name = 'benthic'), 'submersible', 'View from a submersible on the bottom of a waterbody.'); + + INSERT INTO + vantage_method (method_lookup_id, vantage_id) + VALUES + -- Visual Encounter Method + -- Air Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'helicopter' AND vc.name = 'air')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'plane' AND vc.name = 'air')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'drone' AND vc.name = 'air')), + + -- Arboreal Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'stationary fixture' AND vc.name = 'arboreal')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'climbing' AND vc.name = 'arboreal')), + + -- Water Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'boat' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'kayak or canoe' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'submersible' AND vc.name = 'water')), + + -- Ground Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'foot' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'on-road vehicle' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'off-road vehicle' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'horseback' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'snowmobile' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'visual encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'bike' AND vc.name = 'ground')), + + -- Audio Encounter Method + -- Air Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'helicopter' AND vc.name = 'air')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'plane' AND vc.name = 'air')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'drone' AND vc.name = 'air')), + + -- Arboreal Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'stationary fixture' AND vc.name = 'arboreal')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'climbing' AND vc.name = 'arboreal')), + + -- Water Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'boat' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'kayak or canoe' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'submersible' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'stationary fixture' AND vc.name = 'water')), + + -- Ground Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'foot' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'on-road vehicle' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'off-road vehicle' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'horseback' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'snowmobile' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'audio encounter'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'bike' AND vc.name = 'ground')), + + -- Radar Method + -- Air Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'helicopter' AND vc.name = 'air')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'plane' AND vc.name = 'air')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'drone' AND vc.name = 'air')), + + -- Ground Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'foot' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'on-road vehicle' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'off-road vehicle' AND vc.name = 'ground')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'stationary fixture' AND vc.name = 'ground')), + + -- Water Vantage Modes + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'boat' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'kayak or canoe' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'submersible' AND vc.name = 'water')), + ((SELECT method_lookup_id FROM method_lookup WHERE LOWER(name) = 'radar'), + (SELECT vantage_id FROM vantage v JOIN vantage_category vc ON vc.vantage_category_id = v.vantage_category_id WHERE v.name = 'stationary fixture' AND vc.name = 'water')); - -- indexes on vantage_mode - CREATE UNIQUE INDEX vantage_mode_nuk1 ON vantage_mode(vantage_mode_category_id, name, (record_end_date is NULL)) where record_end_date is null; - CREATE INDEX vantage_mode_idx1 ON vantage_mode(vantage_mode_category_id); - ---------------------------------------------------------------------------------------- - -- UPDATE VIEWS + -- ADD/UPDATE VIEWS ---------------------------------------------------------------------------------------- + SET SEARCH_PATH=biohub_dapi_v1; - SET SEARCH_PATH = biohub_dapi_v1; + CREATE OR REPLACE VIEW vantage_category AS SELECT * FROM biohub.vantage_category; + CREATE OR REPLACE VIEW vantage AS SELECT * FROM biohub.vantage; + CREATE OR REPLACE VIEW vantage_method AS SELECT * FROM biohub.vantage_method; + CREATE OR REPLACE VIEW method_technique AS SELECT * FROM biohub.method_technique; + CREATE OR REPLACE VIEW method_technique_vantage AS SELECT * FROM biohub.method_technique_vantage; - CREATE OR REPLACE VIEW vantage_mode_category AS SELECT * FROM biohub.vantage_mode_category; - CREATE OR REPLACE VIEW vantage_mode AS SELECT * FROM biohub.vantage_mode; `); } export async function down(knex: Knex): Promise { + await knex.raw(``); }