diff --git a/__tests__/e2e/countries.spec.ts b/__tests__/e2e/countries.spec.ts index c052c492..2573f71e 100644 --- a/__tests__/e2e/countries.spec.ts +++ b/__tests__/e2e/countries.spec.ts @@ -1,5 +1,6 @@ import supertest from 'supertest'; import app from '../../server/app'; +import seed from '../seed'; describe('', () => { it('countries/6632544', async () => { @@ -58,4 +59,22 @@ describe('', () => { }, 1000 * 60, ); + + it('countries/v2/leaderboard', async () => { + const response = await seed + .clear() + .then(async () => + seed + .seed() + .then(async () => supertest(app).get('/countries/v2/leaderboard')), + ); + expect(response.status).toBe(200); + expect(response.body.countries[0]).toMatchObject({ + id: 6632357, + name: 'United States', + planted: '2', + centroid: expect.stringMatching(/coordinates/), + }); + await seed.clear(); + }); }); diff --git a/__tests__/seed.js b/__tests__/seed.js new file mode 100644 index 00000000..90f7eddf --- /dev/null +++ b/__tests__/seed.js @@ -0,0 +1,68 @@ +import { knex } from 'knex'; +import log from 'loglevel'; +const uuid = require('uuid'); + +const connection = process.env.DATABASE_URL; + +!connection && log.warn('env var DATABASE_URL not set'); + +const knexConfig = { + client: 'pg', + // debug: process.env.NODE_LOG_LEVEL === 'debug', + debug: true, + connection, + pool: { min: 0, max: 10 }, +}; + +const dataRawCaptureFeature = [ + { + id: uuid.v4(), + lat: '41.50414585511928', + lon: '-75.66275380279951', + location: '0101000020E6100000B514ED8E6AEA52C05D13F4D987C04440', + field_user_id: 5127, + field_username: 'test', + created_at: new Date().toUTCString(), + updated_at: new Date().toUTCString(), + }, + { + id: uuid.v4(), + lat: '40.50414585511928', + lon: '-75.66275380279951', + location: '0101000020E6100000B514ED8E6AEA52C05D13F4D987C04440', + field_user_id: 5127, + field_username: 'test', + created_at: new Date().toUTCString(), + updated_at: new Date().toUTCString(), + }, + { + id: uuid.v4(), + lat: '57.57641356164619', + lon: '-113.11416324692146', + location: '0101000020E6100000B4FB5C734E475CC0E21E6AEBC7C94C40', + field_user_id: 5127, + field_username: 'test', + created_at: new Date().toUTCString(), + updated_at: new Date().toUTCString(), + }, +]; + +async function seed() { + knexConfig.searchPath = [process.env.DATABASE_SCHEMA, 'webmap']; + const serverCon = knex(knexConfig); + const response = await serverCon.transaction(async (trx) => { + return await trx.insert(dataRawCaptureFeature).into('raw_capture_feature'); + }); + serverCon.destroy(); + return response; +} + +async function clear() { + knexConfig.searchPath = [process.env.DATABASE_SCHEMA, 'webmap']; + const serverCon = knex(knexConfig); + const response = await serverCon('raw_capture_feature').del(); + serverCon.destroy(); + return response; +} + +export default { clear, seed }; diff --git a/server/infra/database/CountryRepositoryV2.ts b/server/infra/database/CountryRepositoryV2.ts index 9e67d746..e9434592 100644 --- a/server/infra/database/CountryRepositoryV2.ts +++ b/server/infra/database/CountryRepositoryV2.ts @@ -58,4 +58,27 @@ export default class CountryRepositoryV2 extends BaseRepository { } return object.rows; } + + + async getLeaderBoard(top = 10) { + const sql = ` + select r.*, public.region.name, ST_AsGeoJSON(public.region.centroid) as centroid from ( + select count(public.region.id) as planted, public.region.id + from webmap.raw_capture_feature + LEFT JOIN public.region + on ST_WITHIN(webmap.raw_capture_feature.location, public.region.geom) + left join public.region_type + on public.region.type_id = public.region_type.id + where + public.region_type.type = 'country' + group by public.region.id + order by count(public.region.id) desc + limit ${top} + ) r left join public.region + on r.id = public.region.id + ; + `; + const object = await this.session.getDB().raw(sql); + return object.rows; + } } diff --git a/server/models/CountryV2.ts b/server/models/CountryV2.ts index 1cf03570..1dc97791 100644 --- a/server/models/CountryV2.ts +++ b/server/models/CountryV2.ts @@ -17,4 +17,7 @@ export default { getCountries, getById: delegateRepository('getById'), getByFilter: delegateRepository('getByFilter'), + getLeaderBoard: delegateRepository( + 'getLeaderBoard', + ), }; diff --git a/server/routers/countriesRouter.ts b/server/routers/countriesRouter.ts index 5c64b2b8..3d572f27 100644 --- a/server/routers/countriesRouter.ts +++ b/server/routers/countriesRouter.ts @@ -9,6 +9,19 @@ import CountryModelV2 from '../models/CountryV2'; const router = express.Router(); +router.get( + '/v2/leaderboard', + handlerWrapper(async (req, res) => { + const repo = new CountryRepositoryV2(new Session()); + const exe = CountryModelV2.getLeaderBoard(repo); + const result = await exe(req.params.id); + res.send({ + countries: result, + }); + res.end(); + }), +); + router.get( '/v2/:id', handlerWrapper(async (req, res) => {