Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update routes from benefit #278

Merged
merged 1 commit into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions backend/database/seeders/benefitsProducts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import db from '../../src/schemas';
import { BenefitProduct } from '../../src/schemas/benefitProducts';

const list = [
{
productsId: 5,
benefitsId: 1,
amount: 2
},
{
productsId: 6,
benefitsId: 2,
amount: 2
},
{
productsId: 7,
benefitsId: 2,
amount: 2
},
{
productsId: 8,
benefitsId: 2,
amount: 2
}
] as BenefitProduct[];

/**
* Seed the benefits table
*/
const seed = async () => {
const alreadyCreated = await db.benefitProducts.findAll();
if (alreadyCreated.length < list.length) {
await db.benefitProducts.bulkCreate(list);
console.log(`[seed] Benefits: Seeded successfully - ${list.length} new created`);
} else {
console.log(`[seed] Benefits: Nothing to seed`);
}
};

export default { seed, groupList: list };
2 changes: 2 additions & 0 deletions backend/database/seeders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import families from './families';
import consumptions from './consumptions';
import dependents from './dependents';
import products from './products';
import benefitsProducts from './benefitsProducts';

/**
* Seed all tables
Expand All @@ -26,6 +27,7 @@ const seedAll = async () => {
await dependents.seed();
await consumptions.seed();
await products.seed();
await benefitsProducts.seed();
} else {
// Production seed - one city and admin user
await cities.seed();
Expand Down
16 changes: 16 additions & 0 deletions backend/src/models/benefitProducts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ export const getAll = (): Promise<SequelizeBenefitProduct[]> => {
});
};

/**
* Get all products associated to benefit
* @param benefitsId unique ID of the desired benefit
* @returns Promise<Item>
*/
export const getAllProductsByBenefitId = (
benefitsId: NonNullable<BenefitProduct['id']>
): Promise<SequelizeBenefitProduct[]> => {
return db.benefitProducts.findAll({
where: {
benefitsId
},
include: [{ model: db.products, as: 'products' }]
});
};

/**
* Get a single item using the unique ID
* @param id unique ID of the desired item
Expand Down
77 changes: 77 additions & 0 deletions backend/src/models/benefits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@ export const getAll = (cityId: NonNullable<City['id']>): Promise<SequelizeBenefi
return db.benefits.findAll({ include: [{ model: db.institutions, as: 'institution', where: { cityId } }] });
};

/**
* Get all items on the table without any filter
* @param cityId logged user city ID
* @returns Promise<List of items>
*/
export const getAllWithProduct = (cityId: NonNullable<City['id']>): Promise<any> => {
return db.benefits.findAll({
include: [
{ model: db.institutions, as: 'institution', where: { cityId } },
{ model: db.benefitProducts, as: 'benefitProduct', include: [{ model: db.products, as: 'products' }] }
]
});
};

/**
* Get a single item using the unique ID
* @param id unique ID of the desired item
Expand All @@ -30,6 +44,25 @@ export const create = (values: Benefit | SequelizeBenefit): Promise<SequelizeBen
return db.benefits.create(values);
};

/**
* Function to create a new row on the table using product
* @param values object with the new item data
* @returns Promise<Item>
*/
export const createWithProduct = async (values: Benefit | SequelizeBenefit): Promise<SequelizeBenefit> => {
const created = await db.benefits.create(values);

if (values.products && created) {
const productList = values.products.map((i) => {
i.benefitsId = created.id as number;
return i;
});
db.benefitProducts.bulkCreate(productList);
}

return created;
};

/**
* Function to update a row on the table by the unique ID
* @param id unique ID of the desired item
Expand All @@ -52,6 +85,50 @@ export const updateById = async (
return null;
};

/**
* Function to update a row on the table by the unique ID
* @param id unique ID of the desired item
* @param values object with the new data
* @param cityId logged user city ID
* @returns Promise<Item>
*/
export const updateWithProduct = async (
id: NonNullable<Benefit['id']>,
values: Benefit | SequelizeBenefit,
cityId: NonNullable<City['id']>
): Promise<SequelizeBenefit | null> => {
// Trying to get item on the city
const cityItem = await getById(id, cityId);
if (cityItem) {
// The update return an array [count, item[]], so I'm destructuring to get the updated benefit
const [, [updated]] = await db.benefits.update(values, { where: { id }, returning: true });
const updatedProducts = await db.benefitProducts.findAll({ where: { benefitsId: updated.id as number } });

if (values.products) {
const list = values.products.map((i) => {
i.benefitsId = updated.id as number;
return i;
});
const productToUpdate = list.filter((f) => f.id);
const productToAdd = list.filter((f) => !f.id);
const productToRemove = updatedProducts.filter((a) => {
const index = productToUpdate.find((f) => f.id === a.id);
if (!index) return a;
});

await db.benefitProducts.bulkCreate(productToAdd);

productToRemove.map(async (dt) => {
await db.benefitProducts.destroy({ where: { id: dt.id } });
});
productToUpdate.map(async (up) => {
await db.benefitProducts.update({ amount: up.amount }, { where: { id: up.id } });
});
}
}
return null;
};

/**
* Function to delete a row on the table by the unique ID
* @param id unique ID of the desired item
Expand Down
10 changes: 7 additions & 3 deletions backend/src/routes/benefits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const router = express.Router({ mergeParams: true });
router.get('/', async (req, res) => {
try {
if (!req.user?.cityId) throw Error('User without selected city');
const items = await benefitModel.getAll(req.user.cityId);
const items = await benefitModel.getAllWithProduct(req.user.cityId);
res.send(items);
} catch (error) {
logging.error(error);
Expand Down Expand Up @@ -41,7 +41,9 @@ router.get('/:id', async (req, res) => {
router.post('/', async (req, res) => {
try {
if (!req.user?.cityId) throw Error('User without selected city');
const item = await benefitModel.create(req.body);
let item;
if (req.body.value) item = await benefitModel.create(req.body);
else item = await benefitModel.createWithProduct(req.body);
res.send(item);
} catch (error) {
logging.error(error);
Expand All @@ -55,7 +57,9 @@ router.post('/', async (req, res) => {
router.put('/:id', async (req, res) => {
try {
if (!req.user?.cityId) throw Error('User without selected city');
const item = await benefitModel.updateById(req.params.id, req.body, req.user.cityId);
let item;
if (req.body.value) item = await benefitModel.updateById(req.params.id, req.body, req.user.cityId);
else item = await benefitModel.updateWithProduct(req.params.id, req.body, req.user.cityId);
res.send(item);
} catch (error) {
logging.error(error);
Expand Down
6 changes: 3 additions & 3 deletions backend/src/schemas/benefitProducts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Sequelize, Model, DataTypes, BuildOptions, ModelCtor } from 'sequelize'
// Simple item type
export interface BenefitProduct {
readonly id?: number | string;
productId: number | string;
benefitId: number | string;
productsId: number | string;
benefitsId: number | string;
amount: number;
createdAt?: number | Date | null;
updatedAt?: number | Date | null;
Expand Down Expand Up @@ -49,7 +49,7 @@ export const attributes = {
}
};

const tableName = 'Benefits';
const tableName = 'BenefitProducts';

/**
* Sequelize model initializer function
Expand Down
6 changes: 6 additions & 0 deletions backend/src/schemas/benefits.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Sequelize, Model, DataTypes, BuildOptions, ModelCtor } from 'sequelize';
import { BenefitProduct } from './benefitProducts';

// Simple item type
export interface Benefit {
Expand All @@ -8,6 +9,7 @@ export interface Benefit {
title: string;
month: number;
year: number;
products?: BenefitProduct[];
value?: number;
createdAt?: number | Date | null;
updatedAt?: number | Date | null;
Expand Down Expand Up @@ -76,6 +78,10 @@ export const initBenefitSchema = (sequelize: Sequelize): SequelizeBenefitModel =
foreignKey: 'institutionId',
as: 'institution'
});
Schema.hasMany(models.benefitProducts, {
foreignKey: 'benefitsId',
as: 'benefitProduct'
});
};

return Schema;
Expand Down
8 changes: 8 additions & 0 deletions backend/src/schemas/products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,13 @@ export const initProductSchema = (sequelize: Sequelize): SequelizeProductModel =
// Sequelize relations
// Schema.associate = (models): void => {};

Schema.associate = (models): void => {
// Sequelize relations
Schema.hasMany(models.benefitProducts, {
foreignKey: 'productsId',
as: 'benefitProduct'
});
};

return Schema;
};