diff --git a/packages/server-nest/src/main.ts b/packages/server-nest/src/main.ts index 7c411ec8f..78d305afe 100644 --- a/packages/server-nest/src/main.ts +++ b/packages/server-nest/src/main.ts @@ -1,7 +1,8 @@ import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; -import { AppModule } from './modules/App/App.module'; import { ClsMiddleware } from 'nestjs-cls'; +import { AppModule } from './modules/App/App.module'; +import './utils/moment-mysql'; async function bootstrap() { const app = await NestFactory.create(AppModule); diff --git a/packages/server-nest/src/modules/App/App.module.ts b/packages/server-nest/src/modules/App/App.module.ts index 0a027cba7..65523f431 100644 --- a/packages/server-nest/src/modules/App/App.module.ts +++ b/packages/server-nest/src/modules/App/App.module.ts @@ -33,6 +33,7 @@ import { TransformerInjectable } from '../Transformer/TransformerInjectable.serv import { TransformerModule } from '../Transformer/Transformer.module'; import { AccountsModule } from '../Accounts/Accounts.module'; import { ExpensesModule } from '../Expenses/Expenses.module'; +import { ItemCategoryModule } from '../ItemCategories/ItemCategory.module'; @Module({ imports: [ @@ -87,6 +88,7 @@ import { ExpensesModule } from '../Expenses/Expenses.module'; TenancyDatabaseModule, TenancyModelsModule, ItemsModule, + ItemCategoryModule, AccountsModule, ExpensesModule, ], @@ -106,7 +108,6 @@ import { ExpensesModule } from '../Expenses/Expenses.module'; }, AppService, JwtStrategy, - ], }) export class AppModule { diff --git a/packages/server-nest/src/modules/Expenses/Expenses.module.ts b/packages/server-nest/src/modules/Expenses/Expenses.module.ts index 8881d152b..cc11874c6 100644 --- a/packages/server-nest/src/modules/Expenses/Expenses.module.ts +++ b/packages/server-nest/src/modules/Expenses/Expenses.module.ts @@ -6,17 +6,25 @@ import { PublishExpense } from './commands/PublishExpense.service'; import { ExpensesController } from './Expenses.controller'; import { ExpensesApplication } from './ExpensesApplication.service'; import { GetExpenseService } from './queries/GetExpense.service'; +import { ExpenseDTOTransformer } from './commands/CommandExpenseDTO.transformer'; +import { CommandExpenseValidator } from './commands/CommandExpenseValidator.service'; +import { TenancyContext } from '../Tenancy/TenancyContext.service'; +import { TransformerInjectable } from '../Transformer/TransformerInjectable.service'; @Module({ imports: [], controllers: [ExpensesController], providers: [ CreateExpense, + ExpenseDTOTransformer, + CommandExpenseValidator, EditExpense, DeleteExpense, PublishExpense, GetExpenseService, ExpensesApplication, + TenancyContext, + TransformerInjectable ], }) export class ExpensesModule {} diff --git a/packages/server-nest/src/modules/Expenses/commands/ExpenseDTOTransformer.ts b/packages/server-nest/src/modules/Expenses/commands/CommandExpenseDTO.transformer.ts similarity index 97% rename from packages/server-nest/src/modules/Expenses/commands/ExpenseDTOTransformer.ts rename to packages/server-nest/src/modules/Expenses/commands/CommandExpenseDTO.transformer.ts index 9ebd61635..2d5785b7b 100644 --- a/packages/server-nest/src/modules/Expenses/commands/ExpenseDTOTransformer.ts +++ b/packages/server-nest/src/modules/Expenses/commands/CommandExpenseDTO.transformer.ts @@ -7,7 +7,6 @@ import { IExpenseEditDTO, } from '../interfaces/Expenses.interface'; // import { BranchTransactionDTOTransform } from '@/services/Branches/Integrations/BranchTransactionDTOTransform'; -// import { TenantMetadata } from '@/system/models'; import { Injectable } from '@nestjs/common'; import { Expense } from '../models/Expense.model'; import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index'; @@ -86,7 +85,7 @@ export class ExpenseDTOTransformer { */ public expenseCreateDTO = async ( expenseDTO: IExpenseCreateDTO, - ): Promise => { + ): Promise> => { const initialDTO = this.expenseDTOToModel(expenseDTO); const tenant = await this.tenancyContext.getTenant(true); diff --git a/packages/server-nest/src/modules/Expenses/commands/CreateExpense.service.ts b/packages/server-nest/src/modules/Expenses/commands/CreateExpense.service.ts index 1df82ae1d..8283e9387 100644 --- a/packages/server-nest/src/modules/Expenses/commands/CreateExpense.service.ts +++ b/packages/server-nest/src/modules/Expenses/commands/CreateExpense.service.ts @@ -6,7 +6,7 @@ import { IExpenseCreatingPayload, } from '../interfaces/Expenses.interface'; import { CommandExpenseValidator } from './CommandExpenseValidator.service'; -import { ExpenseDTOTransformer } from './ExpenseDTOTransformer'; +import { ExpenseDTOTransformer } from './CommandExpenseDTO.transformer'; import { Account } from '@/modules/Accounts/models/Account.model'; import { Expense } from '@/modules/Expenses/models/Expense.model'; import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service'; diff --git a/packages/server-nest/src/modules/Expenses/commands/EditExpense.service.ts b/packages/server-nest/src/modules/Expenses/commands/EditExpense.service.ts index 2c308fc25..5232b8ace 100644 --- a/packages/server-nest/src/modules/Expenses/commands/EditExpense.service.ts +++ b/packages/server-nest/src/modules/Expenses/commands/EditExpense.service.ts @@ -7,7 +7,7 @@ import { } from '../interfaces/Expenses.interface'; import { CommandExpenseValidator } from './CommandExpenseValidator.service'; import { EventEmitter2 } from '@nestjs/event-emitter'; -import { ExpenseDTOTransformer } from './ExpenseDTOTransformer'; +import { ExpenseDTOTransformer } from './CommandExpenseDTO.transformer'; // import { EntriesService } from '@/services/Entries'; import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service'; import { Account } from '@/modules/Accounts/models/Account.model'; diff --git a/packages/server-nest/src/modules/ItemCategories/ItemCategory.application.ts b/packages/server-nest/src/modules/ItemCategories/ItemCategory.application.ts index 83430aea3..3b8a26e17 100644 --- a/packages/server-nest/src/modules/ItemCategories/ItemCategory.application.ts +++ b/packages/server-nest/src/modules/ItemCategories/ItemCategory.application.ts @@ -1,9 +1,11 @@ +import { Injectable } from '@nestjs/common'; import { IItemCategoryOTD } from './ItemCategory.interfaces'; import { CreateItemCategoryService } from './commands/CreateItemCategory.service'; import { DeleteItemCategoryService } from './commands/DeleteItemCategory.service'; import { EditItemCategoryService } from './commands/EditItemCategory.service'; import { GetItemCategoryService } from './queries/GetItemCategory.service'; +@Injectable() export class ItemCategoryApplication { constructor( private readonly createItemCategoryService: CreateItemCategoryService, diff --git a/packages/server-nest/src/modules/ItemCategories/ItemCategory.controller.ts b/packages/server-nest/src/modules/ItemCategories/ItemCategory.controller.ts index be4d929e9..805f65727 100644 --- a/packages/server-nest/src/modules/ItemCategories/ItemCategory.controller.ts +++ b/packages/server-nest/src/modules/ItemCategories/ItemCategory.controller.ts @@ -9,8 +9,10 @@ import { } from '@nestjs/common'; import { ItemCategoryApplication } from './ItemCategory.application'; import { IItemCategoryOTD } from './ItemCategory.interfaces'; +import { PublicRoute } from '../Auth/Jwt.guard'; @Controller('item-categories') +@PublicRoute() export class ItemCategoryController { constructor( private readonly itemCategoryApplication: ItemCategoryApplication, diff --git a/packages/server-nest/src/modules/ItemCategories/ItemCategory.module.ts b/packages/server-nest/src/modules/ItemCategories/ItemCategory.module.ts index 0626185a6..d9c22fc43 100644 --- a/packages/server-nest/src/modules/ItemCategories/ItemCategory.module.ts +++ b/packages/server-nest/src/modules/ItemCategories/ItemCategory.module.ts @@ -6,6 +6,9 @@ import { EditItemCategoryService } from './commands/EditItemCategory.service'; import { GetItemCategoryService } from './queries/GetItemCategory.service'; import { ItemCategoryApplication } from './ItemCategory.application'; import { ItemCategoryController } from './ItemCategory.controller'; +import { CommandItemCategoryValidatorService } from './commands/CommandItemCategoryValidator.service'; +import { TransformerInjectable } from '../Transformer/TransformerInjectable.service'; +import { TenancyContext } from '../Tenancy/TenancyContext.service'; @Module({ imports: [TenancyDatabaseModule], @@ -16,6 +19,9 @@ import { ItemCategoryController } from './ItemCategory.controller'; GetItemCategoryService, DeleteItemCategoryService, ItemCategoryApplication, + CommandItemCategoryValidatorService, + TransformerInjectable, + TenancyContext ], }) export class ItemCategoryModule {} diff --git a/packages/server-nest/src/modules/ItemCategories/commands/CommandItemCategoryValidator.service.ts b/packages/server-nest/src/modules/ItemCategories/commands/CommandItemCategoryValidator.service.ts index b11a46f35..5b827e122 100644 --- a/packages/server-nest/src/modules/ItemCategories/commands/CommandItemCategoryValidator.service.ts +++ b/packages/server-nest/src/modules/ItemCategories/commands/CommandItemCategoryValidator.service.ts @@ -1,10 +1,11 @@ import { Account } from '@/modules/Accounts/models/Account.model'; import { ItemCategory } from '../models/ItemCategory.model'; -import { Inject } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { ServiceError } from '@/modules/Items/ServiceError'; import { ERRORS } from '../constants'; import { ACCOUNT_ROOT_TYPE, ACCOUNT_TYPE } from '@/constants/accounts'; +@Injectable() export class CommandItemCategoryValidatorService { constructor( @Inject(ItemCategory.name) diff --git a/packages/server-nest/src/modules/ItemCategories/commands/CreateItemCategory.service.ts b/packages/server-nest/src/modules/ItemCategories/commands/CreateItemCategory.service.ts index 1988aa026..16bfa5147 100644 --- a/packages/server-nest/src/modules/ItemCategories/commands/CreateItemCategory.service.ts +++ b/packages/server-nest/src/modules/ItemCategories/commands/CreateItemCategory.service.ts @@ -26,12 +26,15 @@ export class CreateItemCategoryService { * Transforms OTD to model object. * @param {IItemCategoryOTD} itemCategoryOTD * @param {ISystemUser} authorizedUser + * @returns {ItemCategory} */ private transformOTDToObject( itemCategoryOTD: IItemCategoryOTD, - authorizedUser: SystemUser, - ): ItemCategory { - return { ...itemCategoryOTD, userId: authorizedUser.id }; + ): Partial { + return { + ...itemCategoryOTD, + // userId: authorizedUser.id + }; } /** * Inserts a new item category. @@ -58,10 +61,8 @@ export class CreateItemCategoryService { itemCategoryOTD.inventoryAccountId, ); } - const itemCategoryObj = this.transformOTDToObject( - itemCategoryOTD, - authorizedUser, - ); + const itemCategoryObj = this.transformOTDToObject(itemCategoryOTD); + // Creates item category under unit-of-work evnirement. return this.uow.withTransaction(async (trx: Knex.Transaction) => { // Inserts the item category. diff --git a/packages/server-nest/src/modules/ItemCategories/commands/EditItemCategory.service.ts b/packages/server-nest/src/modules/ItemCategories/commands/EditItemCategory.service.ts index 7152a64eb..6e78d5b70 100644 --- a/packages/server-nest/src/modules/ItemCategories/commands/EditItemCategory.service.ts +++ b/packages/server-nest/src/modules/ItemCategories/commands/EditItemCategory.service.ts @@ -10,12 +10,14 @@ import { SystemUser } from '@/modules/System/models/SystemUser'; import { Knex } from 'knex'; import { ItemCategory } from '../models/ItemCategory.model'; import { Inject } from '@nestjs/common'; +import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; export class EditItemCategoryService { constructor( private readonly uow: UnitOfWork, private readonly validator: CommandItemCategoryValidatorService, private readonly eventEmitter: EventEmitter2, + private readonly tenancyContext: TenancyContext, @Inject(ItemCategory.name) private readonly itemCategoryModel: typeof ItemCategory, ) {} @@ -29,7 +31,7 @@ export class EditItemCategoryService { public async editItemCategory( itemCategoryId: number, itemCategoryOTD: IItemCategoryOTD, - ): Promise { + ): Promise { // Retrieve the item category from the storage. const oldItemCategory = await this.itemCategoryModel .query() @@ -52,11 +54,14 @@ export class EditItemCategoryService { itemCategoryOTD.inventoryAccountId, ); } + // Retrieves the authorized user. + const authorizedUser = await this.tenancyContext.getSystemUser(); + const itemCategoryObj = this.transformOTDToObject( itemCategoryOTD, authorizedUser, ); - // + // Creates item category under unit-of-work evnirement. return this.uow.withTransaction(async (trx: Knex.Transaction) => { // const itemCategory = await ItemCategory.query().patchAndFetchById( diff --git a/packages/server-nest/src/modules/ItemCategories/models/ItemCategory.model.ts b/packages/server-nest/src/modules/ItemCategories/models/ItemCategory.model.ts index 8f61a4c91..462aa8fdc 100644 --- a/packages/server-nest/src/modules/ItemCategories/models/ItemCategory.model.ts +++ b/packages/server-nest/src/modules/ItemCategories/models/ItemCategory.model.ts @@ -5,6 +5,15 @@ import { Model, mixin } from 'objection'; // import ItemCategorySettings from './ItemCategory.Settings'; export class ItemCategory extends BaseModel { + name!: string; + description!: string; + + costAccountId!: number; + sellAccountId!: number; + inventoryAccountId!: number; + + userId!: number; + /** * Table name. */ @@ -58,6 +67,6 @@ export class ItemCategory extends BaseModel { * Model meta. */ // static get meta() { - // return ItemCategorySettings; + // return ItemCategorySettings; // } } diff --git a/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts b/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts index d6522be4f..57ea4aefe 100644 --- a/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts +++ b/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts @@ -6,8 +6,19 @@ import { Item } from '../../../modules/Items/models/Item'; import { Account } from '@/modules/Accounts/models/Account.model'; import { ItemEntry } from '@/modules/Items/models/ItemEntry'; import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model'; +import { Expense } from '@/modules/Expenses/models/Expense.model'; +import ExpenseCategory from '@/modules/Expenses/models/ExpenseCategory.model'; +import { ItemCategory } from '@/modules/ItemCategories/models/ItemCategory.model'; -const models = [Item, Account, ItemEntry, AccountTransaction]; +const models = [ + Item, + Account, + ItemEntry, + AccountTransaction, + Expense, + ExpenseCategory, + ItemCategory, +]; const modelProviders = models.map((model) => { return { diff --git a/packages/server-nest/src/utils/moment-mysql.ts b/packages/server-nest/src/utils/moment-mysql.ts new file mode 100644 index 000000000..c911e15a9 --- /dev/null +++ b/packages/server-nest/src/utils/moment-mysql.ts @@ -0,0 +1,14 @@ +import * as moment from 'moment'; + +// Extends moment prototype to add a new method to format date to MySQL datetime format. +moment.prototype.toMySqlDateTime = function () { + return this.format('YYYY-MM-DD HH:mm:ss'); +}; + +declare global { + namespace moment { + interface Moment { + toMySqlDateTime(): string; + } + } +} diff --git a/packages/server-nest/test/item-categories.e2e-spec.ts b/packages/server-nest/test/item-categories.e2e-spec.ts new file mode 100644 index 000000000..3dc681655 --- /dev/null +++ b/packages/server-nest/test/item-categories.e2e-spec.ts @@ -0,0 +1,49 @@ +import * as request from 'supertest'; +import { faker } from '@faker-js/faker'; +import { app } from './init-app-test'; + +describe('Item Categories(e2e)', () => { + it('/item-categories (POST)', () => { + return request(app.getHttpServer()) + .post('/item-categories') + .set('organization-id', '4064541lv40nhca') + .send({ + name: faker.person.fullName(), + description: faker.lorem.sentence(), + }) + .expect(201); + }); + + it('/item-categories/:id (GET)', async () => { + const response = await request(app.getHttpServer()) + .post('/item-categories') + .set('organization-id', '4064541lv40nhca') + .send({ + name: faker.person.fullName(), + description: faker.lorem.sentence(), + }); + const itemCategoryId = response.body.id; + + return request(app.getHttpServer()) + .get(`/item-categories/${itemCategoryId}`) + .set('organization-id', '4064541lv40nhca') + .expect(200); + }); + + it('/item-categories/:id (DELETE)', async () => { + const response = await request(app.getHttpServer()) + .post('/item-categories') + .set('organization-id', '4064541lv40nhca') + .send({ + name: faker.person.fullName(), + description: faker.lorem.sentence(), + }); + + const itemCategoryId = response.body.id; + + return request(app.getHttpServer()) + .delete(`/item-categories/${itemCategoryId}`) + .set('organization-id', '4064541lv40nhca') + .expect(200); + }); +}); diff --git a/packages/server-nest/test/items.e2e-spec.ts b/packages/server-nest/test/items.e2e-spec.ts index 4d0060304..185037f85 100644 --- a/packages/server-nest/test/items.e2e-spec.ts +++ b/packages/server-nest/test/items.e2e-spec.ts @@ -1,8 +1,5 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; import { faker } from '@faker-js/faker'; -import { AppModule } from '../src/modules/App/App.module'; import { app } from './init-app-test'; describe('Items (e2e)', () => { diff --git a/packages/server/src/services/Expenses/CRUD/CreateExpense.ts b/packages/server/src/services/Expenses/CRUD/CreateExpense.ts index a342daed7..f64eba1a2 100644 --- a/packages/server/src/services/Expenses/CRUD/CreateExpense.ts +++ b/packages/server/src/services/Expenses/CRUD/CreateExpense.ts @@ -20,7 +20,7 @@ export class CreateExpense { private tenancy: HasTenancyService; @Inject() - private eventPublisher: EventPublisher; +private eventPublisher: EventPublisher; @Inject() private uow: UnitOfWork;