From 078098c593e53c8960dd0b53640f88bd6520e5b8 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sat, 17 Oct 2020 18:12:15 +0200 Subject: [PATCH] fix: edit custom view details. --- server/src/api/controllers/Views.ts | 16 ++++++++++--- .../seeds/core/20200810121807_seed_views.js | 22 ++++++++--------- .../core/20200810121808_seed_views_roles.js | 17 ++++++------- server/src/locales/en.json | 8 ++++++- server/src/models/Account.js | 2 +- server/src/models/AccountType.js | 14 +++++++++++ server/src/models/Expense.js | 9 +++++++ server/src/models/Item.js | 7 ++++++ server/src/models/ManualJournal.js | 7 ++++++ .../Accounts/AccountsTypesServices.ts | 11 +-------- .../ItemCategories/ItemCategoriesService.ts | 7 +++++- server/src/services/Views/ViewsService.ts | 24 +++++++++++-------- 12 files changed, 97 insertions(+), 47 deletions(-) diff --git a/server/src/api/controllers/Views.ts b/server/src/api/controllers/Views.ts index 238d01b6b..3d588d13b 100644 --- a/server/src/api/controllers/Views.ts +++ b/server/src/api/controllers/Views.ts @@ -52,6 +52,7 @@ export default class ViewsController extends BaseController{ ], this.validationResult, asyncMiddleware(this.getView.bind(this)), + this.handlerServiceErrors, ); return router; } @@ -157,7 +158,10 @@ export default class ViewsController extends BaseController{ try { const view = await this.viewsService.newView(tenantId, viewDTO); - return res.status(200).send({ id: view.id }); + return res.status(200).send({ + id: view.id, + message: 'The view has been created successfully.', + }); } catch (error) { next(error); } @@ -176,7 +180,10 @@ export default class ViewsController extends BaseController{ try { await this.viewsService.editView(tenantId, viewId, viewEditDTO); - return res.status(200).send({ id: viewId }); + return res.status(200).send({ + id: viewId, + message: 'The given view has been edited succcessfully.', + }); } catch (error) { next(error); } @@ -194,7 +201,10 @@ export default class ViewsController extends BaseController{ try { await this.viewsService.deleteView(tenantId, viewId); - return res.status(200).send(); + return res.status(200).send({ + id: viewId, + message: 'The view has been deleted successfully.', + }); } catch (error) { next(error); } diff --git a/server/src/database/seeds/core/20200810121807_seed_views.js b/server/src/database/seeds/core/20200810121807_seed_views.js index f47b01b23..f2981437e 100644 --- a/server/src/database/seeds/core/20200810121807_seed_views.js +++ b/server/src/database/seeds/core/20200810121807_seed_views.js @@ -19,19 +19,19 @@ exports.up = (knex) => { { id: 5, name: i18n.__('Expenses'), roles_logic_expression: '1', resource_model: 'Account', predefined: true }, // Items - // { id: 6, name: 'Services', roles_logic_expression: '1', resource_id: 2, predefined: true }, - // { id: 7, name: 'Inventory', roles_logic_expression: '1', resource_id: 2, predefined: true }, - // { id: 8, name: 'Non-Inventory', roles_logic_expression: '1', resource_id: 2, predefined: true }, + { id: 6, name: i18n.__('Services'), roles_logic_expression: '1', resource_model: 'Item', predefined: true }, + { id: 7, name: i18n.__('Inventory'), roles_logic_expression: '1', resource_model: 'Item', predefined: true }, + { id: 8, name: i18n.__('Non-Inventory'), roles_logic_expression: '1', resource_model: 'Item', predefined: true }, - // // Manual Journals - // { id: 9, name: 'Journal', roles_logic_expression: '1', resource_id: 4, predefined: true }, - // { id: 10, name: 'Credit', roles_logic_expression: '1', resource_id: 4, predefined: true }, - // { id: 11, name: 'Reconciliation', roles_logic_expression: '1', resource_id: 4, predefined: true }, + // Manual Journals + { id: 9, name: i18n.__('Journal'), roles_logic_expression: '1', resource_model: 'ManualJournal', predefined: true }, + { id: 10, name: i18n.__('Credit'), roles_logic_expression: '1', resource_model: 'ManualJournal', predefined: true }, + { id: 11, name: i18n.__('Reconciliation'), roles_logic_expression: '1', resource_model: 'ManualJournal', predefined: true }, - // // Expenses - // { id: 12, name: 'Interest', roles_logic_expression: '1', resource_id: 3, predefined: false, }, - // { id: 13, name: 'Depreciation', roles_logic_expression: '1', resource_id: 3, predefined: false, }, - // { id: 14, name: 'Payroll', roles_logic_expression: '1', resource_id: '3', predefined: false }, + // Expenses + { id: 12, name: i18n.__('Interest'), roles_logic_expression: '1', resource_model: 'Expense', predefined: false, }, + { id: 13, name: i18n.__('Depreciation'), roles_logic_expression: '1', resource_model: 'Expense', predefined: false, }, + { id: 14, name: i18n.__('Payroll'), roles_logic_expression: '1', resource_model: 'Expense', predefined: false }, ]); }); }; diff --git a/server/src/database/seeds/core/20200810121808_seed_views_roles.js b/server/src/database/seeds/core/20200810121808_seed_views_roles.js index f8ad2a64f..3f2e0acde 100644 --- a/server/src/database/seeds/core/20200810121808_seed_views_roles.js +++ b/server/src/database/seeds/core/20200810121808_seed_views_roles.js @@ -14,17 +14,14 @@ exports.up = (knex) => { { id: 12, field_key: 'active', index: 1, comparator: 'is', value: 1, view_id: 15 }, // Items. - // { id: 6, field_id: 12, index: 1, comparator: 'equals', value: 'service', view_id: 6 }, - // { id: 7, field_id: 12, index: 1, comparator: 'equals', value: 'inventory', view_id: 7 }, - // { id: 8, field_id: 12, index: 1, comparator: 'equals', value: 'non-inventory', view_id: 8 }, + { id: 6, field_id: 12, index: 1, comparator: 'equals', value: 'service', view_id: 6 }, + { id: 7, field_id: 12, index: 1, comparator: 'equals', value: 'inventory', view_id: 7 }, + { id: 8, field_id: 12, index: 1, comparator: 'equals', value: 'non-inventory', view_id: 8 }, - // // Manual Journals. - // { id: 9, field_id: 26, index: 1, comparator: 'equals', value: 'Journal', view_id: 9 }, - // { id: 10, field_id: 26, index: 1, comparator: 'equals', value: 'CreditNote', view_id: 10 }, - // { id: 11, field_id: 26, index: 1, comparator: 'equals', value: 'Reconciliation', view_id: 11 }, - - // Expenses - // { id: 12, field_id: index: } + // Manual Journals. + { id: 9, field_id: 26, index: 1, comparator: 'equals', value: 'Journal', view_id: 9 }, + { id: 10, field_id: 26, index: 1, comparator: 'equals', value: 'CreditNote', view_id: 10 }, + { id: 11, field_id: 26, index: 1, comparator: 'equals', value: 'Reconciliation', view_id: 11 }, ]); }); }; diff --git a/server/src/locales/en.json b/server/src/locales/en.json index 69522edf2..332cd9a10 100644 --- a/server/src/locales/en.json +++ b/server/src/locales/en.json @@ -37,5 +37,11 @@ "Balance": "Balance", "Active": "Active", "Created at": "Created at", - "fixed_asset": "Fixed asset" + "fixed_asset": "Fixed asset", + "Journal": "Journal", + "Reconciliation": "Reconciliation", + "Credit": "Credit", + "Interest": "Interest", + "Depreciation": "Depreciation", + "Payroll": "Payroll" } \ No newline at end of file diff --git a/server/src/models/Account.js b/server/src/models/Account.js index 26e38183e..76e9810a0 100644 --- a/server/src/models/Account.js +++ b/server/src/models/Account.js @@ -26,7 +26,7 @@ export default class Account extends TenantModel { } /** - * + * Allows to mark model as resourceable to viewable and filterable. */ static get resourceable() { return true; diff --git a/server/src/models/AccountType.js b/server/src/models/AccountType.js index a93b3d688..800d355cc 100644 --- a/server/src/models/AccountType.js +++ b/server/src/models/AccountType.js @@ -10,6 +10,20 @@ export default class AccountType extends TenantModel { return 'account_types'; } + /** + * Virtaul attributes. + */ + static get virtualAttributes() { + return ['label']; + } + + /** + * Translatable lable. + */ + label() { + return AccountType.labels[this.key] || ''; + } + /** * Relationship mapping. */ diff --git a/server/src/models/Expense.js b/server/src/models/Expense.js index eb1ae2c01..b5294f8ec 100644 --- a/server/src/models/Expense.js +++ b/server/src/models/Expense.js @@ -25,7 +25,16 @@ export default class Expense extends TenantModel { return ['createdAt', 'updatedAt']; } + /** + * Allows to mark model as resourceable to viewable and filterable. + */ + static get resourceable() { + return true; + } + /** + * + */ static get media () { return true; } diff --git a/server/src/models/Item.js b/server/src/models/Item.js index 739342c66..34a61e6e0 100644 --- a/server/src/models/Item.js +++ b/server/src/models/Item.js @@ -19,6 +19,13 @@ export default class Item extends TenantModel { return ['createdAt', 'updatedAt']; } + /** + * Allows to mark model as resourceable to viewable and filterable. + */ + static get resourceable() { + return true; + } + /** * Model modifiers. */ diff --git a/server/src/models/ManualJournal.js b/server/src/models/ManualJournal.js index d3f0bf408..e9fb675ac 100644 --- a/server/src/models/ManualJournal.js +++ b/server/src/models/ManualJournal.js @@ -17,6 +17,13 @@ export default class ManualJournal extends TenantModel { return ['createdAt', 'updatedAt']; } + /** + * + */ + static get resourceable() { + return true; + } + /** * Relationship mapping. */ diff --git a/server/src/services/Accounts/AccountsTypesServices.ts b/server/src/services/Accounts/AccountsTypesServices.ts index c21126989..c7e33df4f 100644 --- a/server/src/services/Accounts/AccountsTypesServices.ts +++ b/server/src/services/Accounts/AccountsTypesServices.ts @@ -15,15 +15,6 @@ export default class AccountsTypesService implements IAccountsTypesService{ */ async getAccountsTypes(tenantId: number): Promise { const { accountTypeRepository } = this.tenancy.repositories(tenantId); - const { AccountType } = this.tenancy.models(tenantId); - const { __ } = this.tenancy.i18n(tenantId); - - const allAccountsTypes = await accountTypeRepository.all(); - - return allAccountsTypes.map((_accountType: IAccountType) => ({ - id: _accountType.id, - label: __(AccountType.labels[_accountType.key]), - ...omit(_accountType, ['id']), - })); + return accountTypeRepository.all(); } } \ No newline at end of file diff --git a/server/src/services/ItemCategories/ItemCategoriesService.ts b/server/src/services/ItemCategories/ItemCategoriesService.ts index 14bbee307..c045571c4 100644 --- a/server/src/services/ItemCategories/ItemCategoriesService.ts +++ b/server/src/services/ItemCategories/ItemCategoriesService.ts @@ -11,6 +11,7 @@ import { IItemCategoriesService, IItemCategoriesFilter, ISystemUser, + IFilterMeta, } from "interfaces"; import DynamicListingService from 'services/DynamicListing/DynamicListService'; import TenancyService from 'services/Tenancy/TenancyService'; @@ -245,7 +246,11 @@ export default class ItemCategoriesService implements IItemCategoriesService { * @param {number} tenantId * @param filter */ - public async getItemCategoriesList(tenantId: number, filter: IItemCategoriesFilter, authorizedUser: ISystemUser) { + public async getItemCategoriesList( + tenantId: number, + filter: IItemCategoriesFilter, + authorizedUser: ISystemUser + ): Promise<{ itemCategories: IItemCategory[], filterMeta: IFilterMeta }> { const { ItemCategory } = this.tenancy.models(tenantId); const dynamicList = await this.dynamicListService.dynamicList(tenantId, ItemCategory, filter); diff --git a/server/src/services/Views/ViewsService.ts b/server/src/services/Views/ViewsService.ts index a55a17265..b019ea168 100644 --- a/server/src/services/Views/ViewsService.ts +++ b/server/src/services/Views/ViewsService.ts @@ -165,7 +165,7 @@ export default class ViewsService implements IViewsService { * - Store view roles/conditions to the storage. * --------- * @param {number} tenantId - Tenant id. - * @param {IViewDTO} viewDTO - View DTO. + * @param {IViewDTO} viewDTO - New view DTO. * * @return {Promise} */ @@ -195,7 +195,7 @@ export default class ViewsService implements IViewsService { predefined: false, name: viewDTO.name, rolesLogicExpression: viewDTO.logicExpression, - resourceModel: viewDTO.resourceModel, + resourceModel: ResourceModel.name, roles: viewDTO.roles, columns: viewDTO.columns, }); @@ -215,22 +215,23 @@ export default class ViewsService implements IViewsService { * - Delete old view columns and roles. * - Re-save view columns and roles. * - * @param {number} tenantId - * @param {number} viewId - * @param {IViewEditDTO} + * @param {number} tenantId - + * @param {number} viewId - + * @param {IViewEditDTO} viewEditDTO - + * @return {Promise} */ - public async editView(tenantId: number, viewId: number, viewEditDTO: IViewEditDTO): Promise { + public async editView(tenantId: number, viewId: number, viewEditDTO: IViewEditDTO): Promise { const { viewRepository } = this.tenancy.repositories(tenantId); this.logger.info('[view] trying to edit custom view.', { tenantId, viewId }); // Retrieve view details or throw not found error. - const view = await this.getViewOrThrowError(tenantId, viewId); + const oldView = await this.getViewOrThrowError(tenantId, viewId); // Validate the resource name is exists and resourcable. - const ResourceModel = this.getResourceModelOrThrowError(tenantId, view.resourceModel); + const ResourceModel = this.getResourceModelOrThrowError(tenantId, oldView.resourceModel); // Validate view name uniquiness. - await this.validateViewNameUniquiness(tenantId, view.resourceModel, viewEditDTO.name, viewId); + await this.validateViewNameUniquiness(tenantId, oldView.resourceModel, viewEditDTO.name, viewId); // Validate the given fields keys exist on the storage. this.validateResourceRolesFieldsExistance(ResourceModel, viewEditDTO.roles); @@ -243,7 +244,8 @@ export default class ViewsService implements IViewsService { throw new ServiceError(ERRORS.LOGIC_EXPRESSION_INVALID); } // Update view details. - await viewRepository.update(tenantId, viewId, { + this.logger.info('[views] trying to update view details.', { tenantId, viewId }); + const view = await viewRepository.update(viewId, { predefined: false, name: viewEditDTO.name, rolesLogicExpression: viewEditDTO.logicExpression, @@ -251,6 +253,8 @@ export default class ViewsService implements IViewsService { columns: viewEditDTO.columns, }) this.logger.info('[view] edited successfully.', { tenantId, viewId }); + + return view; } /**