Skip to content

Commit

Permalink
Merge pull request #359 from aayushgauba/main
Browse files Browse the repository at this point in the history
fix: species v2
  • Loading branch information
dadiorchen authored Sep 27, 2023
2 parents 9ec872f + 7883430 commit cb251a1
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 196 deletions.
221 changes: 87 additions & 134 deletions server/infra/database/SpeciesRepositoryV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,146 +6,99 @@ import Session from './Session';
export default class SpeciesRepositoryV2 extends BaseRepository<Species> {
constructor(session: Session) {
super('tree_species', session);
this.tableName = 'herbarium.species';
}

async getByOrganization(organization_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
species_id as id, total, ts.name, ts.desc
FROM
(
SELECT
ss.species_id, count(ss.species_id) as total
from webmap.species_stat ss
WHERE
ss.planter_id IN (
SELECT
id
FROM planter p
WHERE
p.organization_id in ( SELECT entity_id from getEntityRelationshipChildren(${organization_id}))
)
OR
ss.planting_organization_id = ${organization_id}
GROUP BY ss.species_id
) s_count
JOIN tree_species ts
ON ts.id = s_count.species_id
ORDER BY total DESC
LIMIT ${limit}
OFFSET ${offset}
`;
const object = await this.session.getDB().raw(sql);
return object.rows;
}
filterWhereBuilder(object, builder) {
const result = builder;
const {
whereNulls = [],
whereNotNulls = [],
whereIns = [],
...parameters
} = object;

async countByOrganization(organization_id: number) {
const totalSql = `
SELECT
species_id as id, total, ts.name, ts.desc
FROM
(
SELECT
ss.species_id, count(ss.species_id) as total
from webmap.species_stat ss
WHERE
ss.planter_id IN (
SELECT
id
FROM planter p
WHERE
p.organization_id in ( SELECT entity_id from getEntityRelationshipChildren(${organization_id}))
)
OR
ss.planting_organization_id = ${organization_id}
GROUP BY ss.species_id
) s_count
JOIN tree_species ts
ON ts.id = s_count.species_id
ORDER BY total DESC
`;
const total = await this.session.getDB().raw(totalSql);
return parseInt(total.rows.length);
}
result.whereNot(`${this.tableName}.status`, 'deleted');
whereNotNulls.forEach((whereNot) => {
result.whereNotNull(whereNot);
});

async getByPlanter(planter_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
species_id as id, total, ts.name, ts.desc
FROM
(
SELECT
ss.species_id, count(ss.species_id) as total
from webmap.species_stat ss
WHERE
ss.planter_id = ${planter_id}
GROUP BY ss.species_id
) s_count
JOIN tree_species ts
ON ts.id = s_count.species_id
ORDER BY total DESC
LIMIT ${limit}
OFFSET ${offset}
`;
const object = await this.session.getDB().raw(sql);
return object.rows;
}
whereNulls.forEach((whereNull) => {
result.whereNull(whereNull);
});

async getByGrower(grower_id: string, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
species_id as id, total, ts.name, ts.desc
FROM
(
SELECT
ss.species_id, count(ss.species_id) as total
from webmap.species_stat ss
WHERE
ss.planter_id IN (
SELECT
id
FROM planter p
WHERE
p.grower_account_uuid = '${grower_id}'
)
whereIns.forEach((whereIn) => {
result.whereIn(whereIn.field, whereIn.values);
});

GROUP BY
ss.species_id
) s_count
JOIN tree_species ts
ON ts.id = s_count.species_id
ORDER BY total DESC
LIMIT ${limit}
OFFSET ${offset}
`;
const object = await this.session.getDB().raw(sql);
return object.rows;
}
const filterObject = { ...parameters };

if (filterObject.id) {
result.where(`${this.tableName}.id`, '=', filterObject.id);
delete filterObject.id;
}

if (filterObject.scientific_name) {
result.where(
`${this.tableName}.scientific_name`,
'ilike',
`%${filterObject.scientific_name}%`,
);
delete filterObject.scientific_name;
}

if (filterObject.organization_id) {
result.where(
`${this.tableName}.organization_id`,
'=',
`${filterObject.organization_id}`,
);
delete filterObject.organization_id;
}

// if 'captures_amount_max' === 0, 'captures_amount_min' can be only 0.
if (filterObject.captures_amount_max === 0) {
result.whereNull('c.captures_count');
delete filterObject.captures_amount_min;
delete filterObject.captures_amount_max;
}

// if 'captures_amount_max' === 0 and 'captures_amount_max' is not defined, all results should be returned.
if (
filterObject.captures_amount_min === 0 &&
!filterObject.captures_amount_max
) {
delete filterObject.captures_amount_min;
delete filterObject.captures_amount_max;
}

if (filterObject.captures_amount_min) {
result.where(
`c.captures_count`,
'>=',
`${filterObject.captures_amount_min}`,
);
delete filterObject.captures_amount_min;
}

if (filterObject.captures_amount_max) {
result.where(
`c.captures_count`,
'<=',
`${filterObject.captures_amount_max}`,
);
delete filterObject.captures_amount_max;
}

if (filterObject.wallet) {
result.where(
`${this.tableName}.wallet`,
'ilike',
`%${filterObject.wallet}%`,
);
delete filterObject.wallet;
}

async getByWallet(wallet_id: string, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
species_id as id, total, ts.name, ts.desc
FROM
(
SELECT
ss.species_id, count(ss.species_id) as total
from webmap.species_stat ss
WHERE
ss.wallet_id::text = '${wallet_id}'
GROUP BY ss.species_id
) s_count
JOIN tree_species ts
ON ts.id = s_count.species_id
ORDER BY total DESC
LIMIT ${limit}
OFFSET ${offset}
`;
const object = await this.session.getDB().raw(sql);
return object.rows;
result.where(filterObject);
}
}
16 changes: 16 additions & 0 deletions server/interfaces/SpeciesFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import DbModel from './DbModel';

interface SpeciesFilter extends DbModel {
id?: number;
scientific_name?: string;
description?: string;
limit?: number;
offset?: number;
keyword?: string;
morphology?: string;
range?: string;
created_at?: string;
updated_at?: string;
}

export default SpeciesFilter;
61 changes: 6 additions & 55 deletions server/models/SpeciesV2.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,27 @@
import log from 'loglevel';
import FilterOptions from 'interfaces/FilterOptions';
import Species from 'interfaces/Species';
import SpeciesFilter from 'interfaces/SpeciesFilter';
import { delegateRepository } from '../infra/database/delegateRepository';
import SpeciesRepositoryV2 from '../infra/database/SpeciesRepositoryV2';

type Filter = Partial<{
planter_id: number;
organization_id: number;
wallet_id: string;
grower_id: string;
}>;

function getByFilter(
speciesRepository: SpeciesRepositoryV2,
): (filter: Filter, options: FilterOptions) => Promise<Species[]> {
return async function (filter: Filter, options: FilterOptions) {
if (filter.organization_id) {
log.warn('using org filter...');
const trees = await speciesRepository.getByOrganization(
filter.organization_id,
options,
);
return trees;
}
if (filter.planter_id) {
log.warn('using planter filter...');
const trees = await speciesRepository.getByPlanter(
filter.planter_id,
options,
);
return trees;
}

if (filter.wallet_id) {
log.warn('using wallet filter...');
const trees = await speciesRepository.getByWallet(
filter.wallet_id,
options,
);
return trees;
}
if (filter.grower_id) {
log.warn('using grower filter...');
const trees = await speciesRepository.getByGrower(
filter.grower_id,
options,
);
return trees;
}

const trees = await speciesRepository.getByFilter(filter, options);
return trees;
};
}
function countByFilter(
speciesRepository: SpeciesRepositoryV2,
): (filter: Filter) => Promise<number> {
return async function (filter: Filter) {
if (filter.organization_id) {
log.warn('using org filter...');
const total = await speciesRepository.countByOrganization(
filter.organization_id,
);
return total;
}
const total = await speciesRepository.countByFilter(filter);
return total;
): (filter: SpeciesFilter, options: FilterOptions) => Promise<SpeciesFilter[]> {
return async function (filter: SpeciesFilter, options: FilterOptions) {
const result = await speciesRepository.getByFilter(filter, options);
return result;
};
}

export default {
getById: delegateRepository<SpeciesRepositoryV2, Species>('getById'),
getByGrower: delegateRepository<SpeciesRepositoryV2, Species>('getByGrower'),
getByFilter,
countByFilter,
};
17 changes: 10 additions & 7 deletions server/routers/speciesRouterV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import SpeciesModel from '../models/SpeciesV2';
const router = express.Router();
type Filter = Partial<{
planter_id: number;
organization_id: number;
organization_id: string;
wallet_id: string;
grower_id: string;
}>;

router.get(
'/:id',
handlerWrapper(async (req, res) => {
Joi.assert(req.params.id, Joi.number().required());
Joi.assert(req.params.id, Joi.string().uuid().required());
const repo = new SpeciesRepositoryV2(new Session());
const exe = SpeciesModel.getById(repo);
const result = await exe(req.params.id);
Expand All @@ -32,12 +32,16 @@ router.get(
Joi.assert(
req.query,
Joi.object().keys({
organization_id: Joi.number().integer().min(0),
planter_id: Joi.number().integer().min(0),
grower_id: Joi.string().guid(),
wallet_id: Joi.string(),
limit: Joi.number().integer().min(1).max(1000),
offset: Joi.number().integer().min(0),
keyword: Joi.string(),
id: Joi.string().uuid(),
scientific_name: Joi.string(),
description: Joi.string(),
morphology: Joi.string(),
range: Joi.string(),
created_at: Joi.string(),
updated_at: Joi.string(),
}),
);
const {
Expand Down Expand Up @@ -66,7 +70,6 @@ router.get(
});
log.warn('species filter:', filter, 'took time:', Date.now() - begin, 'ms');
res.send({
total: await SpeciesModel.countByFilter(repo)(filter),
offset,
limit,
species: result,
Expand Down

0 comments on commit cb251a1

Please sign in to comment.