Skip to content

Commit

Permalink
fix(fdbs): limit main food record editing
Browse files Browse the repository at this point in the history
  • Loading branch information
lukashroch authored and mucc001 committed Oct 4, 2023
1 parent 1b94693 commit cd8f791
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 55 deletions.
49 changes: 25 additions & 24 deletions apps/admin/src/components/fdbs/attribute-list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<v-switch
v-model="attributes.sameAsBeforeOption"
class="mt-0"
:disabled="isInherited('sameAsBeforeOption')"
:disabled="disabled || isInherited('sameAsBeforeOption')"
:error-messages="errors.get('main.attributes.sameAsBeforeOption')"
hide-details="auto"
:label="$t('fdbs.attributes.sameAsBeforeOption')"
Expand Down Expand Up @@ -77,7 +77,7 @@
:disabled="disabled || isInherited('useInRecipes')"
:error-messages="errors.get('main.attributes.useInRecipes')"
hide-details="auto"
:items="useInRecipeTypes"
:items="useInRecipeTypeItems"
:label="$t('fdbs.attributes.useInRecipes._')"
name="attributes.useInRecipes"
outlined
Expand All @@ -92,13 +92,13 @@

<script lang="ts">
import type { PropType } from 'vue';
import { deepEqual } from 'fast-equals';
import { defineComponent } from 'vue';
import { computed, defineComponent } from 'vue';
import type { Nullable } from '@intake24/common/types';
import type { Errors } from '@intake24/common/util';
import type { AttributeDefaultsAttributes } from '@intake24/db';
import { useInRecipeTypes } from '@intake24/common/types';
import { useI18n } from '@intake24/i18n';
type Attributes = Pick<
AttributeDefaultsAttributes,
Expand Down Expand Up @@ -134,31 +134,32 @@ export default defineComponent({
emits: ['input'],
data() {
setup(props, { emit }) {
const { i18n } = useI18n();
const attributes = computed({
get() {
return props.value;
},
set(val) {
emit('input', val);
},
});
const useInRecipeTypeItems = computed(() =>
Object.values(useInRecipeTypes).map((value) => ({
value,
text: i18n.t(`fdbs.attributes.useInRecipes.${value}`),
}))
);
return {
attributes,
defaultAttributes,
attributes: { ...this.value } as Nullable<Attributes>,
useInRecipeTypes: Object.values(useInRecipeTypes).map((value) => ({
value,
text: this.$t(`fdbs.attributes.useInRecipes.${value}`),
})),
useInRecipeTypeItems,
};
},
watch: {
value(val: Attributes) {
this.attributes = { ...val };
},
attributes: {
handler(val: Attributes, oldVal: Attributes) {
if (deepEqual(oldVal, val)) return;
this.$emit('input', { ...val });
},
deep: true,
},
},
methods: {
isInherited(attribute: AttributeType) {
return this.attributes[attribute] === null;
Expand Down
20 changes: 16 additions & 4 deletions apps/api/src/http/controllers/admin/fdbs/food.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type { Request, Response } from 'express';
import { pick } from 'lodash';

import type { IoC } from '@intake24/api/ioc';
import type { FoodLocalEntry, FoodsResponse } from '@intake24/common/types/http/admin';
import type { FoodInput, FoodLocalEntry, FoodsResponse } from '@intake24/common/types/http/admin';
import type { PaginateQuery } from '@intake24/db';
import { NotFoundError } from '@intake24/api/http/errors';
import { SystemLocale } from '@intake24/db';
import { FoodLocal, SystemLocale } from '@intake24/db';

import { getAndCheckAccess } from '../securable.controller';

Expand Down Expand Up @@ -51,13 +51,25 @@ const adminFoodController = ({ adminFoodService }: Pick<IoC, 'adminFoodService'>
};

const update = async (
req: Request<{ foodId: string; localeId: string }>,
req: Request<{ foodId: string; localeId: string }, any, FoodInput>,
res: Response<FoodLocalEntry>
): Promise<void> => {
const { code } = await getAndCheckAccess(SystemLocale, 'food-list', req);
const { foodId } = req.params;

const foodLocal = await adminFoodService.updateFood(foodId, code, req.body);
const { aclService } = req.scope.cradle;
const { main, ...rest } = req.body;

const canUpdateMain =
main?.code &&
((await aclService.hasPermission('locales|food-list')) ||
(await FoodLocal.count({ where: { foodCode: main.code } })) === 1);

const foodLocal = await adminFoodService.updateFood(
foodId,
code,
canUpdateMain ? req.body : rest
);
if (!foodLocal) throw new NotFoundError();

res.json(foodLocal);
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/http/requests/admin/fdbs/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const categories: Schema = {
in: ['body'],
errorMessage: typeErrorMessage('array._'),
isArray: { bail: true },
optional: true,
custom: {
options: async (value: any[], meta): Promise<void> => {
if (value.some(({ code }) => !code || typeof code !== 'string'))
Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/http/requests/admin/fdbs/foods/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ const defaults: Schema = {
isString: true,
isEmpty: { negated: true },
isLength: { options: { min: 3, max: 128 } },
optional: true,
},
'main.code': {
in: ['body'],
errorMessage: typeErrorMessage('string.minMax', { min: 1, max: 8 }),
isString: { bail: true },
isEmpty: { negated: true, bail: true },
isLength: { options: { min: 1, max: 8 }, bail: true },
optional: true,
custom: {
options: async (value, meta): Promise<void> => {
const { localeId, foodId } = (meta.req as Request).params;
Expand All @@ -49,6 +51,7 @@ const defaults: Schema = {
errorMessage: typeErrorMessage('string._'),
isString: { bail: true },
isEmpty: { negated: true, bail: true },
optional: true,
custom: {
options: async (value, meta): Promise<void> => {
const foodGroup = await FoodGroup.findByPk(value);
Expand Down
52 changes: 31 additions & 21 deletions apps/api/src/services/admin/food.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,7 @@ const adminFoodService = ({ db }: Pick<IoC, 'db'>) => {
newMethods.push(newMethod);

if (parameters.length) {
const records = parameters.map((item) => ({
...item,
portionSizeMethodId: newMethod.id,
}));
const records = parameters.map((item) => ({ ...item, portionSizeMethodId: newMethod.id }));
await FoodPortionSizeMethodParameter.bulkCreate(records, { transaction });
}
}
Expand Down Expand Up @@ -261,33 +258,46 @@ const adminFoodService = ({ db }: Pick<IoC, 'db'>) => {
const { attributes } = main;
if (!attributes) throw new NotFoundError();

const categories = (input.main.parentCategories ?? []).map(({ code }) => code);
const nutrientRecords = (input.nutrientRecords ?? []).map(({ id }) => id);

await db.foods.transaction(async (transaction) => {
await Promise.all([
const nutrientRecords = input.nutrientRecords.map(({ id }) => id);

const promises: Promise<any>[] = [
foodLocal.update(pick(input, ['name']), { transaction }),
main.update(pick(input.main, ['name', 'foodGroupId']), { transaction }),
attributes.update(
pick(input.main.attributes, [
'sameAsBeforeOption',
'readyMealOption',
'reasonableAmount',
'useInRecipes',
]),
{ transaction }
),
main.$set('parentCategories', categories, { transaction }),
foodLocal.$set('nutrientRecords', nutrientRecords, { transaction }),
updatePortionSizeMethods(foodLocalId, portionSizeMethods, input.portionSizeMethods, {
transaction,
}),
updateAssociatedFoods(main.code, localeCode, associatedFoods, input.associatedFoods, {
transaction,
}),
]);
];

if (input.main) {
promises.push(main.update(pick(input.main, ['name', 'foodGroupId']), { transaction }));

if (input.main.parentCategories) {
const categories = input.main.parentCategories.map(({ code }) => code);
promises.push(main.$set('parentCategories', categories, { transaction }));
}

if (input.main.attributes) {
promises.push(
attributes.update(
pick(input.main.attributes, [
'sameAsBeforeOption',
'readyMealOption',
'reasonableAmount',
'useInRecipes',
]),
{ transaction }
)
);
}
}

await Promise.all(promises);

if (main.code !== input.main.code)
if (input.main?.code && input.main.code !== main.code)
await Food.update({ code: input.main.code }, { where: { code: main.code }, transaction });
});

Expand Down
12 changes: 6 additions & 6 deletions packages/common/src/types/http/admin/foods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import type {

export type FoodInput = {
name: string;
main: {
code: string;
name: string;
foodGroupId: string;
attributes: FoodAttributeAttributes;
parentCategories: Pick<CategoryAttributes, 'code' | 'name'>[];
main?: {
code?: string;
name?: string;
foodGroupId?: string;
attributes?: FoodAttributeAttributes;
parentCategories?: Pick<CategoryAttributes, 'code' | 'name'>[];
};
nutrientRecords: Pick<NutrientTableRecordAttributes, 'id'>[];
portionSizeMethods: (FoodPortionSizeMethodCreationAttributes & {
Expand Down

0 comments on commit cd8f791

Please sign in to comment.