mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
refactor: migrate to Nestjs
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { ClsMiddleware } from 'nestjs-cls';
|
||||
import { AppModule } from './modules/App/App.module';
|
||||
import './utils/moment-mysql';
|
||||
import { AppModule } from './modules/App/App.module';
|
||||
import { ServiceErrorFilter } from './common/filters/service-error.filter';
|
||||
|
||||
async function bootstrap() {
|
||||
|
||||
@@ -4,8 +4,10 @@ import {
|
||||
ICreditNoteEditDTO,
|
||||
ICreditNoteNewDTO,
|
||||
} from './types/CreditNotes.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
|
||||
@Controller('credit-notes')
|
||||
@PublicRoute()
|
||||
export class CreditNotesController {
|
||||
/**
|
||||
* @param {CreditNoteApplication} creditNoteApplication - The credit note application service.
|
||||
@@ -28,7 +30,7 @@ export class CreditNotesController {
|
||||
);
|
||||
}
|
||||
|
||||
@Post(':id/open')
|
||||
@Put(':id/open')
|
||||
openCreditNote(@Param('id') creditNoteId: number) {
|
||||
return this.creditNoteApplication.openCreditNote(creditNoteId);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import moment from 'moment';
|
||||
import { omit } from 'lodash';
|
||||
import * as moment from 'moment';
|
||||
import * as composeAsync from 'async/compose';
|
||||
import * as R from 'ramda';
|
||||
import composeAsync from 'async/compose';
|
||||
import { ERRORS } from '../constants';
|
||||
import {
|
||||
ICreditNoteEditDTO,
|
||||
|
||||
@@ -287,7 +287,7 @@ export class CreditNote extends BaseModel {
|
||||
const { Branch } = require('../../Branches/models/Branch.model');
|
||||
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||
const { PdfTemplate } = require('../../PdfTemplate/models/PdfTemplate');
|
||||
const { PdfTemplateModel } = require('../../PdfTemplate/models/PdfTemplate');
|
||||
|
||||
return {
|
||||
/**
|
||||
@@ -384,7 +384,7 @@ export class CreditNote extends BaseModel {
|
||||
*/
|
||||
pdfTemplate: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: PdfTemplate,
|
||||
modelClass: PdfTemplateModel,
|
||||
join: {
|
||||
from: 'credit_notes.pdfTemplateId',
|
||||
to: 'pdf_templates.id',
|
||||
|
||||
@@ -117,121 +117,121 @@ export class ItemEntry extends BaseModel {
|
||||
/**
|
||||
* Item entry relations.
|
||||
*/
|
||||
// static get relationMappings() {
|
||||
// const Item = require('models/Item');
|
||||
// const BillLandedCostEntry = require('models/BillLandedCostEntry');
|
||||
// const SaleInvoice = require('models/SaleInvoice');
|
||||
// const Bill = require('models/Bill');
|
||||
// const SaleReceipt = require('models/SaleReceipt');
|
||||
// const SaleEstimate = require('models/SaleEstimate');
|
||||
// const ProjectTask = require('models/Task');
|
||||
// const Expense = require('models/Expense');
|
||||
// const TaxRate = require('models/TaxRate');
|
||||
static get relationMappings() {
|
||||
const { Item } = require('../../Items/models/Item');
|
||||
// const BillLandedCostEntry = require('models/BillLandedCostEntry');
|
||||
const { SaleInvoice } = require('../../SaleInvoices/models/SaleInvoice');
|
||||
const { Bill } = require('../../Bills/models/Bill');
|
||||
const { SaleReceipt } = require('../../SaleReceipts/models/SaleReceipt');
|
||||
const { SaleEstimate } = require('../../SaleEstimates/models/SaleEstimate');
|
||||
// const ProjectTask = require('models/Task');
|
||||
const { Expense } = require('../../Expenses/models/Expense.model');
|
||||
const { TaxRateModel } = require('../../TaxRates/models/TaxRate.model');
|
||||
|
||||
// return {
|
||||
// item: {
|
||||
// relation: Model.BelongsToOneRelation,
|
||||
// modelClass: Item.default,
|
||||
// join: {
|
||||
// from: 'items_entries.itemId',
|
||||
// to: 'items.id',
|
||||
// },
|
||||
// },
|
||||
// allocatedCostEntries: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: BillLandedCostEntry.default,
|
||||
// join: {
|
||||
// from: 'items_entries.referenceId',
|
||||
// to: 'bill_located_cost_entries.entryId',
|
||||
// },
|
||||
// },
|
||||
return {
|
||||
item: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Item,
|
||||
join: {
|
||||
from: 'items_entries.itemId',
|
||||
to: 'items.id',
|
||||
},
|
||||
},
|
||||
// allocatedCostEntries: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: BillLandedCostEntry,
|
||||
// join: {
|
||||
// from: 'items_entries.referenceId',
|
||||
// to: 'bill_located_cost_entries.entryId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// invoice: {
|
||||
// relation: Model.BelongsToOneRelation,
|
||||
// modelClass: SaleInvoice.default,
|
||||
// join: {
|
||||
// from: 'items_entries.referenceId',
|
||||
// to: 'sales_invoices.id',
|
||||
// },
|
||||
// },
|
||||
invoice: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: SaleInvoice,
|
||||
join: {
|
||||
from: 'items_entries.referenceId',
|
||||
to: 'sales_invoices.id',
|
||||
},
|
||||
},
|
||||
|
||||
// bill: {
|
||||
// relation: Model.BelongsToOneRelation,
|
||||
// modelClass: Bill.default,
|
||||
// join: {
|
||||
// from: 'items_entries.referenceId',
|
||||
// to: 'bills.id',
|
||||
// },
|
||||
// },
|
||||
bill: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Bill,
|
||||
join: {
|
||||
from: 'items_entries.referenceId',
|
||||
to: 'bills.id',
|
||||
},
|
||||
},
|
||||
|
||||
// estimate: {
|
||||
// relation: Model.BelongsToOneRelation,
|
||||
// modelClass: SaleEstimate.default,
|
||||
// join: {
|
||||
// from: 'items_entries.referenceId',
|
||||
// to: 'sales_estimates.id',
|
||||
// },
|
||||
// },
|
||||
estimate: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: SaleEstimate,
|
||||
join: {
|
||||
from: 'items_entries.referenceId',
|
||||
to: 'sales_estimates.id',
|
||||
},
|
||||
},
|
||||
|
||||
// /**
|
||||
// * Sale receipt reference.
|
||||
// */
|
||||
// receipt: {
|
||||
// relation: Model.BelongsToOneRelation,
|
||||
// modelClass: SaleReceipt.default,
|
||||
// join: {
|
||||
// from: 'items_entries.referenceId',
|
||||
// to: 'sales_receipts.id',
|
||||
// },
|
||||
// },
|
||||
/**
|
||||
* Sale receipt reference.
|
||||
*/
|
||||
receipt: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: SaleReceipt,
|
||||
join: {
|
||||
from: 'items_entries.referenceId',
|
||||
to: 'sales_receipts.id',
|
||||
},
|
||||
},
|
||||
|
||||
// /**
|
||||
// * Project task reference.
|
||||
// */
|
||||
// projectTaskRef: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: ProjectTask.default,
|
||||
// join: {
|
||||
// from: 'items_entries.projectRefId',
|
||||
// to: 'tasks.id',
|
||||
// },
|
||||
// },
|
||||
/**
|
||||
* Project task reference.
|
||||
*/
|
||||
// projectTaskRef: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: ProjectTask.default,
|
||||
// join: {
|
||||
// from: 'items_entries.projectRefId',
|
||||
// to: 'tasks.id',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Project expense reference.
|
||||
// */
|
||||
// projectExpenseRef: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: Expense.default,
|
||||
// join: {
|
||||
// from: 'items_entries.projectRefId',
|
||||
// to: 'expenses_transactions.id',
|
||||
// },
|
||||
// },
|
||||
/**
|
||||
* Project expense reference.
|
||||
*/
|
||||
// projectExpenseRef: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: Expense.default,
|
||||
// join: {
|
||||
// from: 'items_entries.projectRefId',
|
||||
// to: 'expenses_transactions.id',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Project bill reference.
|
||||
// */
|
||||
// projectBillRef: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: Bill.default,
|
||||
// join: {
|
||||
// from: 'items_entries.projectRefId',
|
||||
// to: 'bills.id',
|
||||
// },
|
||||
// },
|
||||
/**
|
||||
* Project bill reference.
|
||||
*/
|
||||
// projectBillRef: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: Bill.default,
|
||||
// join: {
|
||||
// from: 'items_entries.projectRefId',
|
||||
// to: 'bills.id',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Tax rate reference.
|
||||
// */
|
||||
// tax: {
|
||||
// relation: Model.HasOneRelation,
|
||||
// modelClass: TaxRate.default,
|
||||
// join: {
|
||||
// from: 'items_entries.taxRateId',
|
||||
// to: 'tax_rates.id',
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
/**
|
||||
* Tax rate reference.
|
||||
*/
|
||||
tax: {
|
||||
relation: Model.HasOneRelation,
|
||||
modelClass: TaxRateModel,
|
||||
join: {
|
||||
from: 'items_entries.taxRateId',
|
||||
to: 'tax_rates.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
@@ -57,6 +58,7 @@ export class SaleInvoicesController {
|
||||
}
|
||||
|
||||
@Post(':id/deliver')
|
||||
@HttpCode(200)
|
||||
deliverSaleInvoice(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.saleInvoiceApplication.deliverSaleInvoice(id);
|
||||
}
|
||||
@@ -67,6 +69,7 @@ export class SaleInvoicesController {
|
||||
}
|
||||
|
||||
@Post(':id/writeoff')
|
||||
@HttpCode(200)
|
||||
writeOff(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() writeoffDTO: ISaleInvoiceWriteoffDTO,
|
||||
@@ -75,6 +78,7 @@ export class SaleInvoicesController {
|
||||
}
|
||||
|
||||
@Post(':id/cancel-writeoff')
|
||||
@HttpCode(200)
|
||||
cancelWrittenoff(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.saleInvoiceApplication.cancelWrittenoff(id);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { omit, sumBy } from 'lodash';
|
||||
import * as R from 'ramda';
|
||||
import * as moment from 'moment';
|
||||
import '../../../utils/moment-mysql';
|
||||
import * as composeAsync from 'async/compose';
|
||||
import {
|
||||
ISaleInvoiceCreateDTO,
|
||||
@@ -23,6 +24,17 @@ import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export class CommandSaleInvoiceDTOTransformer {
|
||||
/**
|
||||
* @param {BranchTransactionDTOTransformer} branchDTOTransform - Branch transaction DTO transformer.
|
||||
* @param {WarehouseTransactionDTOTransform} warehouseDTOTransform - Warehouse transaction DTO transformer.
|
||||
* @param {ItemsEntriesService} itemsEntriesService - Items entries service.
|
||||
* @param {CommandSaleInvoiceValidators} validators - Command sale invoice validators.
|
||||
* @param {SaleInvoiceIncrement} invoiceIncrement - Sale invoice increment.
|
||||
* @param {ItemEntriesTaxTransactions} taxDTOTransformer - Item entries tax transactions.
|
||||
* @param {BrandingTemplateDTOTransformer} brandingTemplatesTransformer - Branding template DTO transformer.
|
||||
* @param {TenancyContext} tenancyContext - Tenancy context.
|
||||
* @param {SaleInvoice} saleInvoiceModel - Sale invoice model.
|
||||
*/
|
||||
constructor(
|
||||
private branchDTOTransform: BranchTransactionDTOTransformer,
|
||||
private warehouseDTOTransform: WarehouseTransactionDTOTransform,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import moment from 'moment';
|
||||
import * as moment from 'moment';
|
||||
import {
|
||||
ISaleInvoiceDeliveringPayload,
|
||||
ISaleInvoiceEventDeliveredPayload,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { mixin, Model, raw } from 'objection';
|
||||
import { castArray, takeWhile } from 'lodash';
|
||||
import moment, { MomentInput, unitOfTime } from 'moment';
|
||||
import * as moment from 'moment';
|
||||
import { MomentInput, unitOfTime } from 'moment';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import ModelSetting from './ModelSetting';
|
||||
// import SaleInvoiceMeta from './SaleInvoice.Settings';
|
||||
@@ -8,6 +9,9 @@ import moment, { MomentInput, unitOfTime } from 'moment';
|
||||
// import { DEFAULT_VIEWS } from '@/services/Sales/Invoices/constants';
|
||||
// import ModelSearchable from './ModelSearchable';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
import { TaxRateTransaction } from '@/modules/TaxRates/models/TaxRateTransaction.model';
|
||||
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
||||
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
|
||||
|
||||
export class SaleInvoice extends BaseModel {
|
||||
public taxAmountWithheld: number;
|
||||
@@ -39,7 +43,9 @@ export class SaleInvoice extends BaseModel {
|
||||
public branchId: number;
|
||||
public warehouseId: number;
|
||||
|
||||
// public taxes: TaxRateTransaction[];
|
||||
public taxes: TaxRateTransaction[];
|
||||
public entries: ItemEntry[];
|
||||
public attachments: Document[];
|
||||
|
||||
/**
|
||||
* Table name
|
||||
@@ -438,7 +444,7 @@ export class SaleInvoice extends BaseModel {
|
||||
const { Branch } = require('../../Branches/models/Branch.model');
|
||||
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||
const { Account } = require('../../Accounts/models/Account.model');
|
||||
// const TaxRateTransaction = require('../../Tax');
|
||||
const { TaxRateTransaction } = require('../../TaxRates/models/TaxRateTransaction.model');
|
||||
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
||||
const {
|
||||
@@ -561,17 +567,17 @@ export class SaleInvoice extends BaseModel {
|
||||
/**
|
||||
* Invoice may has associated tax rate transactions.
|
||||
*/
|
||||
// taxes: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: TaxRateTransaction.default,
|
||||
// join: {
|
||||
// from: 'sales_invoices.id',
|
||||
// to: 'tax_rate_transactions.referenceId',
|
||||
// },
|
||||
// filter(builder) {
|
||||
// builder.where('reference_type', 'SaleInvoice');
|
||||
// },
|
||||
// },
|
||||
taxes: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: TaxRateTransaction,
|
||||
join: {
|
||||
from: 'sales_invoices.id',
|
||||
to: 'tax_rate_transactions.referenceId',
|
||||
},
|
||||
filter(builder) {
|
||||
builder.where('reference_type', 'SaleInvoice');
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Sale invoice transaction may has many attached attachments.
|
||||
|
||||
@@ -184,31 +184,31 @@ export class SaleInvoiceTransformer extends Transformer {
|
||||
* Retrieve the taxes lines of sale invoice.
|
||||
* @param {ISaleInvoice} invoice
|
||||
*/
|
||||
// protected taxes = (invoice: SaleInvoice) => {
|
||||
// return this.item(invoice.taxes, new SaleInvoiceTaxEntryTransformer(), {
|
||||
// subtotal: invoice.subtotal,
|
||||
// isInclusiveTax: invoice.isInclusiveTax,
|
||||
// currencyCode: invoice.currencyCode,
|
||||
// });
|
||||
// };
|
||||
protected taxes = (invoice: SaleInvoice) => {
|
||||
return this.item(invoice.taxes, new SaleInvoiceTaxEntryTransformer(), {
|
||||
subtotal: invoice.subtotal,
|
||||
isInclusiveTax: invoice.isInclusiveTax,
|
||||
currencyCode: invoice.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the entries of the sale invoice.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {}
|
||||
*/
|
||||
// protected entries = (invoice: SaleInvoice) => {
|
||||
// return this.item(invoice.entries, new ItemEntryTransformer(), {
|
||||
// currencyCode: invoice.currencyCode,
|
||||
// });
|
||||
// };
|
||||
protected entries = (invoice: SaleInvoice) => {
|
||||
return this.item(invoice.entries, new ItemEntryTransformer(), {
|
||||
currencyCode: invoice.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the sale invoice attachments.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns
|
||||
*/
|
||||
// protected attachments = (invoice: SaleInvoice) => {
|
||||
// return this.item(invoice.attachments, new AttachmentTransformer());
|
||||
// };
|
||||
protected attachments = (invoice: SaleInvoice) => {
|
||||
return this.item(invoice.attachments, new AttachmentTransformer());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { mixin, Model, raw } from 'objection';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import ModelSearchable from './ModelSearchable';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
|
||||
export class TaxRateTransaction extends BaseModel {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'tax_rate_transactions';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get virtualAttributes() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { TaxRateModel } = require('./TaxRate.model');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Belongs to the tax rate.
|
||||
*/
|
||||
taxRate: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: TaxRateModel,
|
||||
join: {
|
||||
from: 'tax_rate_transactions.taxRateId',
|
||||
to: 'tax_rates.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,21 @@
|
||||
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { VendorCreditsApplicationService } from './VendorCreditsApplication.service';
|
||||
import { IVendorCreditCreateDTO, IVendorCreditEditDTO } from './types/VendorCredit.types';
|
||||
import {
|
||||
IVendorCreditCreateDTO,
|
||||
IVendorCreditEditDTO,
|
||||
} from './types/VendorCredit.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
|
||||
@Controller('vendor-credits')
|
||||
@PublicRoute()
|
||||
export class VendorCreditsController {
|
||||
constructor(
|
||||
private readonly vendorCreditsApplication: VendorCreditsApplicationService,
|
||||
@@ -13,7 +26,12 @@ export class VendorCreditsController {
|
||||
return this.vendorCreditsApplication.createVendorCredit(dto);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@Put(':id/open')
|
||||
async openVendorCredit(@Param('id') vendorCreditId: number) {
|
||||
return this.vendorCreditsApplication.openVendorCredit(vendorCreditId);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async editVendorCredit(
|
||||
@Param('id') vendorCreditId: number,
|
||||
@Body() dto: IVendorCreditEditDTO,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
||||
import { BranchesModule } from '../Branches/Branches.module';
|
||||
import { WarehousesModule } from '../Warehouses/Warehouses.module';
|
||||
import { VendorCreditsApplicationService } from './VendorCreditsApplication.service';
|
||||
import { OpenVendorCreditService } from './commands/OpenVendorCredit.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -35,6 +36,7 @@ import { VendorCreditsApplicationService } from './VendorCreditsApplication.serv
|
||||
GetRefundVendorCreditService,
|
||||
GetVendorCreditService,
|
||||
VendorCreditsApplicationService,
|
||||
OpenVendorCreditService
|
||||
],
|
||||
exports: [
|
||||
CreateVendorCreditService,
|
||||
@@ -45,6 +47,7 @@ import { VendorCreditsApplicationService } from './VendorCreditsApplication.serv
|
||||
GetRefundVendorCreditService,
|
||||
GetVendorCreditService,
|
||||
VendorCreditsApplicationService,
|
||||
OpenVendorCreditService
|
||||
],
|
||||
controllers: [VendorCreditsController],
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import { GetVendorCreditService } from './queries/GetVendorCredit.service';
|
||||
import { IVendorCreditEditDTO } from './types/VendorCredit.types';
|
||||
import { IVendorCreditCreateDTO } from './types/VendorCredit.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OpenVendorCreditService } from './commands/OpenVendorCredit.service';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditsApplicationService {
|
||||
@@ -20,6 +21,7 @@ export class VendorCreditsApplicationService {
|
||||
private readonly editVendorCreditService: EditVendorCreditService,
|
||||
private readonly deleteVendorCreditService: DeleteVendorCreditService,
|
||||
private readonly getVendorCreditService: GetVendorCreditService,
|
||||
private readonly openVendorCreditService: OpenVendorCreditService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -32,6 +34,15 @@ export class VendorCreditsApplicationService {
|
||||
return this.createVendorCreditService.newVendorCredit(dto, trx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the given vendor credit.
|
||||
* @param {number} vendorCreditId - The vendor credit id.
|
||||
* @returns {Promise<VendorCredit>} The opened vendor credit.
|
||||
*/
|
||||
openVendorCredit(vendorCreditId: number) {
|
||||
return this.openVendorCreditService.openVendorCredit(vendorCreditId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the given vendor credit.
|
||||
* @param {number} vendorCreditId - The vendor credit id.
|
||||
|
||||
@@ -10,6 +10,7 @@ import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { VendorCredit } from '../models/VendorCredit';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { Knex } from 'knex';
|
||||
|
||||
@Injectable()
|
||||
export class OpenVendorCreditService {
|
||||
@@ -32,6 +33,7 @@ export class OpenVendorCreditService {
|
||||
*/
|
||||
public openVendorCredit = async (
|
||||
vendorCreditId: number,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<VendorCredit> => {
|
||||
// Retrieve the vendor credit or throw not found service error.
|
||||
const oldVendorCredit = await this.vendorCreditModel
|
||||
@@ -75,7 +77,7 @@ export class OpenVendorCreditService {
|
||||
} as IVendorCreditOpenedPayload);
|
||||
|
||||
return vendorCredit;
|
||||
});
|
||||
}, trx);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,10 +80,9 @@ export class VendorCreditDTOTransformService {
|
||||
}),
|
||||
};
|
||||
return R.compose(
|
||||
VendorCredit.fromJson<VendorCredit>,
|
||||
this.branchDTOTransform.transformDTO<VendorCredit>,
|
||||
this.warehouseDTOTransform.transformDTO<VendorCredit>,
|
||||
)(initialDTO);
|
||||
)(initialDTO) as VendorCredit;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -292,6 +292,9 @@ export class VendorCredit extends BaseModel {
|
||||
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Vendor credit may belongs to vendor.
|
||||
*/
|
||||
vendor: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Vendor,
|
||||
@@ -304,6 +307,9 @@ export class VendorCredit extends BaseModel {
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Vendor credit may has many item entries.
|
||||
*/
|
||||
entries: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: ItemEntry,
|
||||
|
||||
@@ -4,8 +4,10 @@ import { Body, Controller, Delete, Param, Post } from '@nestjs/common';
|
||||
import { VendorCreditsRefundApplication } from './VendorCreditsRefund.application';
|
||||
import { IRefundVendorCreditDTO } from './types/VendorCreditRefund.types';
|
||||
import { RefundVendorCredit } from './models/RefundVendorCredit';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
|
||||
@Controller('vendor-credits')
|
||||
@PublicRoute()
|
||||
export class VendorCreditsRefundController {
|
||||
constructor(
|
||||
private readonly vendorCreditsRefundApplication: VendorCreditsRefundApplication,
|
||||
|
||||
@@ -38,7 +38,7 @@ export class RefundVendorCredit extends BaseModel {
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { VendorCredit } = require('./VendorCredit');
|
||||
const { VendorCredit } = require('../../VendorCredit/models/VendorCredit');
|
||||
const { Account } = require('../../Accounts/models/Account.model');
|
||||
|
||||
return {
|
||||
|
||||
71
packages/server-nest/test/credit-notes.e2e-spec.ts
Normal file
71
packages/server-nest/test/credit-notes.e2e-spec.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import * as request from 'supertest';
|
||||
import { app } from './init-app-test';
|
||||
|
||||
const requestCreditNote = () => ({
|
||||
customerId: 2,
|
||||
creditNoteDate: '2020-02-02',
|
||||
branchId: 1,
|
||||
warehouseId: 1,
|
||||
entries: [
|
||||
{
|
||||
index: 1,
|
||||
itemId: 1000,
|
||||
quantity: 1,
|
||||
rate: 1000,
|
||||
description: "It's description here.",
|
||||
},
|
||||
],
|
||||
discount: '100',
|
||||
discountType: 'amount',
|
||||
});
|
||||
|
||||
describe('Credit Notes (e2e)', () => {
|
||||
it('/credit-notes (POST)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.post('/credit-notes')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestCreditNote())
|
||||
.expect(201);
|
||||
});
|
||||
|
||||
it('/credit-notes/:id (DELETE)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/credit-notes')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestCreditNote());
|
||||
const creditNoteId = response.body.id;
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.delete(`/credit-notes/${creditNoteId}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/credit-notes/:id (PUT)', async () => {
|
||||
const creditNote = requestCreditNote();
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/credit-notes')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(creditNote);
|
||||
const creditNoteId = response.body.id;
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.put(`/credit-notes/${creditNoteId}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(creditNote)
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/credit-notes/:id/open (POST)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/credit-notes')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestCreditNote());
|
||||
const creditNoteId = response.body.id;
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.put(`/credit-notes/${creditNoteId}/open`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
@@ -2,32 +2,148 @@ import * as request from 'supertest';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { app } from './init-app-test';
|
||||
|
||||
const requestSaleInvoiceBody = () => ({
|
||||
customerId: 2,
|
||||
invoiceDate: '2023-01-01',
|
||||
dueDate: '2023-02-01',
|
||||
invoiceNo: faker.string.uuid(),
|
||||
referenceNo: 'REF-000201',
|
||||
delivered: true,
|
||||
discountType: 'percentage',
|
||||
discount: 10,
|
||||
branchId: 1,
|
||||
warehouseId: 1,
|
||||
entries: [
|
||||
{
|
||||
index: 1,
|
||||
itemId: 1001,
|
||||
quantity: 2,
|
||||
rate: 1000,
|
||||
description: 'Item description...',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
describe('Sale Invoices (e2e)', () => {
|
||||
it('/sale-invoices (POST)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send({
|
||||
customerId: 2,
|
||||
invoiceDate: '2023-01-01',
|
||||
dueDate: '2023-02-01',
|
||||
invoiceNo: 'INV-002005',
|
||||
referenceNo: 'REF-000201',
|
||||
delivered: true,
|
||||
discountType: 'percentage',
|
||||
discount: 10,
|
||||
branchId: 1,
|
||||
warehouseId: 1,
|
||||
entries: [
|
||||
{
|
||||
index: 1,
|
||||
itemId: 1001,
|
||||
quantity: 2,
|
||||
rate: 1000,
|
||||
description: 'Item description...',
|
||||
},
|
||||
],
|
||||
})
|
||||
.send(requestSaleInvoiceBody())
|
||||
.expect(201);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id (DELETE)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.delete(`/sale-invoices/${response.body.id}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id (PUT)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.put(`/sale-invoices/${response.body.id}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody())
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id (GET)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.get(`/sale-invoices/${response.body.id}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id/state (GET)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.get(`/sale-invoices/${response.body.id}/state`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id/payments (GET)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.get(`/sale-invoices/${response.body.id}/payments`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id/writeoff (POST)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/sale-invoices/${response.body.id}/writeoff`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send({
|
||||
expenseAccountId: 1024,
|
||||
date: '2023-01-01',
|
||||
reason: 'Write off reason',
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id/cancel-writeoff (POST)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestSaleInvoiceBody());
|
||||
|
||||
await request(app.getHttpServer())
|
||||
.post(`/sale-invoices/${response.body.id}/writeoff`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send({
|
||||
expenseAccountId: 1024,
|
||||
date: '2023-01-01',
|
||||
reason: 'Write off reason',
|
||||
});
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/sale-invoices/${response.body.id}/cancel-writeoff`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/sale-invoices/:id/deliver (PUT)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/sale-invoices')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send({
|
||||
...requestSaleInvoiceBody(),
|
||||
delivered: false,
|
||||
});
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/sale-invoices/${response.body.id}/deliver`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
|
||||
73
packages/server-nest/test/vendor-credits.e2e-spec.ts
Normal file
73
packages/server-nest/test/vendor-credits.e2e-spec.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import * as request from 'supertest';
|
||||
import { app } from './init-app-test';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
const requestVendorCredit = () => ({
|
||||
vendorId: 3,
|
||||
exchangeRate: 1,
|
||||
vendorCreditNumber: faker.string.uuid(),
|
||||
vendorCreditDate: '2025-01-01',
|
||||
entries: [
|
||||
{
|
||||
index: 1,
|
||||
item_id: 1000,
|
||||
quantity: 1,
|
||||
rate: 1000,
|
||||
description: "It's description here.",
|
||||
},
|
||||
],
|
||||
branchId: 1,
|
||||
warehouseId: 1,
|
||||
});
|
||||
|
||||
describe('Vendor Credits (e2e)', () => {
|
||||
it('/vendor-credits (POST)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.post('/vendor-credits')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestVendorCredit())
|
||||
.expect(201);
|
||||
});
|
||||
|
||||
it('/vendor-credits/:id (DELETE)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/vendor-credits')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestVendorCredit());
|
||||
|
||||
const vendorCreditId = response.body.id;
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.delete(`/vendor-credits/${vendorCreditId}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/vendor-credits/:id/open (POST)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/vendor-credits')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestVendorCredit());
|
||||
|
||||
const vendorCreditId = response.body.id;
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.put(`/vendor-credits/${vendorCreditId}/open`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('/vendor-credits/:id (GET)', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/vendor-credits')
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.send(requestVendorCredit());
|
||||
|
||||
const vendorCreditId = response.body.id;
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.get(`/vendor-credits/${vendorCreditId}`)
|
||||
.set('organization-id', '4064541lv40nhca')
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -544,6 +544,9 @@ importers:
|
||||
axios:
|
||||
specifier: ^1.6.0
|
||||
version: 1.7.7
|
||||
bluebird:
|
||||
specifier: ^3.7.2
|
||||
version: 3.7.2
|
||||
bull:
|
||||
specifier: ^4.16.3
|
||||
version: 4.16.4
|
||||
@@ -16906,7 +16909,7 @@ packages:
|
||||
postcss-modules-values: 4.0.0(postcss@8.4.47)
|
||||
postcss-value-parser: 4.2.0
|
||||
semver: 7.6.2
|
||||
webpack: 5.91.0(esbuild@0.18.20)(webpack-cli@5.1.4)
|
||||
webpack: 5.91.0(esbuild@0.23.1)
|
||||
|
||||
/css-loader@6.11.0(webpack@5.96.1):
|
||||
resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==}
|
||||
@@ -32291,7 +32294,7 @@ packages:
|
||||
peerDependencies:
|
||||
webpack: ^5.0.0
|
||||
dependencies:
|
||||
webpack: 5.91.0(esbuild@0.18.20)(webpack-cli@5.1.4)
|
||||
webpack: 5.91.0(esbuild@0.23.1)
|
||||
|
||||
/style-loader@3.3.4(webpack@5.96.1):
|
||||
resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==}
|
||||
@@ -34736,7 +34739,6 @@ packages:
|
||||
- '@swc/core'
|
||||
- esbuild
|
||||
- uglify-js
|
||||
dev: false
|
||||
|
||||
/webpack@5.91.0(esbuild@0.23.1)(webpack-cli@4.10.0):
|
||||
resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==}
|
||||
|
||||
Reference in New Issue
Block a user