mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 07:40:32 +00:00
feat: wip migrate to nestjs
This commit is contained in:
@@ -37,13 +37,15 @@ import { TaxRatesModule } from '../TaxRates/TaxRate.module';
|
|||||||
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
||||||
import { BranchesModule } from '../Branches/Branches.module';
|
import { BranchesModule } from '../Branches/Branches.module';
|
||||||
import { WarehousesModule } from '../Warehouses/Warehouses.module';
|
import { WarehousesModule } from '../Warehouses/Warehouses.module';
|
||||||
import { SaleEstimatesModule } from '../SaleEstimates/SaleEstimates.module';
|
|
||||||
import { SerializeInterceptor } from '@/common/interceptors/serialize.interceptor';
|
import { SerializeInterceptor } from '@/common/interceptors/serialize.interceptor';
|
||||||
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
|
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
|
||||||
import { CustomersModule } from '../Customers/Customers.module';
|
import { CustomersModule } from '../Customers/Customers.module';
|
||||||
import { VendorsModule } from '../Vendors/Vendors.module';
|
import { VendorsModule } from '../Vendors/Vendors.module';
|
||||||
|
import { SaleEstimatesModule } from '../SaleEstimates/SaleEstimates.module';
|
||||||
import { BillsModule } from '../Bills/Bills.module';
|
import { BillsModule } from '../Bills/Bills.module';
|
||||||
import { BillPaymentsModule } from '../BillPayments/BillPayments.module';
|
import { SaleInvoicesModule } from '../SaleInvoices/SaleInvoices.module';
|
||||||
|
import { SaleReceiptsModule } from '../SaleReceipts/SaleReceipts.module';
|
||||||
|
// import { BillPaymentsModule } from '../BillPayments/BillPayments.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -109,9 +111,11 @@ import { BillPaymentsModule } from '../BillPayments/BillPayments.module';
|
|||||||
WarehousesModule,
|
WarehousesModule,
|
||||||
CustomersModule,
|
CustomersModule,
|
||||||
VendorsModule,
|
VendorsModule,
|
||||||
|
SaleInvoicesModule,
|
||||||
SaleEstimatesModule,
|
SaleEstimatesModule,
|
||||||
|
SaleReceiptsModule,
|
||||||
BillsModule,
|
BillsModule,
|
||||||
BillPaymentsModule,
|
// BillPaymentsModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { AutoIncrementOrdersService } from './AutoIncrementOrders.service';
|
|||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [AutoIncrementOrdersService, TransformerInjectable],
|
providers: [AutoIncrementOrdersService],
|
||||||
exports: [AutoIncrementOrdersService],
|
exports: [AutoIncrementOrdersService],
|
||||||
})
|
})
|
||||||
export class AutoIncrementOrdersModule {}
|
export class AutoIncrementOrdersModule {}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TransactionLandedCostEntriesService } from './TransactionLandedCostEntries.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [TransactionLandedCostEntriesService],
|
||||||
|
exports: [TransactionLandedCostEntriesService],
|
||||||
|
})
|
||||||
|
export class BillLandedCostsModule {}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ServiceError } from '../Items/ServiceError';
|
||||||
|
import { transformToMap } from '@/utils/transform-to-key';
|
||||||
|
import { ICommonLandedCostEntry, ICommonLandedCostEntryDTO } from './types/BillLandedCosts.types';
|
||||||
|
|
||||||
|
const ERRORS = {
|
||||||
|
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
|
||||||
|
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
|
LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES:
|
||||||
|
'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES',
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TransactionLandedCostEntriesService {
|
||||||
|
/**
|
||||||
|
* Validates bill entries that has allocated landed cost amount not deleted.
|
||||||
|
* @param {ICommonLandedCostEntry[]} oldCommonEntries -
|
||||||
|
* @param {ICommonLandedCostEntryDTO[]} newBillEntries -
|
||||||
|
*/
|
||||||
|
public getLandedCostEntriesDeleted(
|
||||||
|
oldCommonEntries: ICommonLandedCostEntry[],
|
||||||
|
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||||
|
): ICommonLandedCostEntry[] {
|
||||||
|
const newBillEntriesById = transformToMap(newCommonEntriesDTO, 'id');
|
||||||
|
|
||||||
|
return oldCommonEntries.filter((entry) => {
|
||||||
|
const newEntry = newBillEntriesById.get(entry.id);
|
||||||
|
|
||||||
|
if (entry.allocatedCostAmount > 0 && typeof newEntry === 'undefined') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the bill entries that have located cost amount should not be deleted.
|
||||||
|
* @param {ICommonLandedCostEntry[]} oldCommonEntries - Old bill entries.
|
||||||
|
* @param {ICommonLandedCostEntryDTO[]} newBillEntries - New DTO bill entries.
|
||||||
|
*/
|
||||||
|
public validateLandedCostEntriesNotDeleted(
|
||||||
|
oldCommonEntries: ICommonLandedCostEntry[],
|
||||||
|
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||||
|
): void {
|
||||||
|
const entriesDeleted = this.getLandedCostEntriesDeleted(
|
||||||
|
oldCommonEntries,
|
||||||
|
newCommonEntriesDTO
|
||||||
|
);
|
||||||
|
if (entriesDeleted.length > 0) {
|
||||||
|
throw new ServiceError(ERRORS.ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate allocated cost amount entries should be smaller than new entries amount.
|
||||||
|
* @param {ICommonLandedCostEntry[]} oldCommonEntries - Old bill entries.
|
||||||
|
* @param {ICommonLandedCostEntryDTO[]} newBillEntries - New DTO bill entries.
|
||||||
|
*/
|
||||||
|
public validateLocatedCostEntriesSmallerThanNewEntries(
|
||||||
|
oldCommonEntries: ICommonLandedCostEntry[],
|
||||||
|
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||||
|
): void {
|
||||||
|
const oldBillEntriesById = transformToMap(oldCommonEntries, 'id');
|
||||||
|
|
||||||
|
newCommonEntriesDTO.forEach((entry) => {
|
||||||
|
const oldEntry = oldBillEntriesById.get(entry.id);
|
||||||
|
|
||||||
|
if (oldEntry && oldEntry.allocatedCostAmount > entry.amount) {
|
||||||
|
throw new ServiceError(
|
||||||
|
ERRORS.LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,15 +4,15 @@ import { lowerCase } from 'lodash';
|
|||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
|
||||||
export class BillLandedCost extends BaseModel {
|
export class BillLandedCost extends BaseModel {
|
||||||
amount: number;
|
amount!: number;
|
||||||
fromTransactionId: number;
|
fromTransactionId!: number;
|
||||||
fromTransactionType: string;
|
fromTransactionType!: string;
|
||||||
fromTransactionEntryId: number;
|
fromTransactionEntryId!: number;
|
||||||
allocationMethod: string;
|
allocationMethod!: string;
|
||||||
costAccountId: number;
|
costAccountId!: number;
|
||||||
description: string;
|
description!: string;
|
||||||
billId: number;
|
billId!: number;
|
||||||
exchangeRate: number;
|
exchangeRate!: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
@@ -60,15 +60,19 @@ export class BillLandedCost extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const BillLandedCostEntry = require('models/BillLandedCostEntry');
|
const { BillLandedCostEntry } = require('./BillLandedCostEntry');
|
||||||
const Bill = require('models/Bill');
|
const { Bill } = require('../../Bills/models/Bill');
|
||||||
const ItemEntry = require('models/ItemEntry');
|
const {
|
||||||
const ExpenseCategory = require('models/ExpenseCategory');
|
ItemEntry,
|
||||||
|
} = require('../../TransactionItemEntry/models/ItemEntry');
|
||||||
|
const {
|
||||||
|
ExpenseCategory,
|
||||||
|
} = require('../../Expenses/models/ExpenseCategory.model');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bill: {
|
bill: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Bill.default,
|
modelClass: Bill,
|
||||||
join: {
|
join: {
|
||||||
from: 'bill_located_costs.billId',
|
from: 'bill_located_costs.billId',
|
||||||
to: 'bills.id',
|
to: 'bills.id',
|
||||||
@@ -76,7 +80,7 @@ export class BillLandedCost extends BaseModel {
|
|||||||
},
|
},
|
||||||
allocateEntries: {
|
allocateEntries: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: BillLandedCostEntry.default,
|
modelClass: BillLandedCostEntry,
|
||||||
join: {
|
join: {
|
||||||
from: 'bill_located_costs.id',
|
from: 'bill_located_costs.id',
|
||||||
to: 'bill_located_cost_entries.billLocatedCostId',
|
to: 'bill_located_cost_entries.billLocatedCostId',
|
||||||
@@ -84,7 +88,7 @@ export class BillLandedCost extends BaseModel {
|
|||||||
},
|
},
|
||||||
allocatedFromBillEntry: {
|
allocatedFromBillEntry: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: ItemEntry.default,
|
modelClass: ItemEntry,
|
||||||
join: {
|
join: {
|
||||||
from: 'bill_located_costs.fromTransactionEntryId',
|
from: 'bill_located_costs.fromTransactionEntryId',
|
||||||
to: 'items_entries.id',
|
to: 'items_entries.id',
|
||||||
@@ -92,7 +96,7 @@ export class BillLandedCost extends BaseModel {
|
|||||||
},
|
},
|
||||||
allocatedFromExpenseEntry: {
|
allocatedFromExpenseEntry: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: ExpenseCategory.default,
|
modelClass: ExpenseCategory,
|
||||||
join: {
|
join: {
|
||||||
from: 'bill_located_costs.fromTransactionEntryId',
|
from: 'bill_located_costs.fromTransactionEntryId',
|
||||||
to: 'expense_transaction_categories.id',
|
to: 'expense_transaction_categories.id',
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import { BaseModel } from '@/models/Model';
|
||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
import TenantModel from 'models/TenantModel';
|
|
||||||
|
|
||||||
export default class BillLandedCostEntry extends TenantModel {
|
export class BillLandedCostEntry extends BaseModel {
|
||||||
|
cost!: number;
|
||||||
|
entryId!: number;
|
||||||
|
billLocatedCostId!: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
*/
|
*/
|
||||||
@@ -13,12 +17,14 @@ export default class BillLandedCostEntry extends TenantModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const ItemEntry = require('models/ItemEntry');
|
const {
|
||||||
|
ItemEntry,
|
||||||
|
} = require('../../TransactionItemEntry/models/ItemEntry');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
itemEntry: {
|
itemEntry: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: ItemEntry.default,
|
modelClass: ItemEntry,
|
||||||
join: {
|
join: {
|
||||||
from: 'bill_located_cost_entries.entryId',
|
from: 'bill_located_cost_entries.entryId',
|
||||||
to: 'items_entries.id',
|
to: 'items_entries.id',
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
|
|
||||||
|
export interface ILandedCostItemDTO {
|
||||||
|
entryId: number;
|
||||||
|
cost: number;
|
||||||
|
}
|
||||||
|
export type ILandedCostType = 'Expense' | 'Bill';
|
||||||
|
|
||||||
|
export interface ILandedCostDTO {
|
||||||
|
transactionType: ILandedCostType;
|
||||||
|
transactionId: number;
|
||||||
|
transactionEntryId: number;
|
||||||
|
allocationMethod: string;
|
||||||
|
description: string;
|
||||||
|
items: ILandedCostItemDTO[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILandedCostQueryDTO {
|
||||||
|
vendorId: number;
|
||||||
|
fromDate: Date;
|
||||||
|
toDate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUnallocatedListCost {
|
||||||
|
costNumber: string;
|
||||||
|
costAmount: number;
|
||||||
|
unallocatedAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILandedCostTransactionsQueryDTO {
|
||||||
|
transactionType: string;
|
||||||
|
date: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILandedCostEntriesQueryDTO {
|
||||||
|
transactionType: string;
|
||||||
|
transactionId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILandedCostTransaction {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
amount: number;
|
||||||
|
allocatedCostAmount: number;
|
||||||
|
unallocatedCostAmount: number;
|
||||||
|
currencyCode: string;
|
||||||
|
exchangeRate: number;
|
||||||
|
// formattedAllocatedCostAmount: string;
|
||||||
|
// formattedAmount: string;
|
||||||
|
// formattedUnallocatedCostAmount: string;
|
||||||
|
transactionType: string;
|
||||||
|
entries?: ILandedCostTransactionEntry[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILandedCostTransactionEntry {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
amount: number;
|
||||||
|
unallocatedCostAmount: number;
|
||||||
|
allocatedCostAmount: number;
|
||||||
|
description: string;
|
||||||
|
costAccountId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILandedCostTransactionEntryDOJO
|
||||||
|
extends ILandedCostTransactionEntry {
|
||||||
|
formattedAmount: string;
|
||||||
|
formattedUnallocatedCostAmount: string;
|
||||||
|
formattedAllocatedCostAmount: string;
|
||||||
|
}
|
||||||
|
export interface ILandedCostTransactionDOJO extends ILandedCostTransaction {
|
||||||
|
formattedAmount: string;
|
||||||
|
formattedUnallocatedCostAmount: string;
|
||||||
|
formattedAllocatedCostAmount: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILandedCostEntry {
|
||||||
|
id: number;
|
||||||
|
landedCost?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBillLandedCostTransaction {
|
||||||
|
id: number;
|
||||||
|
fromTransactionId: number;
|
||||||
|
fromTransactionType: string;
|
||||||
|
fromTransactionEntryId: number;
|
||||||
|
|
||||||
|
billId: number;
|
||||||
|
allocationMethod: string;
|
||||||
|
costAccountId: number;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
amount: number;
|
||||||
|
localAmount?: number;
|
||||||
|
currencyCode: string;
|
||||||
|
exchangeRate: number;
|
||||||
|
|
||||||
|
allocateEntries?: IBillLandedCostTransactionEntry[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBillLandedCostTransactionEntry {
|
||||||
|
cost: number;
|
||||||
|
entryId: number;
|
||||||
|
billLocatedCostId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllocatedLandedCostDeletedPayload {
|
||||||
|
tenantId: number;
|
||||||
|
oldBillLandedCost: IBillLandedCostTransaction;
|
||||||
|
billId: number;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllocatedLandedCostCreatedPayload {
|
||||||
|
tenantId: number;
|
||||||
|
bill: Bill;
|
||||||
|
billLandedCostId: number;
|
||||||
|
billLandedCost: IBillLandedCostTransaction;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBillAssociatedLandedCostTransactions {}
|
||||||
|
|
||||||
|
|
||||||
|
interface ICommonEntry {
|
||||||
|
id?: number;
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICommonLandedCostEntry extends ICommonEntry {
|
||||||
|
landedCost: boolean;
|
||||||
|
allocatedCostAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ICommonEntryDTO {
|
||||||
|
id?: number;
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICommonLandedCostEntryDTO extends ICommonEntryDTO {
|
||||||
|
landedCost?: boolean;
|
||||||
|
}
|
||||||
@@ -4,6 +4,13 @@ import { CreateBillPaymentService } from './commands/CreateBillPayment.service';
|
|||||||
import { EditBillPayment } from './commands/EditBillPayment.service';
|
import { EditBillPayment } from './commands/EditBillPayment.service';
|
||||||
import { GetBillPayment } from './queries/GetBillPayment.service';
|
import { GetBillPayment } from './queries/GetBillPayment.service';
|
||||||
import { DeleteBillPayment } from './commands/DeleteBillPayment.service';
|
import { DeleteBillPayment } from './commands/DeleteBillPayment.service';
|
||||||
|
import { BillPaymentBillSync } from './commands/BillPaymentBillSync.service';
|
||||||
|
import { GetPaymentBills } from './queries/GetPaymentBills.service';
|
||||||
|
import { BillPaymentValidators } from './commands/BillPaymentValidators.service';
|
||||||
|
import { CommandBillPaymentDTOTransformer } from './commands/CommandBillPaymentDTOTransformer.service';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
import { BranchTransactionDTOTransformer } from '../Branches/integrations/BranchTransactionDTOTransform';
|
||||||
|
import { BranchesSettingsService } from '../Branches/BranchesSettings';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -12,6 +19,13 @@ import { DeleteBillPayment } from './commands/DeleteBillPayment.service';
|
|||||||
EditBillPayment,
|
EditBillPayment,
|
||||||
GetBillPayment,
|
GetBillPayment,
|
||||||
DeleteBillPayment,
|
DeleteBillPayment,
|
||||||
|
BillPaymentBillSync,
|
||||||
|
GetPaymentBills,
|
||||||
|
BillPaymentValidators,
|
||||||
|
CommandBillPaymentDTOTransformer,
|
||||||
|
BranchTransactionDTOTransformer,
|
||||||
|
BranchesSettingsService,
|
||||||
|
TenancyContext
|
||||||
],
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { CreateBillPaymentService } from './commands/CreateBillPayment.service';
|
import { CreateBillPaymentService } from './commands/CreateBillPayment.service';
|
||||||
import { DeleteBillPayment } from './commands/DeleteBillPayment.service';
|
import { DeleteBillPayment } from './commands/DeleteBillPayment.service';
|
||||||
import { EditBillPayment } from './commands/EditBillPayment.service';
|
import { EditBillPayment } from './commands/EditBillPayment.service';
|
||||||
import { GetBillPayments } from './GetBillPayments';
|
// import { GetBillPayments } from './GetBillPayments';
|
||||||
import { GetBillPayment } from './queries/GetBillPayment.service';
|
import { GetBillPayment } from './queries/GetBillPayment.service';
|
||||||
import { GetPaymentBills } from './queries/GetPaymentBills.service';
|
import { GetPaymentBills } from './queries/GetPaymentBills.service';
|
||||||
import { IBillPaymentDTO } from './types/BillPayments.types';
|
import { IBillPaymentDTO } from './types/BillPayments.types';
|
||||||
@@ -17,7 +17,7 @@ export class BillPaymentsApplication {
|
|||||||
private createBillPaymentService: CreateBillPaymentService,
|
private createBillPaymentService: CreateBillPaymentService,
|
||||||
private deleteBillPaymentService: DeleteBillPayment,
|
private deleteBillPaymentService: DeleteBillPayment,
|
||||||
private editBillPaymentService: EditBillPayment,
|
private editBillPaymentService: EditBillPayment,
|
||||||
private getBillPaymentsService: GetBillPayments,
|
// private getBillPaymentsService: GetBillPayments,
|
||||||
private getBillPaymentService: GetBillPayment,
|
private getBillPaymentService: GetBillPayment,
|
||||||
private getPaymentBillsService: GetPaymentBills,
|
private getPaymentBillsService: GetPaymentBills,
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -1,75 +1,75 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
// import { Inject, Service } from 'typedi';
|
||||||
import * as R from 'ramda';
|
// import * as R from 'ramda';
|
||||||
import {
|
// import {
|
||||||
IBillPayment,
|
// IBillPayment,
|
||||||
IBillPaymentsFilter,
|
// IBillPaymentsFilter,
|
||||||
IPaginationMeta,
|
// IPaginationMeta,
|
||||||
IFilterMeta,
|
// IFilterMeta,
|
||||||
} from '@/interfaces';
|
// } from '@/interfaces';
|
||||||
import { BillPaymentTransformer } from './queries/BillPaymentTransformer';
|
// import { BillPaymentTransformer } from './queries/BillPaymentTransformer';
|
||||||
import DynamicListingService from '@/services/DynamicListing/DynamicListService';
|
// import DynamicListingService from '@/services/DynamicListing/DynamicListService';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
// import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||||
|
|
||||||
@Service()
|
// @Service()
|
||||||
export class GetBillPayments {
|
// export class GetBillPayments {
|
||||||
@Inject()
|
// @Inject()
|
||||||
private tenancy: HasTenancyService;
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
@Inject()
|
// @Inject()
|
||||||
private dynamicListService: DynamicListingService;
|
// private dynamicListService: DynamicListingService;
|
||||||
|
|
||||||
@Inject()
|
// @Inject()
|
||||||
private transformer: TransformerInjectable;
|
// private transformer: TransformerInjectable;
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Retrieve bill payment paginted and filterable list.
|
// * Retrieve bill payment paginted and filterable list.
|
||||||
* @param {number} tenantId
|
// * @param {number} tenantId
|
||||||
* @param {IBillPaymentsFilter} billPaymentsFilter
|
// * @param {IBillPaymentsFilter} billPaymentsFilter
|
||||||
*/
|
// */
|
||||||
public async getBillPayments(
|
// public async getBillPayments(
|
||||||
tenantId: number,
|
// tenantId: number,
|
||||||
filterDTO: IBillPaymentsFilter
|
// filterDTO: IBillPaymentsFilter
|
||||||
): Promise<{
|
// ): Promise<{
|
||||||
billPayments: IBillPayment[];
|
// billPayments: IBillPayment[];
|
||||||
pagination: IPaginationMeta;
|
// pagination: IPaginationMeta;
|
||||||
filterMeta: IFilterMeta;
|
// filterMeta: IFilterMeta;
|
||||||
}> {
|
// }> {
|
||||||
const { BillPayment } = this.tenancy.models(tenantId);
|
// const { BillPayment } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
// Parses filter DTO.
|
// // Parses filter DTO.
|
||||||
const filter = this.parseListFilterDTO(filterDTO);
|
// const filter = this.parseListFilterDTO(filterDTO);
|
||||||
|
|
||||||
// Dynamic list service.
|
// // Dynamic list service.
|
||||||
const dynamicList = await this.dynamicListService.dynamicList(
|
// const dynamicList = await this.dynamicListService.dynamicList(
|
||||||
tenantId,
|
// tenantId,
|
||||||
BillPayment,
|
// BillPayment,
|
||||||
filter
|
// filter
|
||||||
);
|
// );
|
||||||
const { results, pagination } = await BillPayment.query()
|
// const { results, pagination } = await BillPayment.query()
|
||||||
.onBuild((builder) => {
|
// .onBuild((builder) => {
|
||||||
builder.withGraphFetched('vendor');
|
// builder.withGraphFetched('vendor');
|
||||||
builder.withGraphFetched('paymentAccount');
|
// builder.withGraphFetched('paymentAccount');
|
||||||
|
|
||||||
dynamicList.buildQuery()(builder);
|
// dynamicList.buildQuery()(builder);
|
||||||
filter?.filterQuery && filter?.filterQuery(builder);
|
// filter?.filterQuery && filter?.filterQuery(builder);
|
||||||
})
|
// })
|
||||||
.pagination(filter.page - 1, filter.pageSize);
|
// .pagination(filter.page - 1, filter.pageSize);
|
||||||
|
|
||||||
// Transformes the bill payments models to POJO.
|
// // Transformes the bill payments models to POJO.
|
||||||
const billPayments = await this.transformer.transform(
|
// const billPayments = await this.transformer.transform(
|
||||||
tenantId,
|
// tenantId,
|
||||||
results,
|
// results,
|
||||||
new BillPaymentTransformer()
|
// new BillPaymentTransformer()
|
||||||
);
|
// );
|
||||||
return {
|
// return {
|
||||||
billPayments,
|
// billPayments,
|
||||||
pagination,
|
// pagination,
|
||||||
filterMeta: dynamicList.getResponseMeta(),
|
// filterMeta: dynamicList.getResponseMeta(),
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
private parseListFilterDTO(filterDTO) {
|
// private parseListFilterDTO(filterDTO) {
|
||||||
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
|
// return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { Bill } from '../../Bills/models/Bill';
|
import { Bill } from '../../Bills/models/Bill';
|
||||||
import { IBillPaymentEntryDTO } from '../types/BillPayments.types';
|
import { IBillPaymentEntryDTO } from '../types/BillPayments.types';
|
||||||
|
import { entriesAmountDiff } from '@/utils/entries-amount-diff';
|
||||||
|
import Objection from 'objection';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BillPaymentBillSync {
|
export class BillPaymentBillSync {
|
||||||
constructor(private readonly bill: typeof Bill) {}
|
constructor(
|
||||||
|
@Inject(Bill.name)
|
||||||
|
private readonly bill: typeof Bill
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves bills payment amount changes different.
|
* Saves bills payment amount changes different.
|
||||||
@@ -18,7 +23,7 @@ export class BillPaymentBillSync {
|
|||||||
oldPaymentMadeEntries?: IBillPaymentEntryDTO[],
|
oldPaymentMadeEntries?: IBillPaymentEntryDTO[],
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const opers: Promise<void>[] = [];
|
const opers: Objection.QueryBuilder<Bill, Bill[]>[] = [];
|
||||||
|
|
||||||
const diffEntries = entriesAmountDiff(
|
const diffEntries = entriesAmountDiff(
|
||||||
paymentMadeEntries,
|
paymentMadeEntries,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { ERRORS } from '../constants';
|
import { ERRORS } from '../constants';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Bill } from '../../Bills/models/Bill';
|
import { Bill } from '../../Bills/models/Bill';
|
||||||
import { BillPayment } from '../models/BillPayment';
|
import { BillPayment } from '../models/BillPayment';
|
||||||
import { IBillReceivePageEntry } from '../types/BillPayments.types';
|
import { IBillReceivePageEntry } from '../types/BillPayments.types';
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export class CreateBillPaymentService {
|
|||||||
public async createBillPayment(
|
public async createBillPayment(
|
||||||
billPaymentDTO: IBillPaymentDTO,
|
billPaymentDTO: IBillPaymentDTO,
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<IBillPayment> {
|
): Promise<BillPayment> {
|
||||||
const tenantMeta = await this.tenancyContext.getTenant(true);
|
const tenantMeta = await this.tenancyContext.getTenant(true);
|
||||||
|
|
||||||
// Retrieves the payment vendor or throw not found error.
|
// Retrieves the payment vendor or throw not found error.
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import { Model, mixin } from 'objection';
|
|||||||
// import { DEFAULT_VIEWS } from '@/services/Sales/PaymentReceived/constants';
|
// import { DEFAULT_VIEWS } from '@/services/Sales/PaymentReceived/constants';
|
||||||
// import ModelSearchable from './ModelSearchable';
|
// import ModelSearchable from './ModelSearchable';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
import { BillPaymentEntry } from './BillPaymentEntry';
|
||||||
|
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
||||||
|
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
|
||||||
|
|
||||||
export class BillPayment extends BaseModel{
|
export class BillPayment extends BaseModel{
|
||||||
vendorId: number;
|
vendorId: number;
|
||||||
@@ -23,6 +26,12 @@ export class BillPayment extends BaseModel{
|
|||||||
createdAt?: Date;
|
createdAt?: Date;
|
||||||
updatedAt?: Date;
|
updatedAt?: Date;
|
||||||
|
|
||||||
|
branchId?: number;
|
||||||
|
|
||||||
|
entries?: BillPaymentEntry[];
|
||||||
|
vendor?: Vendor;
|
||||||
|
attachments?: Document[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
// import TenantModel from 'models/TenantModel';
|
// import TenantModel from 'models/TenantModel';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
|
import { BillPayment } from './BillPayment';
|
||||||
|
|
||||||
export class BillPaymentEntry extends BaseModel {
|
export class BillPaymentEntry extends BaseModel {
|
||||||
public billPaymentId: number;
|
public billPaymentId: number;
|
||||||
@@ -8,6 +10,9 @@ export class BillPaymentEntry extends BaseModel {
|
|||||||
public paymentAmount: number;
|
public paymentAmount: number;
|
||||||
public index: number;
|
public index: number;
|
||||||
|
|
||||||
|
bill?: Bill;
|
||||||
|
payment?: BillPayment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +37,7 @@ export class BillPaymentEntry extends BaseModel {
|
|||||||
return {
|
return {
|
||||||
payment: {
|
payment: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: BillPayment.default,
|
modelClass: BillPayment,
|
||||||
join: {
|
join: {
|
||||||
from: 'bills_payments_entries.billPaymentId',
|
from: 'bills_payments_entries.billPaymentId',
|
||||||
to: 'bills_payments.id',
|
to: 'bills_payments.id',
|
||||||
@@ -40,7 +45,7 @@ export class BillPaymentEntry extends BaseModel {
|
|||||||
},
|
},
|
||||||
bill: {
|
bill: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Bill.default,
|
modelClass: Bill,
|
||||||
join: {
|
join: {
|
||||||
from: 'bills_payments_entries.billId',
|
from: 'bills_payments_entries.billId',
|
||||||
to: 'bills.id',
|
to: 'bills.id',
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { IBill } from './Bill';
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
import { AttachmentLinkDTO } from './Attachments';
|
|
||||||
import { BillPayment } from '../models/BillPayment';
|
import { BillPayment } from '../models/BillPayment';
|
||||||
|
import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
|
||||||
|
|
||||||
export interface IBillPaymentEntry {
|
export interface IBillPaymentEntry {
|
||||||
id?: number;
|
id?: number;
|
||||||
billPaymentId: number;
|
billPaymentId: number;
|
||||||
billId: number;
|
billId: number;
|
||||||
paymentAmount: number;
|
paymentAmount: number;
|
||||||
|
bill?: Bill;
|
||||||
bill?: IBill;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBillPayment {
|
export interface IBillPayment {
|
||||||
@@ -39,6 +38,7 @@ export interface IBillPaymentEntryDTO {
|
|||||||
|
|
||||||
export interface IBillPaymentDTO {
|
export interface IBillPaymentDTO {
|
||||||
vendorId: number;
|
vendorId: number;
|
||||||
|
amount: number;
|
||||||
paymentAccountId: number;
|
paymentAccountId: number;
|
||||||
paymentNumber?: string;
|
paymentNumber?: string;
|
||||||
paymentDate: Date;
|
paymentDate: Date;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class BillsApplication {
|
|||||||
private deleteBillService: DeleteBill,
|
private deleteBillService: DeleteBill,
|
||||||
private getDueBillsService: GetDueBills,
|
private getDueBillsService: GetDueBills,
|
||||||
private openBillService: OpenBillService,
|
private openBillService: OpenBillService,
|
||||||
private getBillPaymentsService: GetBillPayments,
|
// private getBillPaymentsService: GetBillPayments,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +99,7 @@ export class BillsApplication {
|
|||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {number} billId
|
* @param {number} billId
|
||||||
*/
|
*/
|
||||||
public getBillPayments(billId: number) {
|
// public getBillPayments(billId: number) {
|
||||||
return this.getBillPaymentsService.getBillPayments(billId);
|
// return this.getBillPaymentsService.getBillPayments(billId);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
48
packages/server-nest/src/modules/Bills/Bills.controller.ts
Normal file
48
packages/server-nest/src/modules/Bills/Bills.controller.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Post,
|
||||||
|
Body,
|
||||||
|
Put,
|
||||||
|
Param,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { BillsApplication } from './Bills.application';
|
||||||
|
import { IBillDTO, IBillEditDTO } from './Bills.types';
|
||||||
|
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||||
|
|
||||||
|
@Controller('bills')
|
||||||
|
@PublicRoute()
|
||||||
|
export class BillsController {
|
||||||
|
constructor(private billsApplication: BillsApplication) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
createBill(@Body() billDTO: IBillDTO) {
|
||||||
|
return this.billsApplication.createBill(billDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id')
|
||||||
|
editBill(@Param('id') billId: number, @Body() billDTO: IBillEditDTO) {
|
||||||
|
return this.billsApplication.editBill(billId, billDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
deleteBill(@Param('id') billId: number) {
|
||||||
|
return this.billsApplication.deleteBill(billId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
getBill(@Param('id') billId: number) {
|
||||||
|
return this.billsApplication.getBill(billId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/open')
|
||||||
|
openBill(@Param('id') billId: number) {
|
||||||
|
return this.billsApplication.openBill(billId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('due')
|
||||||
|
getDueBills(@Body('vendorId') vendorId?: number) {
|
||||||
|
return this.billsApplication.getDueBills(vendorId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,14 +4,40 @@ import { CreateBill } from './commands/CreateBill.service';
|
|||||||
import { DeleteBill } from './commands/DeleteBill.service';
|
import { DeleteBill } from './commands/DeleteBill.service';
|
||||||
import { GetBill } from './queries/GetBill';
|
import { GetBill } from './queries/GetBill';
|
||||||
import { BillDTOTransformer } from './commands/BillDTOTransformer.service';
|
import { BillDTOTransformer } from './commands/BillDTOTransformer.service';
|
||||||
|
import { EditBillService } from './commands/EditBill.service';
|
||||||
|
import { GetDueBills } from './queries/GetDueBills.service';
|
||||||
|
import { OpenBillService } from './commands/OpenBill.service';
|
||||||
|
import { BillsValidators } from './commands/BillsValidators.service';
|
||||||
|
import { ItemsEntriesService } from '../Items/ItemsEntries.service';
|
||||||
|
import { BranchTransactionDTOTransformer } from '../Branches/integrations/BranchTransactionDTOTransform';
|
||||||
|
import { BranchesSettingsService } from '../Branches/BranchesSettings';
|
||||||
|
import { WarehouseTransactionDTOTransform } from '../Warehouses/Integrations/WarehouseTransactionDTOTransform';
|
||||||
|
import { WarehousesSettings } from '../Warehouses/WarehousesSettings';
|
||||||
|
import { ItemEntriesTaxTransactions } from '../TaxRates/ItemEntriesTaxTransactions.service';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
import { BillsController } from './Bills.controller';
|
||||||
|
import { BillLandedCostsModule } from '../BillLandedCosts/BillLandedCosts.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [BillLandedCostsModule],
|
||||||
providers: [
|
providers: [
|
||||||
|
TenancyContext,
|
||||||
BillsApplication,
|
BillsApplication,
|
||||||
|
BranchTransactionDTOTransformer,
|
||||||
|
WarehouseTransactionDTOTransform,
|
||||||
|
WarehousesSettings,
|
||||||
|
ItemEntriesTaxTransactions,
|
||||||
|
BranchesSettingsService,
|
||||||
CreateBill,
|
CreateBill,
|
||||||
|
EditBillService,
|
||||||
|
GetDueBills,
|
||||||
|
OpenBillService,
|
||||||
GetBill,
|
GetBill,
|
||||||
DeleteBill,
|
DeleteBill,
|
||||||
BillDTOTransformer,
|
BillDTOTransformer,
|
||||||
|
BillsValidators,
|
||||||
|
ItemsEntriesService
|
||||||
],
|
],
|
||||||
|
controllers: [BillsController],
|
||||||
})
|
})
|
||||||
export class BillsModule {}
|
export class BillsModule {}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export interface IBillCreatedPayload {
|
|||||||
// tenantId: number;
|
// tenantId: number;
|
||||||
bill: Bill;
|
bill: Bill;
|
||||||
billDTO: IBillDTO;
|
billDTO: IBillDTO;
|
||||||
billId: number;
|
// billId: number;
|
||||||
trx?: Knex.Transaction;
|
trx?: Knex.Transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { omit, sumBy } from 'lodash';
|
import { omit, sumBy } from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
import * as composeAsync from 'async/compose';
|
||||||
import { formatDateFields } from '@/utils/format-date-fields';
|
import { formatDateFields } from '@/utils/format-date-fields';
|
||||||
import composeAsync from 'async/compose';
|
|
||||||
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
|
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
|
||||||
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
|
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
|
||||||
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
||||||
import { Item } from '@/modules/Items/models/Item';
|
import { Item } from '@/modules/Items/models/Item';
|
||||||
|
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
||||||
import { ItemEntriesTaxTransactions } from '@/modules/TaxRates/ItemEntriesTaxTransactions.service';
|
import { ItemEntriesTaxTransactions } from '@/modules/TaxRates/ItemEntriesTaxTransactions.service';
|
||||||
import { IBillDTO } from '../Bills.types';
|
import { IBillDTO } from '../Bills.types';
|
||||||
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
|
||||||
import { Bill } from '../models/Bill';
|
import { Bill } from '../models/Bill';
|
||||||
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
|
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
|
||||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||||
@@ -23,8 +23,8 @@ export class BillDTOTransformer {
|
|||||||
private taxDTOTransformer: ItemEntriesTaxTransactions,
|
private taxDTOTransformer: ItemEntriesTaxTransactions,
|
||||||
private tenancyContext: TenancyContext,
|
private tenancyContext: TenancyContext,
|
||||||
|
|
||||||
@Inject(ItemEntry) private itemEntryModel: typeof ItemEntry,
|
@Inject(ItemEntry.name) private itemEntryModel: typeof ItemEntry,
|
||||||
@Inject(Item) private itemModel: typeof Item,
|
@Inject(Item.name) private itemModel: typeof Item,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +44,9 @@ export class BillDTOTransformer {
|
|||||||
private getBillLandedCostAmount(billDTO: IBillDTO): number {
|
private getBillLandedCostAmount(billDTO: IBillDTO): number {
|
||||||
const costEntries = billDTO.entries.filter((entry) => entry.landedCost);
|
const costEntries = billDTO.entries.filter((entry) => entry.landedCost);
|
||||||
|
|
||||||
return this.getBillEntriesTotal(costEntries);
|
// return this.getBillEntriesTotal(costEntries);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +59,7 @@ export class BillDTOTransformer {
|
|||||||
billDTO: IBillDTO,
|
billDTO: IBillDTO,
|
||||||
vendor: Vendor,
|
vendor: Vendor,
|
||||||
oldBill?: Bill,
|
oldBill?: Bill,
|
||||||
) {
|
): Promise<Bill> {
|
||||||
const amount = sumBy(billDTO.entries, (e) =>
|
const amount = sumBy(billDTO.entries, (e) =>
|
||||||
this.itemEntryModel.calcAmount(e),
|
this.itemEntryModel.calcAmount(e),
|
||||||
);
|
);
|
||||||
@@ -112,9 +114,9 @@ export class BillDTOTransformer {
|
|||||||
return R.compose(
|
return R.compose(
|
||||||
// Associates tax amount withheld to the model.
|
// Associates tax amount withheld to the model.
|
||||||
this.taxDTOTransformer.assocTaxAmountWithheldFromEntries,
|
this.taxDTOTransformer.assocTaxAmountWithheldFromEntries,
|
||||||
this.branchDTOTransform.transformDTO,
|
this.branchDTOTransform.transformDTO<Bill>,
|
||||||
this.warehouseDTOTransform.transformDTO,
|
this.warehouseDTOTransform.transformDTO<Bill>,
|
||||||
)(initialDTO);
|
)(initialDTO) as Bill;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
|
|||||||
import { Item } from '@/modules/Items/models/Item';
|
import { Item } from '@/modules/Items/models/Item';
|
||||||
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
||||||
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
||||||
|
import { VendorCreditAppliedBill } from '@/modules/VendorCredit/models/VendorCreditAppliedBill';
|
||||||
|
import { transformToMap } from '@/utils/transform-to-key';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BillsValidators {
|
export class BillsValidators {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export class CreateBill {
|
|||||||
private billModel: typeof Bill,
|
private billModel: typeof Bill,
|
||||||
|
|
||||||
@Inject(Vendor.name)
|
@Inject(Vendor.name)
|
||||||
private contactModel: typeof Vendor,
|
private vendorModel: typeof Vendor,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,9 +49,8 @@ export class CreateBill {
|
|||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<Bill> {
|
): Promise<Bill> {
|
||||||
// Retrieves the given bill vendor or throw not found error.
|
// Retrieves the given bill vendor or throw not found error.
|
||||||
const vendor = await this.contactModel
|
const vendor = await this.vendorModel
|
||||||
.query()
|
.query()
|
||||||
.modify('vendor')
|
|
||||||
.findById(billDTO.vendorId)
|
.findById(billDTO.vendorId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
@@ -70,10 +69,7 @@ export class CreateBill {
|
|||||||
billDTO.entries,
|
billDTO.entries,
|
||||||
);
|
);
|
||||||
// Transform the bill DTO to model object.
|
// Transform the bill DTO to model object.
|
||||||
const billObj = await this.transformerDTO.billDTOToModel(
|
const billObj = await this.transformerDTO.billDTOToModel(billDTO, vendor);
|
||||||
billDTO,
|
|
||||||
vendor,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write new bill transaction with associated transactions under UOW env.
|
// Write new bill transaction with associated transactions under UOW env.
|
||||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
@@ -84,12 +80,11 @@ export class CreateBill {
|
|||||||
} as IBillCreatingPayload);
|
} as IBillCreatingPayload);
|
||||||
|
|
||||||
// Inserts the bill graph object to the storage.
|
// Inserts the bill graph object to the storage.
|
||||||
const bill = await this.billModel.query(trx).upsertGraph(billObj);
|
const bill = await this.billModel.query(trx).upsertGraphAndFetch(billObj);
|
||||||
|
|
||||||
// Triggers `onBillCreated` event.
|
// Triggers `onBillCreated` event.
|
||||||
await this.eventPublisher.emitAsync(events.bill.onCreated, {
|
await this.eventPublisher.emitAsync(events.bill.onCreated, {
|
||||||
bill,
|
bill,
|
||||||
billId: bill.id,
|
|
||||||
billDTO,
|
billDTO,
|
||||||
trx,
|
trx,
|
||||||
} as IBillCreatedPayload);
|
} as IBillCreatedPayload);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export class DeleteBill {
|
|||||||
} as IBillEventDeletingPayload);
|
} as IBillEventDeletingPayload);
|
||||||
|
|
||||||
// Delete all associated bill entries.
|
// Delete all associated bill entries.
|
||||||
await ItemEntry.query(trx)
|
await this.itemEntryModel.query(trx)
|
||||||
.where('reference_type', 'Bill')
|
.where('reference_type', 'Bill')
|
||||||
.where('reference_id', billId)
|
.where('reference_id', billId)
|
||||||
.delete();
|
.delete();
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import { BillDTOTransformer } from './BillDTOTransformer.service';
|
|||||||
import { Bill } from '../models/Bill';
|
import { Bill } from '../models/Bill';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { TransactionLandedCostEntriesService } from '@/modules/BillLandedCosts/TransactionLandedCostEntries.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EditBillService {
|
export class EditBillService {
|
||||||
@@ -21,7 +22,7 @@ export class EditBillService {
|
|||||||
private itemsEntriesService: ItemsEntriesService,
|
private itemsEntriesService: ItemsEntriesService,
|
||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
private eventPublisher: EventEmitter2,
|
private eventPublisher: EventEmitter2,
|
||||||
private entriesService: ItemEntries,
|
private transactionLandedCostEntries: TransactionLandedCostEntriesService,
|
||||||
private transformerDTO: BillDTOTransformer,
|
private transformerDTO: BillDTOTransformer,
|
||||||
@Inject(Bill.name) private billModel: typeof Bill,
|
@Inject(Bill.name) private billModel: typeof Bill,
|
||||||
@Inject(Vendor.name) private contactModel: typeof Vendor,
|
@Inject(Vendor.name) private contactModel: typeof Vendor,
|
||||||
@@ -97,12 +98,12 @@ export class EditBillService {
|
|||||||
oldBill.paymentAmount
|
oldBill.paymentAmount
|
||||||
);
|
);
|
||||||
// Validate landed cost entries that have allocated cost could not be deleted.
|
// Validate landed cost entries that have allocated cost could not be deleted.
|
||||||
await this.entriesService.validateLandedCostEntriesNotDeleted(
|
await this.transactionLandedCostEntries.validateLandedCostEntriesNotDeleted(
|
||||||
oldBill.entries,
|
oldBill.entries,
|
||||||
billObj.entries
|
billObj.entries
|
||||||
);
|
);
|
||||||
// Validate new landed cost entries should be bigger than new entries.
|
// Validate new landed cost entries should be bigger than new entries.
|
||||||
await this.entriesService.validateLocatedCostEntriesSmallerThanNewEntries(
|
await this.transactionLandedCostEntries.validateLocatedCostEntriesSmallerThanNewEntries(
|
||||||
oldBill.entries,
|
oldBill.entries,
|
||||||
billObj.entries
|
billObj.entries
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import moment from 'moment';
|
|||||||
// import { DEFAULT_VIEWS } from '@/services/Purchases/Bills/constants';
|
// import { DEFAULT_VIEWS } from '@/services/Purchases/Bills/constants';
|
||||||
// import ModelSearchable from './ModelSearchable';
|
// import ModelSearchable from './ModelSearchable';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
||||||
|
|
||||||
export class Bill extends BaseModel{
|
export class Bill extends BaseModel{
|
||||||
public amount: number;
|
public amount: number;
|
||||||
@@ -31,9 +32,14 @@ export class Bill extends BaseModel{
|
|||||||
public openedAt: Date | string;
|
public openedAt: Date | string;
|
||||||
public userId: number;
|
public userId: number;
|
||||||
|
|
||||||
|
public branchId: number;
|
||||||
|
public warehouseId: number;
|
||||||
|
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
public updatedAt: Date | null;
|
public updatedAt: Date | null;
|
||||||
|
|
||||||
|
public entries?: ItemEntry[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamps columns.
|
* Timestamps columns.
|
||||||
*/
|
*/
|
||||||
@@ -410,125 +416,125 @@ export class Bill extends BaseModel{
|
|||||||
/**
|
/**
|
||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
// static get relationMappings() {
|
||||||
const Vendor = require('models/Vendor');
|
// const Vendor = require('models/Vendor');
|
||||||
const ItemEntry = require('models/ItemEntry');
|
// const ItemEntry = require('models/ItemEntry');
|
||||||
const BillLandedCost = require('models/BillLandedCost');
|
// const BillLandedCost = require('models/BillLandedCost');
|
||||||
const Branch = require('models/Branch');
|
// const Branch = require('models/Branch');
|
||||||
const Warehouse = require('models/Warehouse');
|
// const Warehouse = require('models/Warehouse');
|
||||||
const TaxRateTransaction = require('models/TaxRateTransaction');
|
// const TaxRateTransaction = require('models/TaxRateTransaction');
|
||||||
const Document = require('models/Document');
|
// const Document = require('models/Document');
|
||||||
const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
vendor: {
|
// vendor: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Vendor.default,
|
// modelClass: Vendor.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.vendorId',
|
// from: 'bills.vendorId',
|
||||||
to: 'contacts.id',
|
// to: 'contacts.id',
|
||||||
},
|
// },
|
||||||
filter(query) {
|
// filter(query) {
|
||||||
query.where('contact_service', 'vendor');
|
// query.where('contact_service', 'vendor');
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
entries: {
|
// entries: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: ItemEntry.default,
|
// modelClass: ItemEntry.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.id',
|
// from: 'bills.id',
|
||||||
to: 'items_entries.referenceId',
|
// to: 'items_entries.referenceId',
|
||||||
},
|
// },
|
||||||
filter(builder) {
|
// filter(builder) {
|
||||||
builder.where('reference_type', 'Bill');
|
// builder.where('reference_type', 'Bill');
|
||||||
builder.orderBy('index', 'ASC');
|
// builder.orderBy('index', 'ASC');
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
locatedLandedCosts: {
|
// locatedLandedCosts: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: BillLandedCost.default,
|
// modelClass: BillLandedCost.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.id',
|
// from: 'bills.id',
|
||||||
to: 'bill_located_costs.billId',
|
// to: 'bill_located_costs.billId',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Bill may belongs to associated branch.
|
// * Bill may belongs to associated branch.
|
||||||
*/
|
// */
|
||||||
branch: {
|
// branch: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Branch.default,
|
// modelClass: Branch.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.branchId',
|
// from: 'bills.branchId',
|
||||||
to: 'branches.id',
|
// to: 'branches.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Bill may has associated warehouse.
|
// * Bill may has associated warehouse.
|
||||||
*/
|
// */
|
||||||
warehouse: {
|
// warehouse: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Warehouse.default,
|
// modelClass: Warehouse.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.warehouseId',
|
// from: 'bills.warehouseId',
|
||||||
to: 'warehouses.id',
|
// to: 'warehouses.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Bill may has associated tax rate transactions.
|
// * Bill may has associated tax rate transactions.
|
||||||
*/
|
// */
|
||||||
taxes: {
|
// taxes: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: TaxRateTransaction.default,
|
// modelClass: TaxRateTransaction.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.id',
|
// from: 'bills.id',
|
||||||
to: 'tax_rate_transactions.referenceId',
|
// to: 'tax_rate_transactions.referenceId',
|
||||||
},
|
// },
|
||||||
filter(builder) {
|
// filter(builder) {
|
||||||
builder.where('reference_type', 'Bill');
|
// builder.where('reference_type', 'Bill');
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Bill may has many attached attachments.
|
// * Bill may has many attached attachments.
|
||||||
*/
|
// */
|
||||||
attachments: {
|
// attachments: {
|
||||||
relation: Model.ManyToManyRelation,
|
// relation: Model.ManyToManyRelation,
|
||||||
modelClass: Document.default,
|
// modelClass: Document.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.id',
|
// from: 'bills.id',
|
||||||
through: {
|
// through: {
|
||||||
from: 'document_links.modelId',
|
// from: 'document_links.modelId',
|
||||||
to: 'document_links.documentId',
|
// to: 'document_links.documentId',
|
||||||
},
|
// },
|
||||||
to: 'documents.id',
|
// to: 'documents.id',
|
||||||
},
|
// },
|
||||||
filter(query) {
|
// filter(query) {
|
||||||
query.where('model_ref', 'Bill');
|
// query.where('model_ref', 'Bill');
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Bill may belongs to matched bank transaction.
|
// * Bill may belongs to matched bank transaction.
|
||||||
*/
|
// */
|
||||||
matchedBankTransaction: {
|
// matchedBankTransaction: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: MatchedBankTransaction,
|
// modelClass: MatchedBankTransaction,
|
||||||
join: {
|
// join: {
|
||||||
from: 'bills.id',
|
// from: 'bills.id',
|
||||||
to: 'matched_bank_transactions.referenceId',
|
// to: 'matched_bank_transactions.referenceId',
|
||||||
},
|
// },
|
||||||
filter(query) {
|
// filter(query) {
|
||||||
query.where('reference_type', 'Bill');
|
// query.where('reference_type', 'Bill');
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the not found bills ids as array that associated to the given vendor.
|
* Retrieve the not found bills ids as array that associated to the given vendor.
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Bill } from '../models/Bill';
|
import { Bill } from '../models/Bill';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetDueBills {
|
export class GetDueBills {
|
||||||
constructor(private billModel: typeof Bill) {}
|
constructor(
|
||||||
|
@Inject(Bill.name)
|
||||||
|
private billModel: typeof Bill,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all due bills or for specific given vendor id.
|
* Retrieve all due bills or for specific given vendor id.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { ActivateBranches } from './commands/ActivateBranchesFeature.service';
|
|||||||
import { BranchesApplication } from './BranchesApplication.service';
|
import { BranchesApplication } from './BranchesApplication.service';
|
||||||
import { BranchesSettingsService } from './BranchesSettings';
|
import { BranchesSettingsService } from './BranchesSettings';
|
||||||
import { BranchCommandValidator } from './commands/BranchCommandValidator.service';
|
import { BranchCommandValidator } from './commands/BranchCommandValidator.service';
|
||||||
|
import { BranchTransactionDTOTransformer } from './integrations/BranchTransactionDTOTransform';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule],
|
||||||
@@ -29,7 +30,9 @@ import { BranchCommandValidator } from './commands/BranchCommandValidator.servic
|
|||||||
BranchesSettingsService,
|
BranchesSettingsService,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
BranchCommandValidator
|
BranchCommandValidator,
|
||||||
|
BranchTransactionDTOTransformer
|
||||||
],
|
],
|
||||||
|
exports: [BranchTransactionDTOTransformer],
|
||||||
})
|
})
|
||||||
export class BranchesModule {}
|
export class BranchesModule {}
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ import { ChromiumlyTenancy } from './ChromiumlyTenancy.service';
|
|||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [ChromiumlyHtmlConvert, ChromiumlyTenancy],
|
providers: [ChromiumlyHtmlConvert, ChromiumlyTenancy],
|
||||||
|
exports: [ChromiumlyHtmlConvert, ChromiumlyTenancy],
|
||||||
})
|
})
|
||||||
export class ChromiumlyTenancyModule {}
|
export class ChromiumlyTenancyModule {}
|
||||||
|
|||||||
@@ -181,12 +181,12 @@ export class CreditNote extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const AccountTransaction = require('models/AccountTransaction');
|
const { AccountTransaction } = require('../../Accounts/models/AccountTransaction.model');
|
||||||
const ItemEntry = require('models/ItemEntry');
|
const { ItemEntry } = require('../../TransactionItemEntry/models/ItemEntry');
|
||||||
const Customer = require('models/Customer');
|
const { Customer } = require('../../Customers/models/Customer');
|
||||||
const Branch = require('models/Branch');
|
const { Branch } = require('../../Branches/models/Branch.model');
|
||||||
const Document = require('models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
const Warehouse = require('models/Warehouse');
|
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
@@ -194,7 +194,7 @@ export class CreditNote extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
entries: {
|
entries: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: ItemEntry.default,
|
modelClass: ItemEntry,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_notes.id',
|
from: 'credit_notes.id',
|
||||||
to: 'items_entries.referenceId',
|
to: 'items_entries.referenceId',
|
||||||
@@ -210,7 +210,7 @@ export class CreditNote extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
customer: {
|
customer: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Customer.default,
|
modelClass: Customer,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_notes.customerId',
|
from: 'credit_notes.customerId',
|
||||||
to: 'contacts.id',
|
to: 'contacts.id',
|
||||||
@@ -225,7 +225,7 @@ export class CreditNote extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
transactions: {
|
transactions: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: AccountTransaction.default,
|
modelClass: AccountTransaction,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_notes.id',
|
from: 'credit_notes.id',
|
||||||
to: 'accounts_transactions.referenceId',
|
to: 'accounts_transactions.referenceId',
|
||||||
@@ -240,7 +240,7 @@ export class CreditNote extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
branch: {
|
branch: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Branch.default,
|
modelClass: Branch,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_notes.branchId',
|
from: 'credit_notes.branchId',
|
||||||
to: 'branches.id',
|
to: 'branches.id',
|
||||||
@@ -252,7 +252,7 @@ export class CreditNote extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
warehouse: {
|
warehouse: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Warehouse.default,
|
modelClass: Warehouse,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_notes.warehouseId',
|
from: 'credit_notes.warehouseId',
|
||||||
to: 'warehouses.id',
|
to: 'warehouses.id',
|
||||||
@@ -264,7 +264,7 @@ export class CreditNote extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
attachments: {
|
attachments: {
|
||||||
relation: Model.ManyToManyRelation,
|
relation: Model.ManyToManyRelation,
|
||||||
modelClass: Document.default,
|
modelClass: Document,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_notes.id',
|
from: 'credit_notes.id',
|
||||||
through: {
|
through: {
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ export class CreditNoteAppliedInvoice extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const SaleInvoice = require('models/SaleInvoice');
|
const { SaleInvoice } = require('../../SaleInvoices/models/SaleInvoice');
|
||||||
const CreditNote = require('models/CreditNote');
|
const { CreditNote } = require('../../CreditNotes/models/CreditNote');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
saleInvoice: {
|
saleInvoice: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: SaleInvoice.default,
|
modelClass: SaleInvoice,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_note_applied_invoice.invoiceId',
|
from: 'credit_note_applied_invoice.invoiceId',
|
||||||
to: 'sales_invoices.id',
|
to: 'sales_invoices.id',
|
||||||
@@ -39,7 +39,7 @@ export class CreditNoteAppliedInvoice extends BaseModel {
|
|||||||
|
|
||||||
creditNote: {
|
creditNote: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: CreditNote.default,
|
modelClass: CreditNote,
|
||||||
join: {
|
join: {
|
||||||
from: 'credit_note_applied_invoice.creditNoteId',
|
from: 'credit_note_applied_invoice.creditNoteId',
|
||||||
to: 'credit_notes.id',
|
to: 'credit_notes.id',
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ import {
|
|||||||
ICustomerNewDTO,
|
ICustomerNewDTO,
|
||||||
ICustomerOpeningBalanceEditDTO,
|
ICustomerOpeningBalanceEditDTO,
|
||||||
} from './types/Customers.types';
|
} from './types/Customers.types';
|
||||||
|
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||||
|
|
||||||
@Controller('customers')
|
@Controller('customers')
|
||||||
|
@PublicRoute()
|
||||||
export class CustomersController {
|
export class CustomersController {
|
||||||
constructor(private customersApplication: CustomersApplication) {}
|
constructor(private customersApplication: CustomersApplication) {}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class DeleteCustomer {
|
|||||||
constructor(
|
constructor(
|
||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
private eventPublisher: EventEmitter2,
|
private eventPublisher: EventEmitter2,
|
||||||
@Inject(Customer.name) private contactModel: typeof Customer,
|
@Inject(Customer.name) private customerModel: typeof Customer,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,10 +31,9 @@ export class DeleteCustomer {
|
|||||||
customerId: number,
|
customerId: number,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Retrieve the customer or throw not found service error.
|
// Retrieve the customer or throw not found service error.
|
||||||
const oldCustomer = await this.contactModel
|
const oldCustomer = await this.customerModel
|
||||||
.query()
|
.query()
|
||||||
.findById(customerId)
|
.findById(customerId)
|
||||||
.modify('customer')
|
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
// .queryAndThrowIfHasRelations({
|
// .queryAndThrowIfHasRelations({
|
||||||
// type: ERRORS.CUSTOMER_HAS_TRANSACTIONS,
|
// type: ERRORS.CUSTOMER_HAS_TRANSACTIONS,
|
||||||
@@ -49,7 +48,7 @@ export class DeleteCustomer {
|
|||||||
// Deletes the customer and associated entities under UOW transaction.
|
// Deletes the customer and associated entities under UOW transaction.
|
||||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
// Delete the customer from the storage.
|
// Delete the customer from the storage.
|
||||||
await this.contactModel.query(trx).findById(customerId).delete();
|
await this.customerModel.query(trx).findById(customerId).delete();
|
||||||
|
|
||||||
// Throws `onCustomerDeleted` event.
|
// Throws `onCustomerDeleted` event.
|
||||||
await this.eventPublisher.emitAsync(events.customers.onDeleted, {
|
await this.eventPublisher.emitAsync(events.customers.onDeleted, {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class EditCustomer {
|
|||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
private eventPublisher: EventEmitter2,
|
private eventPublisher: EventEmitter2,
|
||||||
private customerDTO: CreateEditCustomerDTO,
|
private customerDTO: CreateEditCustomerDTO,
|
||||||
@Inject(Customer.name) private contactModel: typeof Customer,
|
@Inject(Customer.name) private customerModel: typeof Customer,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,10 +37,9 @@ export class EditCustomer {
|
|||||||
customerDTO: ICustomerEditDTO,
|
customerDTO: ICustomerEditDTO,
|
||||||
): Promise<Customer> {
|
): Promise<Customer> {
|
||||||
// Retrieve the customer or throw not found error.
|
// Retrieve the customer or throw not found error.
|
||||||
const oldCustomer = await this.contactModel
|
const oldCustomer = await this.customerModel
|
||||||
.query()
|
.query()
|
||||||
.findById(customerId)
|
.findById(customerId)
|
||||||
.modify('customer')
|
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
// Transforms the given customer DTO to object.
|
// Transforms the given customer DTO to object.
|
||||||
@@ -56,7 +55,7 @@ export class EditCustomer {
|
|||||||
} as ICustomerEventEditingPayload);
|
} as ICustomerEventEditingPayload);
|
||||||
|
|
||||||
// Edits the customer details on the storage.
|
// Edits the customer details on the storage.
|
||||||
const customer = await this.contactModel
|
const customer = await this.customerModel
|
||||||
.query()
|
.query()
|
||||||
.updateAndFetchById(customerId, {
|
.updateAndFetchById(customerId, {
|
||||||
...customerObj,
|
...customerObj,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { CommandExpenseValidator } from './CommandExpenseValidator.service';
|
|||||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||||
import { Expense } from '../models/Expense.model';
|
import { Expense } from '../models/Expense.model';
|
||||||
import ExpenseCategory from '../models/ExpenseCategory.model';
|
import { ExpenseCategory } from '../models/ExpenseCategory.model';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
import {
|
import {
|
||||||
IExpenseEventDeletePayload,
|
IExpenseEventDeletePayload,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
|
||||||
export default class ExpenseCategory extends BaseModel {
|
export class ExpenseCategory extends BaseModel {
|
||||||
amount!: number;
|
amount!: number;
|
||||||
allocatedCostAmount!: number;
|
allocatedCostAmount!: number;
|
||||||
|
|
||||||
@@ -31,12 +31,12 @@ export default class ExpenseCategory extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const Account = require('models/Account');
|
const { Account } = require('../../Accounts/models/Account.model');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
expenseAccount: {
|
expenseAccount: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Account.default,
|
modelClass: Account,
|
||||||
join: {
|
join: {
|
||||||
from: 'expense_transaction_categories.expenseAccountId',
|
from: 'expense_transaction_categories.expenseAccountId',
|
||||||
to: 'accounts.id',
|
to: 'accounts.id',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import { Transformer } from '@/modules/Transformer/Transformer';
|
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||||
import ExpenseCategory from '../models/ExpenseCategory.model';
|
import { ExpenseCategory } from '../models/ExpenseCategory.model';
|
||||||
|
|
||||||
export class ExpenseCategoryTransformer extends Transformer {
|
export class ExpenseCategoryTransformer extends Transformer {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { ItemsApplicationService } from './ItemsApplication.service';
|
|||||||
import { ItemTransactionsService } from './ItemTransactions.service';
|
import { ItemTransactionsService } from './ItemTransactions.service';
|
||||||
import { GetItemService } from './GetItem.service';
|
import { GetItemService } from './GetItem.service';
|
||||||
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
||||||
|
import { ItemsEntriesService } from './ItemsEntries.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule],
|
||||||
@@ -28,6 +29,8 @@ import { TransformerInjectable } from '../Transformer/TransformerInjectable.serv
|
|||||||
ItemTransactionsService,
|
ItemTransactionsService,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
|
ItemsEntriesService
|
||||||
],
|
],
|
||||||
|
exports: [ItemsEntriesService]
|
||||||
})
|
})
|
||||||
export class ItemsModule {}
|
export class ItemsModule {}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ export class ItemsEntriesService {
|
|||||||
/**
|
/**
|
||||||
* Sets the cost/sell accounts to the invoice entries.
|
* Sets the cost/sell accounts to the invoice entries.
|
||||||
*/
|
*/
|
||||||
public async setItemsEntriesDefaultAccounts(entries: ItemEntry[]) {
|
public setItemsEntriesDefaultAccounts = async (entries: ItemEntry[]) => {
|
||||||
const entriesItemsIds = entries.map((e) => e.itemId);
|
const entriesItemsIds = entries.map((e) => e.itemId);
|
||||||
const items = await this.itemModel.query().whereIn('id', entriesItemsIds);
|
const items = await this.itemModel.query().whereIn('id', entriesItemsIds);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ export class ItemEntry extends BaseModel {
|
|||||||
public costAccountId: number;
|
public costAccountId: number;
|
||||||
public taxRateId: number;
|
public taxRateId: number;
|
||||||
|
|
||||||
|
public landedCost!: boolean;
|
||||||
|
public allocatedCostAmount!: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { omit, sumBy } from 'lodash';
|
import { omit, sumBy } from 'lodash';
|
||||||
import composeAsync from 'async/compose';
|
import * as composeAsync from 'async/compose';
|
||||||
import {
|
import {
|
||||||
IPaymentReceivedCreateDTO,
|
IPaymentReceivedCreateDTO,
|
||||||
IPaymentReceivedEditDTO,
|
IPaymentReceivedEditDTO,
|
||||||
@@ -78,6 +78,6 @@ export class PaymentReceiveDTOTransformer {
|
|||||||
|
|
||||||
return R.compose(
|
return R.compose(
|
||||||
this.branchDTOTransform.transformDTO<PaymentReceived>
|
this.branchDTOTransform.transformDTO<PaymentReceived>
|
||||||
)(initialAsyncDTO);
|
)(initialAsyncDTO) as PaymentReceived;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Model, mixin } from 'objection';
|
|||||||
// import { DEFAULT_VIEWS } from '@/services/Sales/PaymentReceived/constants';
|
// import { DEFAULT_VIEWS } from '@/services/Sales/PaymentReceived/constants';
|
||||||
// import ModelSearchable from './ModelSearchable';
|
// import ModelSearchable from './ModelSearchable';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
import { PaymentReceivedEntry } from './PaymentReceivedEntry';
|
||||||
|
|
||||||
export class PaymentReceived extends BaseModel {
|
export class PaymentReceived extends BaseModel {
|
||||||
customerId: number;
|
customerId: number;
|
||||||
@@ -25,6 +26,8 @@ export class PaymentReceived extends BaseModel {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
|
||||||
|
entries?: PaymentReceivedEntry[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
*/
|
*/
|
||||||
@@ -65,17 +68,17 @@ export class PaymentReceived extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const PaymentReceiveEntry = require('models/PaymentReceiveEntry');
|
const { PaymentReceivedEntry } = require('./PaymentReceivedEntry');
|
||||||
const AccountTransaction = require('models/AccountTransaction');
|
const { AccountTransaction } = require('../../Accounts/models/AccountTransaction.model');
|
||||||
const Customer = require('models/Customer');
|
const { Customer } = require('../../Customers/models/Customer');
|
||||||
const Account = require('models/Account');
|
const { Account } = require('../../Accounts/models/Account.model');
|
||||||
const Branch = require('models/Branch');
|
const { Branch } = require('../../Branches/models/Branch.model');
|
||||||
const Document = require('models/Document');
|
// const Document = require('../../Documents/models/Document');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
customer: {
|
customer: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Customer.default,
|
modelClass: Customer,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives.customerId',
|
from: 'payment_receives.customerId',
|
||||||
to: 'contacts.id',
|
to: 'contacts.id',
|
||||||
@@ -84,17 +87,19 @@ export class PaymentReceived extends BaseModel {
|
|||||||
query.where('contact_service', 'customer');
|
query.where('contact_service', 'customer');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
depositAccount: {
|
depositAccount: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Account.default,
|
modelClass: Account,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives.depositAccountId',
|
from: 'payment_receives.depositAccountId',
|
||||||
to: 'accounts.id',
|
to: 'accounts.id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
entries: {
|
entries: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: PaymentReceiveEntry.default,
|
modelClass: PaymentReceivedEntry,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives.id',
|
from: 'payment_receives.id',
|
||||||
to: 'payment_receives_entries.paymentReceiveId',
|
to: 'payment_receives_entries.paymentReceiveId',
|
||||||
@@ -103,9 +108,10 @@ export class PaymentReceived extends BaseModel {
|
|||||||
query.orderBy('index', 'ASC');
|
query.orderBy('index', 'ASC');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
transactions: {
|
transactions: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: AccountTransaction.default,
|
modelClass: AccountTransaction,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives.id',
|
from: 'payment_receives.id',
|
||||||
to: 'accounts_transactions.referenceId',
|
to: 'accounts_transactions.referenceId',
|
||||||
@@ -120,7 +126,7 @@ export class PaymentReceived extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
branch: {
|
branch: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Branch.default,
|
modelClass: Branch,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives.branchId',
|
from: 'payment_receives.branchId',
|
||||||
to: 'branches.id',
|
to: 'branches.id',
|
||||||
@@ -130,21 +136,21 @@ export class PaymentReceived extends BaseModel {
|
|||||||
/**
|
/**
|
||||||
* Payment transaction may has many attached attachments.
|
* Payment transaction may has many attached attachments.
|
||||||
*/
|
*/
|
||||||
attachments: {
|
// attachments: {
|
||||||
relation: Model.ManyToManyRelation,
|
// relation: Model.ManyToManyRelation,
|
||||||
modelClass: Document.default,
|
// modelClass: Document.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'payment_receives.id',
|
// from: 'payment_receives.id',
|
||||||
through: {
|
// through: {
|
||||||
from: 'document_links.modelId',
|
// from: 'document_links.modelId',
|
||||||
to: 'document_links.documentId',
|
// to: 'document_links.documentId',
|
||||||
},
|
// },
|
||||||
to: 'documents.id',
|
// to: 'documents.id',
|
||||||
},
|
// },
|
||||||
filter(query) {
|
// filter(query) {
|
||||||
query.where('model_ref', 'PaymentReceive');
|
// query.where('model_ref', 'PaymentReceive');
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
import { Model, mixin } from 'objection';
|
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||||
|
import { Model } from 'objection';
|
||||||
|
|
||||||
export class PaymentReceivedEntry extends BaseModel {
|
export class PaymentReceivedEntry extends BaseModel {
|
||||||
paymentReceiveId: number;
|
paymentReceiveId: number;
|
||||||
invoiceId: number;
|
invoiceId: number;
|
||||||
paymentAmount: number;
|
paymentAmount: number;
|
||||||
|
index: number;
|
||||||
|
|
||||||
|
invoice?: SaleInvoice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
@@ -24,15 +28,15 @@ export class PaymentReceivedEntry extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const PaymentReceive = require('models/PaymentReceive');
|
const { PaymentReceived } = require('./PaymentReceived');
|
||||||
const SaleInvoice = require('models/SaleInvoice');
|
const { SaleInvoice } = require('../../SaleInvoices/models/SaleInvoice');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
payment: {
|
payment: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: PaymentReceive.default,
|
modelClass: PaymentReceived,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives_entries.paymentReceiveId',
|
from: 'payment_receives_entries.paymentReceiveId',
|
||||||
to: 'payment_receives.id',
|
to: 'payment_receives.id',
|
||||||
@@ -44,7 +48,7 @@ export class PaymentReceivedEntry extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
invoice: {
|
invoice: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: SaleInvoice.default,
|
modelClass: SaleInvoice,
|
||||||
join: {
|
join: {
|
||||||
from: 'payment_receives_entries.invoiceId',
|
from: 'payment_receives_entries.invoiceId',
|
||||||
to: 'sales_invoices.id',
|
to: 'sales_invoices.id',
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { IPaymentReceivePageEntry } from '../types/PaymentReceived.types';
|
import { IPaymentReceivePageEntry } from '../types/PaymentReceived.types';
|
||||||
import { ERRORS } from '../constants';
|
import { ERRORS } from '../constants';
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||||
import { PaymentReceived } from '../models/PaymentReceived';
|
import { PaymentReceived } from '../models/PaymentReceived';
|
||||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import { PaymentReceived } from './models/PaymentReceived';
|
import { PaymentReceived } from './models/PaymentReceived';
|
||||||
import {
|
import {
|
||||||
PaymentReceivedPdfTemplateAttributes,
|
PaymentReceivedPdfTemplateAttributes,
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class PaymentServicesModule {}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { BaseModel } from "@/models/Model";
|
||||||
|
|
||||||
|
export class PaymentIntegration extends BaseModel {
|
||||||
|
paymentEnabled!: boolean;
|
||||||
|
payoutEnabled!: boolean;
|
||||||
|
|
||||||
|
static get tableName() {
|
||||||
|
return 'payment_integrations';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get idColumn() {
|
||||||
|
return 'id';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get virtualAttributes() {
|
||||||
|
return ['fullEnabled'];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get jsonAttributes() {
|
||||||
|
return ['options'];
|
||||||
|
}
|
||||||
|
|
||||||
|
get fullEnabled() {
|
||||||
|
return this.paymentEnabled && this.payoutEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get modifiers() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Query to filter enabled payment and payout.
|
||||||
|
*/
|
||||||
|
fullEnabled(query) {
|
||||||
|
query.where('paymentEnabled', true).andWhere('payoutEnabled', true);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static get jsonSchema() {
|
||||||
|
return {
|
||||||
|
type: 'object',
|
||||||
|
required: ['name', 'service'],
|
||||||
|
properties: {
|
||||||
|
id: { type: 'integer' },
|
||||||
|
service: { type: 'string' },
|
||||||
|
paymentEnabled: { type: 'boolean' },
|
||||||
|
payoutEnabled: { type: 'boolean' },
|
||||||
|
accountId: { type: 'string' },
|
||||||
|
options: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
bankAccountId: { type: 'number' },
|
||||||
|
clearingAccountId: { type: 'number' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createdAt: { type: 'string', format: 'date-time' },
|
||||||
|
updatedAt: { type: 'string', format: 'date-time' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { Model } from 'objection';
|
||||||
|
import { BaseModel } from '@/models/Model';
|
||||||
|
|
||||||
|
export class TransactionPaymentServiceEntry extends BaseModel {
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
static get tableName() {
|
||||||
|
return 'transactions_payment_methods';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json schema of the model.
|
||||||
|
*/
|
||||||
|
static get jsonSchema() {
|
||||||
|
return {
|
||||||
|
type: 'object',
|
||||||
|
required: ['paymentIntegrationId'],
|
||||||
|
properties: {
|
||||||
|
id: { type: 'integer' },
|
||||||
|
referenceId: { type: 'integer' },
|
||||||
|
referenceType: { type: 'string' },
|
||||||
|
paymentIntegrationId: { type: 'integer' },
|
||||||
|
enable: { type: 'boolean' },
|
||||||
|
options: { type: 'object' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relationship mapping.
|
||||||
|
*/
|
||||||
|
static get relationMappings() {
|
||||||
|
const { PaymentIntegration } = require('./PaymentIntegration.model');
|
||||||
|
|
||||||
|
return {
|
||||||
|
paymentIntegration: {
|
||||||
|
relation: Model.BelongsToOneRelation,
|
||||||
|
modelClass: PaymentIntegration,
|
||||||
|
join: {
|
||||||
|
from: 'transactions_payment_methods.paymentIntegrationId',
|
||||||
|
to: 'payment_integrations.id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,15 @@ import { EditPdfTemplateService } from './commands/EditPdfTemplate.service';
|
|||||||
import { PdfTemplateApplication } from './PdfTemplate.application';
|
import { PdfTemplateApplication } from './PdfTemplate.application';
|
||||||
import { PdfTemplatesController } from './PdfTemplates.controller';
|
import { PdfTemplatesController } from './PdfTemplates.controller';
|
||||||
import { GetPdfTemplateService } from './queries/GetPdfTemplate.service';
|
import { GetPdfTemplateService } from './queries/GetPdfTemplate.service';
|
||||||
|
import { BrandingTemplateDTOTransformer } from './BrandingTemplateDTOTransformer';
|
||||||
|
import { GetOrganizationBrandingAttributesService } from './queries/GetOrganizationBrandingAttributes.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
exports: [
|
||||||
|
GetPdfTemplateService,
|
||||||
|
BrandingTemplateDTOTransformer,
|
||||||
|
GetOrganizationBrandingAttributesService,
|
||||||
|
],
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule],
|
||||||
controllers: [PdfTemplatesController],
|
controllers: [PdfTemplatesController],
|
||||||
providers: [
|
providers: [
|
||||||
@@ -22,6 +29,8 @@ import { GetPdfTemplateService } from './queries/GetPdfTemplate.service';
|
|||||||
AssignPdfTemplateDefaultService,
|
AssignPdfTemplateDefaultService,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
|
BrandingTemplateDTOTransformer,
|
||||||
|
GetOrganizationBrandingAttributesService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PdfTemplatesModule {}
|
export class PdfTemplatesModule {}
|
||||||
|
|||||||
@@ -208,23 +208,23 @@ export class SaleEstimate extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const { ItemEntry } = require('../../Items/models/ItemEntry');
|
const { ItemEntry } = require('../../Items/models/ItemEntry');
|
||||||
// const Customer = require('models/Customer');
|
const { Customer } = require('../../Customers/models/Customer');
|
||||||
// const Branch = require('models/Branch');
|
const { Branch } = require('../../Branches/models/Branch.model');
|
||||||
// const Warehouse = require('models/Warehouse');
|
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||||
// const Document = require('models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// customer: {
|
customer: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Customer.default,
|
modelClass: Customer,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_estimates.customerId',
|
from: 'sales_estimates.customerId',
|
||||||
// to: 'contacts.id',
|
to: 'contacts.id',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('contact_service', 'customer');
|
query.where('contact_service', 'customer');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
entries: {
|
entries: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: ItemEntry,
|
modelClass: ItemEntry,
|
||||||
@@ -239,48 +239,48 @@ export class SaleEstimate extends BaseModel {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale estimate may belongs to branch.
|
* Sale estimate may belongs to branch.
|
||||||
// */
|
*/
|
||||||
// branch: {
|
branch: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Branch.default,
|
modelClass: Branch,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_estimates.branchId',
|
from: 'sales_estimates.branchId',
|
||||||
// to: 'branches.id',
|
to: 'branches.id',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale estimate may has associated warehouse.
|
* Sale estimate may has associated warehouse.
|
||||||
// */
|
*/
|
||||||
// warehouse: {
|
warehouse: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Warehouse.default,
|
modelClass: Warehouse,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_estimates.warehouseId',
|
from: 'sales_estimates.warehouseId',
|
||||||
// to: 'warehouses.id',
|
to: 'warehouses.id',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale estimate transaction may has many attached attachments.
|
* Sale estimate transaction may has many attached attachments.
|
||||||
// */
|
*/
|
||||||
// attachments: {
|
attachments: {
|
||||||
// relation: Model.ManyToManyRelation,
|
relation: Model.ManyToManyRelation,
|
||||||
// modelClass: Document.default,
|
modelClass: Document,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_estimates.id',
|
from: 'sales_estimates.id',
|
||||||
// through: {
|
through: {
|
||||||
// from: 'document_links.modelId',
|
from: 'document_links.modelId',
|
||||||
// to: 'document_links.documentId',
|
to: 'document_links.documentId',
|
||||||
// },
|
},
|
||||||
// to: 'documents.id',
|
to: 'documents.id',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('model_ref', 'SaleEstimate');
|
query.where('model_ref', 'SaleEstimate');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types';
|
import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types';
|
||||||
import { AttachmentLinkDTO } from '../Attachments/Attachments.types';
|
import { AttachmentLinkDTO } from '../Attachments/Attachments.types';
|
||||||
import SaleInvoice from './models/SaleInvoice';
|
import { SaleInvoice } from './models/SaleInvoice';
|
||||||
import { SystemUser } from '../System/models/SystemUser';
|
// import SaleInvoice from './models/SaleInvoice';
|
||||||
|
// import { SystemUser } from '../System/models/SystemUser';
|
||||||
// import { ISystemUser, IAccount, ITaxTransaction } from '@/interfaces';
|
// import { ISystemUser, IAccount, ITaxTransaction } from '@/interfaces';
|
||||||
// import { CommonMailOptions, CommonMailOptionsDTO } from './Mailable';
|
// import { CommonMailOptions, CommonMailOptionsDTO } from './Mailable';
|
||||||
// import { IDynamicListFilter } from '@/interfaces/DynamicFilter';
|
// import { IDynamicListFilter } from '@/interfaces/DynamicFilter';
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ import {
|
|||||||
InvoiceNotificationType,
|
InvoiceNotificationType,
|
||||||
} from './SaleInvoice.types';
|
} from './SaleInvoice.types';
|
||||||
import { SaleInvoiceApplication } from './SaleInvoices.application';
|
import { SaleInvoiceApplication } from './SaleInvoices.application';
|
||||||
|
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||||
|
|
||||||
@Controller('sale-invoices')
|
@Controller('sale-invoices')
|
||||||
|
@PublicRoute()
|
||||||
export class SaleInvoicesController {
|
export class SaleInvoicesController {
|
||||||
constructor(private saleInvoiceApplication: SaleInvoiceApplication) {}
|
constructor(private saleInvoiceApplication: SaleInvoiceApplication) {}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,33 @@ import { GetSaleInvoicesPayable } from './queries/GetSaleInvoicesPayable.service
|
|||||||
import { GetSaleInvoiceState } from './queries/GetSaleInvoiceState.service';
|
import { GetSaleInvoiceState } from './queries/GetSaleInvoiceState.service';
|
||||||
import { SaleInvoicePdf } from './queries/SaleInvoicePdf.service';
|
import { SaleInvoicePdf } from './queries/SaleInvoicePdf.service';
|
||||||
import { SaleInvoiceApplication } from './SaleInvoices.application';
|
import { SaleInvoiceApplication } from './SaleInvoices.application';
|
||||||
|
import { ItemsEntriesService } from '../Items/ItemsEntries.service';
|
||||||
|
import { CommandSaleInvoiceValidators } from './commands/CommandSaleInvoiceValidators.service';
|
||||||
|
import { CommandSaleInvoiceDTOTransformer } from './commands/CommandSaleInvoiceDTOTransformer.service';
|
||||||
|
import { SaleEstimateValidators } from '../SaleEstimates/commands/SaleEstimateValidators.service';
|
||||||
|
import { UnlinkConvertedSaleEstimate } from '../SaleEstimates/commands/UnlinkConvertedSaleEstimate.service';
|
||||||
|
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
||||||
|
import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementOrders.module';
|
||||||
|
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
|
||||||
|
import { SaleInvoicePdfTemplate } from './queries/SaleInvoicePdfTemplate.service';
|
||||||
|
import { WriteoffSaleInvoice } from './commands/WriteoffSaleInvoice.service';
|
||||||
|
import { GetInvoicePaymentsService } from './queries/GetInvoicePayments.service';
|
||||||
|
import { BranchesModule } from '../Branches/Branches.module';
|
||||||
|
import { WarehousesModule } from '../Warehouses/Warehouses.module';
|
||||||
|
import { TaxRatesModule } from '../TaxRates/TaxRate.module';
|
||||||
|
import { SaleInvoicesController } from './SaleInvoices.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [
|
||||||
controllers: [],
|
TenancyDatabaseModule,
|
||||||
|
PdfTemplatesModule,
|
||||||
|
AutoIncrementOrdersModule,
|
||||||
|
ChromiumlyTenancyModule,
|
||||||
|
BranchesModule,
|
||||||
|
WarehousesModule,
|
||||||
|
TaxRatesModule,
|
||||||
|
],
|
||||||
|
controllers: [SaleInvoicesController],
|
||||||
providers: [
|
providers: [
|
||||||
CreateSaleInvoice,
|
CreateSaleInvoice,
|
||||||
EditSaleInvoice,
|
EditSaleInvoice,
|
||||||
@@ -37,6 +60,14 @@ import { SaleInvoiceApplication } from './SaleInvoices.application';
|
|||||||
SaleInvoiceApplication,
|
SaleInvoiceApplication,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
|
ItemsEntriesService,
|
||||||
|
CommandSaleInvoiceValidators,
|
||||||
|
CommandSaleInvoiceDTOTransformer,
|
||||||
|
SaleEstimateValidators,
|
||||||
|
UnlinkConvertedSaleEstimate,
|
||||||
|
SaleInvoicePdfTemplate,
|
||||||
|
WriteoffSaleInvoice,
|
||||||
|
GetInvoicePaymentsService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SaleInvoicesModule {}
|
export class SaleInvoicesModule {}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { omit, sumBy } from 'lodash';
|
import { omit, sumBy } from 'lodash';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import composeAsync from 'async/compose';
|
import * as composeAsync from 'async/compose';
|
||||||
import {
|
import {
|
||||||
ISaleInvoiceCreateDTO,
|
ISaleInvoiceCreateDTO,
|
||||||
ISaleInvoiceEditDTO,
|
ISaleInvoiceEditDTO,
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { SaleInvoice } from '../models/SaleInvoice';
|
import { SaleInvoice } from '../models/SaleInvoice';
|
||||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
import { ERRORS } from '../constants';
|
import { ERRORS } from '../constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommandSaleInvoiceValidators {
|
export class CommandSaleInvoiceValidators {
|
||||||
constructor(private readonly saleInvoiceModel: typeof SaleInvoice) {}
|
constructor(
|
||||||
|
@Inject(SaleInvoice.name)
|
||||||
|
private readonly saleInvoiceModel: typeof SaleInvoice,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the given invoice is existance.
|
* Validates the given invoice is existance.
|
||||||
|
|||||||
@@ -14,22 +14,23 @@ import { ServiceError } from '@/modules/Items/ServiceError';
|
|||||||
import { ERRORS } from '../constants';
|
import { ERRORS } from '../constants';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
import { PaymentReceivedEntry } from '@/modules/PaymentReceived/models/PaymentReceivedEntry';
|
import { PaymentReceivedEntry } from '@/modules/PaymentReceived/models/PaymentReceivedEntry';
|
||||||
import CreditNoteAppliedInvoice from '@/modules/CreditNotes/models/CreditNoteAppliedInvoice';
|
import { CreditNoteAppliedInvoice } from '@/modules/CreditNotes/models/CreditNoteAppliedInvoice';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeleteSaleInvoice {
|
export class DeleteSaleInvoice {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(PaymentReceivedEntry)
|
|
||||||
private paymentReceivedEntryModel: typeof PaymentReceivedEntry,
|
|
||||||
|
|
||||||
@Inject(CreditNoteAppliedInvoice)
|
|
||||||
private creditNoteAppliedInvoiceModel: typeof CreditNoteAppliedInvoice,
|
|
||||||
|
|
||||||
@Inject(SaleInvoice)
|
|
||||||
private saleInvoiceModel: typeof SaleInvoice,
|
|
||||||
private unlockEstimateFromInvoice: UnlinkConvertedSaleEstimate,
|
private unlockEstimateFromInvoice: UnlinkConvertedSaleEstimate,
|
||||||
private eventPublisher: EventEmitter2,
|
private eventPublisher: EventEmitter2,
|
||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
|
|
||||||
|
@Inject(PaymentReceivedEntry.name)
|
||||||
|
private paymentReceivedEntryModel: typeof PaymentReceivedEntry,
|
||||||
|
|
||||||
|
@Inject(CreditNoteAppliedInvoice.name)
|
||||||
|
private creditNoteAppliedInvoiceModel: typeof CreditNoteAppliedInvoice,
|
||||||
|
|
||||||
|
@Inject(SaleInvoice.name)
|
||||||
|
private saleInvoiceModel: typeof SaleInvoice,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ export class GenerateShareLink {
|
|||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
private eventPublisher: EventEmitter2,
|
private eventPublisher: EventEmitter2,
|
||||||
private transformer: TransformerInjectable,
|
private transformer: TransformerInjectable,
|
||||||
@Inject(SaleInvoice) private saleInvoiceModel: typeof SaleInvoice,
|
@Inject(SaleInvoice.name) private saleInvoiceModel: typeof SaleInvoice,
|
||||||
@Inject(PaymentLink) private paymentLinkModel: typeof PaymentLink,
|
@Inject(PaymentLink.name) private paymentLinkModel: typeof PaymentLink,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { mixin, Model, raw } from 'objection';
|
import { mixin, Model, raw } from 'objection';
|
||||||
import { castArray, takeWhile } from 'lodash';
|
import { castArray, takeWhile } from 'lodash';
|
||||||
import moment from 'moment';
|
import moment, { MomentInput, unitOfTime } from 'moment';
|
||||||
// import TenantModel from 'models/TenantModel';
|
// import TenantModel from 'models/TenantModel';
|
||||||
// import ModelSetting from './ModelSetting';
|
// import ModelSetting from './ModelSetting';
|
||||||
// import SaleInvoiceMeta from './SaleInvoice.Settings';
|
// import SaleInvoiceMeta from './SaleInvoice.Settings';
|
||||||
@@ -19,7 +19,7 @@ export class SaleInvoice extends BaseModel{
|
|||||||
public isInclusiveTax: boolean;
|
public isInclusiveTax: boolean;
|
||||||
|
|
||||||
public dueDate: Date;
|
public dueDate: Date;
|
||||||
public deliveredAt: Date;
|
public deliveredAt: Date | string;
|
||||||
public currencyCode: string;
|
public currencyCode: string;
|
||||||
public invoiceDate: Date;
|
public invoiceDate: Date;
|
||||||
|
|
||||||
@@ -262,13 +262,18 @@ export class SaleInvoice extends BaseModel{
|
|||||||
COALESCE(PAYMENT_AMOUNT, 0) -
|
COALESCE(PAYMENT_AMOUNT, 0) -
|
||||||
COALESCE(WRITTENOFF_AMOUNT, 0) -
|
COALESCE(WRITTENOFF_AMOUNT, 0) -
|
||||||
COALESCE(CREDITED_AMOUNT, 0) > 0
|
COALESCE(CREDITED_AMOUNT, 0) > 0
|
||||||
`)
|
`),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Filters the invoices between the given date range.
|
* Filters the invoices between the given date range.
|
||||||
*/
|
*/
|
||||||
filterDateRange(query, startDate, endDate, type = 'day') {
|
filterDateRange(
|
||||||
|
query,
|
||||||
|
startDate: MomentInput,
|
||||||
|
endDate?: MomentInput,
|
||||||
|
type: unitOfTime.StartOf = 'day',
|
||||||
|
) {
|
||||||
const dateFormat = 'YYYY-MM-DD';
|
const dateFormat = 'YYYY-MM-DD';
|
||||||
const fromDate = moment(startDate).startOf(type).format(dateFormat);
|
const fromDate = moment(startDate).startOf(type).format(dateFormat);
|
||||||
const toDate = moment(endDate).endOf(type).format(dateFormat);
|
const toDate = moment(endDate).endOf(type).format(dateFormat);
|
||||||
@@ -418,73 +423,81 @@ export class SaleInvoice extends BaseModel{
|
|||||||
/**
|
/**
|
||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
// static get relationMappings() {
|
static get relationMappings() {
|
||||||
// const AccountTransaction = require('models/AccountTransaction');
|
const {
|
||||||
// const ItemEntry = require('models/ItemEntry');
|
AccountTransaction,
|
||||||
// const Customer = require('models/Customer');
|
} = require('../../Accounts/models/AccountTransaction.model');
|
||||||
|
const {
|
||||||
|
ItemEntry,
|
||||||
|
} = require('../../TransactionItemEntry/models/ItemEntry');
|
||||||
|
const { Customer } = require('../../Customers/models/Customer');
|
||||||
// const InventoryCostLotTracker = require('models/InventoryCostLotTracker');
|
// const InventoryCostLotTracker = require('models/InventoryCostLotTracker');
|
||||||
// const PaymentReceiveEntry = require('models/PaymentReceiveEntry');
|
const {
|
||||||
// const Branch = require('models/Branch');
|
PaymentReceivedEntry,
|
||||||
// const Warehouse = require('models/Warehouse');
|
} = require('../../PaymentReceived/models/PaymentReceivedEntry');
|
||||||
// const Account = require('models/Account');
|
const { Branch } = require('../../Branches/models/Branch.model');
|
||||||
// const TaxRateTransaction = require('models/TaxRateTransaction');
|
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||||
// const Document = require('models/Document');
|
const { Account } = require('../../Accounts/models/Account.model');
|
||||||
|
// const TaxRateTransaction = require('../../Tax');
|
||||||
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
||||||
// const {
|
const {
|
||||||
// TransactionPaymentServiceEntry,
|
TransactionPaymentServiceEntry,
|
||||||
// } = require('models/TransactionPaymentServiceEntry');
|
} = require('../../PaymentServices/models/TransactionPaymentServiceEntry.model');
|
||||||
// const { PdfTemplate } = require('models/PdfTemplate');
|
const {
|
||||||
|
PdfTemplateModel,
|
||||||
|
} = require('../../PdfTemplate/models/PdfTemplate');
|
||||||
|
|
||||||
// return {
|
return {
|
||||||
// /**
|
/**
|
||||||
// * Sale invoice associated entries.
|
* Sale invoice associated entries.
|
||||||
// */
|
*/
|
||||||
// entries: {
|
entries: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: ItemEntry.default,
|
modelClass: ItemEntry,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.id',
|
from: 'sales_invoices.id',
|
||||||
// to: 'items_entries.referenceId',
|
to: 'items_entries.referenceId',
|
||||||
// },
|
},
|
||||||
// filter(builder) {
|
filter(builder) {
|
||||||
// builder.where('reference_type', 'SaleInvoice');
|
builder.where('reference_type', 'SaleInvoice');
|
||||||
// builder.orderBy('index', 'ASC');
|
builder.orderBy('index', 'ASC');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Belongs to customer model.
|
* Belongs to customer model.
|
||||||
// */
|
*/
|
||||||
// customer: {
|
customer: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Customer.default,
|
modelClass: Customer,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.customerId',
|
from: 'sales_invoices.customerId',
|
||||||
// to: 'contacts.id',
|
to: 'contacts.id',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('contact_service', 'Customer');
|
query.where('contact_service', 'Customer');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice has associated account transactions.
|
* Invoice has associated account transactions.
|
||||||
// */
|
*/
|
||||||
// transactions: {
|
transactions: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: AccountTransaction.default,
|
modelClass: AccountTransaction,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.id',
|
from: 'sales_invoices.id',
|
||||||
// to: 'accounts_transactions.referenceId',
|
to: 'accounts_transactions.referenceId',
|
||||||
// },
|
},
|
||||||
// filter(builder) {
|
filter(builder) {
|
||||||
// builder.where('reference_type', 'SaleInvoice');
|
builder.where('reference_type', 'SaleInvoice');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice may has associated cost transactions.
|
* Invoice may has associated cost transactions.
|
||||||
// */
|
*/
|
||||||
// costTransactions: {
|
// costTransactions: {
|
||||||
// relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
// modelClass: InventoryCostLotTracker.default,
|
// modelClass: InventoryCostLotTracker.default,
|
||||||
@@ -497,57 +510,57 @@ export class SaleInvoice extends BaseModel{
|
|||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice may has associated payment entries.
|
* Invoice may has associated payment entries.
|
||||||
// */
|
*/
|
||||||
// paymentEntries: {
|
paymentEntries: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: PaymentReceiveEntry.default,
|
modelClass: PaymentReceivedEntry,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.id',
|
from: 'sales_invoices.id',
|
||||||
// to: 'payment_receives_entries.invoiceId',
|
to: 'payment_receives_entries.invoiceId',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice may has associated branch.
|
* Invoice may has associated branch.
|
||||||
// */
|
*/
|
||||||
// branch: {
|
branch: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Branch.default,
|
modelClass: Branch,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.branchId',
|
from: 'sales_invoices.branchId',
|
||||||
// to: 'branches.id',
|
to: 'branches.id',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice may has associated warehouse.
|
* Invoice may has associated warehouse.
|
||||||
// */
|
*/
|
||||||
// warehouse: {
|
warehouse: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Warehouse.default,
|
modelClass: Warehouse,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.warehouseId',
|
from: 'sales_invoices.warehouseId',
|
||||||
// to: 'warehouses.id',
|
to: 'warehouses.id',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice may has associated written-off expense account.
|
* Invoice may has associated written-off expense account.
|
||||||
// */
|
*/
|
||||||
// writtenoffExpenseAccount: {
|
writtenoffExpenseAccount: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: Account.default,
|
modelClass: Account,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.writtenoffExpenseAccountId',
|
from: 'sales_invoices.writtenoffExpenseAccountId',
|
||||||
// to: 'accounts.id',
|
to: 'accounts.id',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Invoice may has associated tax rate transactions.
|
* Invoice may has associated tax rate transactions.
|
||||||
// */
|
*/
|
||||||
// taxes: {
|
// taxes: {
|
||||||
// relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
// modelClass: TaxRateTransaction.default,
|
// modelClass: TaxRateTransaction.default,
|
||||||
@@ -560,28 +573,28 @@ export class SaleInvoice extends BaseModel{
|
|||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale invoice transaction may has many attached attachments.
|
* Sale invoice transaction may has many attached attachments.
|
||||||
// */
|
*/
|
||||||
// attachments: {
|
attachments: {
|
||||||
// relation: Model.ManyToManyRelation,
|
relation: Model.ManyToManyRelation,
|
||||||
// modelClass: Document.default,
|
modelClass: Document,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.id',
|
from: 'sales_invoices.id',
|
||||||
// through: {
|
through: {
|
||||||
// from: 'document_links.modelId',
|
from: 'document_links.modelId',
|
||||||
// to: 'document_links.documentId',
|
to: 'document_links.documentId',
|
||||||
// },
|
},
|
||||||
// to: 'documents.id',
|
to: 'documents.id',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('model_ref', 'SaleInvoice');
|
query.where('model_ref', 'SaleInvoice');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale invocie may belongs to matched bank transaction.
|
* Sale invocie may belongs to matched bank transaction.
|
||||||
// */
|
*/
|
||||||
// matchedBankTransaction: {
|
// matchedBankTransaction: {
|
||||||
// relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
// modelClass: MatchedBankTransaction,
|
// modelClass: MatchedBankTransaction,
|
||||||
@@ -594,37 +607,37 @@ export class SaleInvoice extends BaseModel{
|
|||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale invoice may belongs to payment methods entries.
|
* Sale invoice may belongs to payment methods entries.
|
||||||
// */
|
*/
|
||||||
// paymentMethods: {
|
paymentMethods: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: TransactionPaymentServiceEntry,
|
modelClass: TransactionPaymentServiceEntry,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.id',
|
from: 'sales_invoices.id',
|
||||||
// to: 'transactions_payment_methods.referenceId',
|
to: 'transactions_payment_methods.referenceId',
|
||||||
// },
|
},
|
||||||
// beforeInsert: (model) => {
|
beforeInsert: (model) => {
|
||||||
// model.referenceType = 'SaleInvoice';
|
model.referenceType = 'SaleInvoice';
|
||||||
// },
|
},
|
||||||
// filter: (query) => {
|
filter: (query) => {
|
||||||
// query.where('reference_type', 'SaleInvoice');
|
query.where('reference_type', 'SaleInvoice');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Sale invoice may belongs to pdf branding template.
|
* Sale invoice may belongs to pdf branding template.
|
||||||
// */
|
*/
|
||||||
// pdfTemplate: {
|
pdfTemplate: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: PdfTemplate,
|
modelClass: PdfTemplateModel,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.pdfTemplateId',
|
from: 'sales_invoices.pdfTemplateId',
|
||||||
// to: 'pdf_templates.id',
|
to: 'pdf_templates.id',
|
||||||
// }
|
},
|
||||||
// },
|
},
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change payment amount.
|
* Change payment amount.
|
||||||
@@ -642,9 +655,9 @@ export class SaleInvoice extends BaseModel{
|
|||||||
/**
|
/**
|
||||||
* Sale invoice meta.
|
* Sale invoice meta.
|
||||||
*/
|
*/
|
||||||
static get meta() {
|
// static get meta() {
|
||||||
return SaleInvoiceMeta;
|
// return SaleInvoiceMeta;
|
||||||
}
|
// }
|
||||||
|
|
||||||
static dueAmountFieldSortQuery(query, role) {
|
static dueAmountFieldSortQuery(query, role) {
|
||||||
query.modify('sortByDueAmount', role.order);
|
query.modify('sortByDueAmount', role.order);
|
||||||
@@ -653,9 +666,9 @@ export class SaleInvoice extends BaseModel{
|
|||||||
/**
|
/**
|
||||||
* Retrieve the default custom views, roles and columns.
|
* Retrieve the default custom views, roles and columns.
|
||||||
*/
|
*/
|
||||||
static get defaultViews() {
|
// static get defaultViews() {
|
||||||
return DEFAULT_VIEWS;
|
// return DEFAULT_VIEWS;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model searchable.
|
* Model searchable.
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export class SaleInvoicePdf {
|
|||||||
public async getSaleInvoicePdf(invoiceId: number): Promise<[Buffer, string]> {
|
public async getSaleInvoicePdf(invoiceId: number): Promise<[Buffer, string]> {
|
||||||
const filename = await this.getInvoicePdfFilename(invoiceId);
|
const filename = await this.getInvoicePdfFilename(invoiceId);
|
||||||
|
|
||||||
const htmlContent = await this.saleInvoiceHtml(invoiceId);
|
const htmlContent = await this.getSaleInvoiceHtml(invoiceId);
|
||||||
|
|
||||||
// Converts the given html content to pdf document.
|
// Converts the given html content to pdf document.
|
||||||
const buffer = await this.chromiumlyTenancy.convertHtmlContent(htmlContent);
|
const buffer = await this.chromiumlyTenancy.convertHtmlContent(htmlContent);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import { pickBy } from 'lodash';
|
import { pickBy } from 'lodash';
|
||||||
import { InvoicePdfTemplateAttributes, ISaleInvoice } from '@/interfaces';
|
import { InvoicePdfTemplateAttributes, ISaleInvoice } from '@/interfaces';
|
||||||
import { contactAddressTextFormat } from '@/utils/address-text-format';
|
import { contactAddressTextFormat } from '@/utils/address-text-format';
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
Param,
|
||||||
|
ParseIntPipe,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ISaleReceiptDTO } from './types/SaleReceipts.types';
|
||||||
|
import { SaleReceiptApplication } from './SaleReceiptApplication.service';
|
||||||
|
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||||
|
|
||||||
|
@Controller('sale-receipts')
|
||||||
|
@PublicRoute()
|
||||||
|
export class SaleReceiptsController {
|
||||||
|
constructor(private saleReceiptApplication: SaleReceiptApplication) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
createSaleReceipt(@Body() saleReceiptDTO: ISaleReceiptDTO) {
|
||||||
|
return this.saleReceiptApplication.createSaleReceipt(saleReceiptDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id')
|
||||||
|
editSaleReceipt(
|
||||||
|
@Param('id', ParseIntPipe) id: number,
|
||||||
|
@Body() saleReceiptDTO: ISaleReceiptDTO,
|
||||||
|
) {
|
||||||
|
return this.saleReceiptApplication.editSaleReceipt(id, saleReceiptDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
getSaleReceipt(@Param('id', ParseIntPipe) id: number) {
|
||||||
|
return this.saleReceiptApplication.getSaleReceipt(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
deleteSaleReceipt(@Param('id', ParseIntPipe) id: number) {
|
||||||
|
return this.saleReceiptApplication.deleteSaleReceipt(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/close')
|
||||||
|
closeSaleReceipt(@Param('id', ParseIntPipe) id: number) {
|
||||||
|
return this.saleReceiptApplication.closeSaleReceipt(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id/pdf')
|
||||||
|
getSaleReceiptPdf(@Param('id', ParseIntPipe) id: number) {
|
||||||
|
return this.saleReceiptApplication.getSaleReceiptPdf(0, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('state')
|
||||||
|
getSaleReceiptState() {
|
||||||
|
return this.saleReceiptApplication.getSaleReceiptState();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,15 +5,47 @@ import { EditSaleReceipt } from './commands/EditSaleReceipt.service';
|
|||||||
import { GetSaleReceipt } from './queries/GetSaleReceipt.service';
|
import { GetSaleReceipt } from './queries/GetSaleReceipt.service';
|
||||||
import { DeleteSaleReceipt } from './commands/DeleteSaleReceipt.service';
|
import { DeleteSaleReceipt } from './commands/DeleteSaleReceipt.service';
|
||||||
import { CloseSaleReceipt } from './commands/CloseSaleReceipt.service';
|
import { CloseSaleReceipt } from './commands/CloseSaleReceipt.service';
|
||||||
|
import { SaleReceiptsPdfService } from './queries/SaleReceiptsPdf.service';
|
||||||
|
import { GetSaleReceiptState } from './queries/GetSaleReceiptState.service';
|
||||||
|
import { ItemsModule } from '../Items/items.module';
|
||||||
|
import { SaleReceiptDTOTransformer } from './commands/SaleReceiptDTOTransformer.service';
|
||||||
|
import { SaleReceiptValidators } from './commands/SaleReceiptValidators.service';
|
||||||
|
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
|
||||||
|
import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectable.module';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
import { SaleReceiptBrandingTemplate } from './queries/SaleReceiptBrandingTemplate.service';
|
||||||
|
import { BranchesModule } from '../Branches/Branches.module';
|
||||||
|
import { WarehousesModule } from '../Warehouses/Warehouses.module';
|
||||||
|
import { SaleReceiptIncrement } from './commands/SaleReceiptIncrement.service';
|
||||||
|
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
||||||
|
import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementOrders.module';
|
||||||
|
import { SaleReceiptsController } from './SaleReceipts.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
controllers: [SaleReceiptsController],
|
||||||
|
imports: [
|
||||||
|
ItemsModule,
|
||||||
|
ChromiumlyTenancyModule,
|
||||||
|
TemplateInjectableModule,
|
||||||
|
BranchesModule,
|
||||||
|
WarehousesModule,
|
||||||
|
PdfTemplatesModule,
|
||||||
|
AutoIncrementOrdersModule
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
TenancyContext,
|
||||||
|
SaleReceiptValidators,
|
||||||
SaleReceiptApplication,
|
SaleReceiptApplication,
|
||||||
CreateSaleReceipt,
|
CreateSaleReceipt,
|
||||||
EditSaleReceipt,
|
EditSaleReceipt,
|
||||||
GetSaleReceipt,
|
GetSaleReceipt,
|
||||||
DeleteSaleReceipt,
|
DeleteSaleReceipt,
|
||||||
CloseSaleReceipt,
|
CloseSaleReceipt,
|
||||||
|
SaleReceiptsPdfService,
|
||||||
|
GetSaleReceiptState,
|
||||||
|
SaleReceiptDTOTransformer,
|
||||||
|
SaleReceiptBrandingTemplate,
|
||||||
|
SaleReceiptIncrement,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SaleReceiptsModule {}
|
export class SaleReceiptsModule {}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { sumBy, omit } from 'lodash';
|
import { sumBy, omit } from 'lodash';
|
||||||
import composeAsync from 'async/compose';
|
import * as composeAsync from 'async/compose';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { SaleReceiptIncrement } from './SaleReceiptIncrement.service';
|
import { SaleReceiptIncrement } from './SaleReceiptIncrement.service';
|
||||||
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
||||||
@@ -18,6 +18,15 @@ import { Customer } from '@/modules/Customers/models/Customer';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SaleReceiptDTOTransformer {
|
export class SaleReceiptDTOTransformer {
|
||||||
|
/**
|
||||||
|
* @param {ItemsEntriesService} itemsEntriesService - Items entries service.
|
||||||
|
* @param {BranchTransactionDTOTransformer} branchDTOTransform - Branch transaction DTO transformer.
|
||||||
|
* @param {WarehouseTransactionDTOTransform} warehouseDTOTransform - Warehouse transaction DTO transformer.
|
||||||
|
* @param {SaleReceiptValidators} validators - Sale receipt validators.
|
||||||
|
* @param {SaleReceiptIncrement} receiptIncrement - Sale receipt increment.
|
||||||
|
* @param {BrandingTemplateDTOTransformer} brandingTemplatesTransformer - Branding template DTO transformer.
|
||||||
|
* @param {typeof ItemEntry} itemEntryModel - Item entry model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly itemsEntriesService: ItemsEntriesService,
|
private readonly itemsEntriesService: ItemsEntriesService,
|
||||||
private readonly branchDTOTransform: BranchTransactionDTOTransformer,
|
private readonly branchDTOTransform: BranchTransactionDTOTransformer,
|
||||||
@@ -60,10 +69,9 @@ export class SaleReceiptDTOTransformer {
|
|||||||
reference_type: 'SaleReceipt',
|
reference_type: 'SaleReceipt',
|
||||||
...entry,
|
...entry,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const asyncEntries = await composeAsync(
|
const asyncEntries = await composeAsync(
|
||||||
// Sets default cost and sell account to receipt items entries.
|
// Sets default cost and sell account to receipt items entries.
|
||||||
this.itemsEntriesService.setItemsEntriesDefaultAccounts(),
|
this.itemsEntriesService.setItemsEntriesDefaultAccounts,
|
||||||
)(initialEntries);
|
)(initialEntries);
|
||||||
|
|
||||||
const entries = R.compose(
|
const entries = R.compose(
|
||||||
@@ -97,6 +105,6 @@ export class SaleReceiptDTOTransformer {
|
|||||||
return R.compose(
|
return R.compose(
|
||||||
this.branchDTOTransform.transformDTO<SaleReceipt>,
|
this.branchDTOTransform.transformDTO<SaleReceipt>,
|
||||||
this.warehouseDTOTransform.transformDTO<SaleReceipt>,
|
this.warehouseDTOTransform.transformDTO<SaleReceipt>,
|
||||||
)(initialAsyncDTO);
|
)(initialAsyncDTO) as SaleReceipt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export class SaleReceiptValidators {
|
|||||||
* @param {typeof Account} accountModel - Account model.
|
* @param {typeof Account} accountModel - Account model.
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(SaleReceipt) private saleReceiptModel: typeof SaleReceipt,
|
@Inject(SaleReceipt.name) private saleReceiptModel: typeof SaleReceipt,
|
||||||
@Inject(Account) private accountModel: typeof Account,
|
@Inject(Account.name) private accountModel: typeof Account,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -119,18 +119,18 @@ export class SaleReceipt extends BaseModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const Customer = require('@/modules/Customers/models/Customer');
|
const { Customer } = require('../../Customers/models/Customer');
|
||||||
const Account = require('@/modules/Accounts/models/Account.model');
|
const { Account } = require('../../Accounts/models/Account.model');
|
||||||
const AccountTransaction = require('@/modules/AccountsTransactions/models/AccountTransaction.model');
|
const { AccountTransaction } = require('../../Accounts/models/AccountTransaction.model');
|
||||||
const ItemEntry = require('@/modules/ItemsEntries/models/ItemEntry');
|
const { ItemEntry } = require('../../TransactionItemEntry/models/ItemEntry');
|
||||||
const Branch = require('@/modules/Branches/models/Branch');
|
const { Branch } = require('../../Branches/models/Branch.model');
|
||||||
const Document = require('@/modules/Documents/models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
const Warehouse = require('@/modules/Warehouses/models/Warehouse');
|
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
customer: {
|
customer: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Customer.default,
|
modelClass: Customer,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.customerId',
|
from: 'sales_receipts.customerId',
|
||||||
to: 'contacts.id',
|
to: 'contacts.id',
|
||||||
@@ -142,7 +142,7 @@ export class SaleReceipt extends BaseModel {
|
|||||||
|
|
||||||
depositAccount: {
|
depositAccount: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Account.default,
|
modelClass: Account,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.depositAccountId',
|
from: 'sales_receipts.depositAccountId',
|
||||||
to: 'accounts.id',
|
to: 'accounts.id',
|
||||||
@@ -151,7 +151,7 @@ export class SaleReceipt extends BaseModel {
|
|||||||
|
|
||||||
entries: {
|
entries: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: ItemEntry.default,
|
modelClass: ItemEntry,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.id',
|
from: 'sales_receipts.id',
|
||||||
to: 'items_entries.referenceId',
|
to: 'items_entries.referenceId',
|
||||||
@@ -164,7 +164,7 @@ export class SaleReceipt extends BaseModel {
|
|||||||
|
|
||||||
transactions: {
|
transactions: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: AccountTransaction.default,
|
modelClass: AccountTransaction,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.id',
|
from: 'sales_receipts.id',
|
||||||
to: 'accounts_transactions.referenceId',
|
to: 'accounts_transactions.referenceId',
|
||||||
@@ -179,7 +179,7 @@ export class SaleReceipt extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
branch: {
|
branch: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Branch.default,
|
modelClass: Branch,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.branchId',
|
from: 'sales_receipts.branchId',
|
||||||
to: 'branches.id',
|
to: 'branches.id',
|
||||||
@@ -191,7 +191,7 @@ export class SaleReceipt extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
warehouse: {
|
warehouse: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Warehouse.default,
|
modelClass: Warehouse,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.warehouseId',
|
from: 'sales_receipts.warehouseId',
|
||||||
to: 'warehouses.id',
|
to: 'warehouses.id',
|
||||||
@@ -203,7 +203,7 @@ export class SaleReceipt extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
attachments: {
|
attachments: {
|
||||||
relation: Model.ManyToManyRelation,
|
relation: Model.ManyToManyRelation,
|
||||||
modelClass: Document.default,
|
modelClass: Document,
|
||||||
join: {
|
join: {
|
||||||
from: 'sales_receipts.id',
|
from: 'sales_receipts.id',
|
||||||
through: {
|
through: {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { SaleReceiptTransformer } from './SaleReceiptTransformer';
|
import { SaleReceiptTransformer } from './SaleReceiptTransformer';
|
||||||
import { SaleReceiptValidators } from '../commands/SaleReceiptValidators.service';
|
import { SaleReceiptValidators } from '../commands/SaleReceiptValidators.service';
|
||||||
import { SaleReceipt } from '../models/SaleReceipt';
|
import { SaleReceipt } from '../models/SaleReceipt';
|
||||||
@@ -7,6 +7,7 @@ import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectab
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetSaleReceipt {
|
export class GetSaleReceipt {
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(SaleReceipt.name)
|
||||||
private readonly saleReceiptModel: typeof SaleReceipt,
|
private readonly saleReceiptModel: typeof SaleReceipt,
|
||||||
private readonly transformer: TransformerInjectable,
|
private readonly transformer: TransformerInjectable,
|
||||||
private readonly validators: SaleReceiptValidators,
|
private readonly validators: SaleReceiptValidators,
|
||||||
@@ -26,11 +27,11 @@ export class GetSaleReceipt {
|
|||||||
.withGraphFetched('depositAccount')
|
.withGraphFetched('depositAccount')
|
||||||
.withGraphFetched('branch')
|
.withGraphFetched('branch')
|
||||||
.withGraphFetched('attachments')
|
.withGraphFetched('attachments')
|
||||||
.throwIfNotFound()
|
.throwIfNotFound();
|
||||||
|
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
saleReceipt,
|
saleReceipt,
|
||||||
new SaleReceiptTransformer()
|
new SaleReceiptTransformer(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class ItemEntriesTaxTransactions {
|
|||||||
* @param model
|
* @param model
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public assocTaxAmountWithheldFromEntries(model: any) {
|
public assocTaxAmountWithheldFromEntries = (model: any) => {
|
||||||
const entries = model.entries.map((entry) =>
|
const entries = model.entries.map((entry) =>
|
||||||
this.itemEntryModel.fromJson(entry),
|
this.itemEntryModel.fromJson(entry),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { EditTaxRateService } from './commands/EditTaxRate.service';
|
|||||||
import { CommandTaxRatesValidators } from './commands/CommandTaxRatesValidator.service';
|
import { CommandTaxRatesValidators } from './commands/CommandTaxRatesValidator.service';
|
||||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
import { TaxRatesApplication } from './TaxRate.application';
|
import { TaxRatesApplication } from './TaxRate.application';
|
||||||
|
import { ItemEntriesTaxTransactions } from './ItemEntriesTaxTransactions.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
@@ -24,7 +25,9 @@ import { TaxRatesApplication } from './TaxRate.application';
|
|||||||
CommandTaxRatesValidators,
|
CommandTaxRatesValidators,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TaxRatesApplication
|
TaxRatesApplication,
|
||||||
|
ItemEntriesTaxTransactions
|
||||||
],
|
],
|
||||||
|
exports: [ItemEntriesTaxTransactions],
|
||||||
})
|
})
|
||||||
export class TaxRatesModule {}
|
export class TaxRatesModule {}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TemplateInjectable } from './TemplateInjectable.service';
|
import { TemplateInjectable } from './TemplateInjectable.service';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [TemplateInjectable],
|
providers: [TemplateInjectable, TenancyContext],
|
||||||
|
exports: [TemplateInjectable]
|
||||||
})
|
})
|
||||||
export class TemplateInjectableModule {}
|
export class TemplateInjectableModule {}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Account } from '@/modules/Accounts/models/Account.model';
|
|||||||
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
||||||
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
||||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||||
import ExpenseCategory from '@/modules/Expenses/models/ExpenseCategory.model';
|
import { ExpenseCategory } from '@/modules/Expenses/models/ExpenseCategory.model';
|
||||||
import { ItemCategory } from '@/modules/ItemCategories/models/ItemCategory.model';
|
import { ItemCategory } from '@/modules/ItemCategories/models/ItemCategory.model';
|
||||||
import { TaxRateModel } from '@/modules/TaxRates/models/TaxRate.model';
|
import { TaxRateModel } from '@/modules/TaxRates/models/TaxRate.model';
|
||||||
import { PdfTemplateModel } from '@/modules/PdfTemplate/models/PdfTemplate';
|
import { PdfTemplateModel } from '@/modules/PdfTemplate/models/PdfTemplate';
|
||||||
@@ -20,6 +20,18 @@ import { Contact } from '@/modules/Contacts/models/Contact';
|
|||||||
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
|
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
|
||||||
import { DocumentLink } from '@/modules/ChromiumlyTenancy/models/DocumentLink';
|
import { DocumentLink } from '@/modules/ChromiumlyTenancy/models/DocumentLink';
|
||||||
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
||||||
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
|
import { BillPayment } from '@/modules/BillPayments/models/BillPayment';
|
||||||
|
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
||||||
|
import { BillLandedCostEntry } from '@/modules/BillLandedCosts/models/BillLandedCostEntry';
|
||||||
|
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
||||||
|
import { VendorCreditAppliedBill } from '@/modules/VendorCredit/models/VendorCreditAppliedBill';
|
||||||
|
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||||
|
import { PaymentReceivedEntry } from '@/modules/PaymentReceived/models/PaymentReceivedEntry';
|
||||||
|
import { CreditNoteAppliedInvoice } from '@/modules/CreditNotes/models/CreditNoteAppliedInvoice';
|
||||||
|
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||||
|
import { PaymentLink } from '@/modules/PaymentLinks/models/PaymentLink';
|
||||||
|
import { SaleReceipt } from '@/modules/SaleReceipts/models/SaleReceipt';
|
||||||
|
|
||||||
const models = [
|
const models = [
|
||||||
Item,
|
Item,
|
||||||
@@ -39,7 +51,19 @@ const models = [
|
|||||||
Contact,
|
Contact,
|
||||||
Document,
|
Document,
|
||||||
DocumentLink,
|
DocumentLink,
|
||||||
Vendor
|
Vendor,
|
||||||
|
Bill,
|
||||||
|
BillPayment,
|
||||||
|
BillPaymentEntry,
|
||||||
|
BillLandedCost,
|
||||||
|
BillLandedCostEntry,
|
||||||
|
VendorCreditAppliedBill,
|
||||||
|
SaleInvoice,
|
||||||
|
PaymentReceivedEntry,
|
||||||
|
CreditNoteAppliedInvoice,
|
||||||
|
CreditNote,
|
||||||
|
PaymentLink,
|
||||||
|
SaleReceipt
|
||||||
];
|
];
|
||||||
|
|
||||||
const modelProviders = models.map((model) => {
|
const modelProviders = models.map((model) => {
|
||||||
|
|||||||
@@ -124,121 +124,121 @@ export class ItemEntry extends BaseModel {
|
|||||||
/**
|
/**
|
||||||
* Item entry relations.
|
* Item entry relations.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
// static get relationMappings() {
|
||||||
const Item = require('models/Item');
|
// const Item = require('models/Item');
|
||||||
const BillLandedCostEntry = require('models/BillLandedCostEntry');
|
// const BillLandedCostEntry = require('models/BillLandedCostEntry');
|
||||||
const SaleInvoice = require('models/SaleInvoice');
|
// const SaleInvoice = require('models/SaleInvoice');
|
||||||
const Bill = require('models/Bill');
|
// const Bill = require('models/Bill');
|
||||||
const SaleReceipt = require('models/SaleReceipt');
|
// const SaleReceipt = require('models/SaleReceipt');
|
||||||
const SaleEstimate = require('models/SaleEstimate');
|
// const SaleEstimate = require('models/SaleEstimate');
|
||||||
const ProjectTask = require('models/Task');
|
// const ProjectTask = require('models/Task');
|
||||||
const Expense = require('models/Expense');
|
// const Expense = require('models/Expense');
|
||||||
const TaxRate = require('models/TaxRate');
|
// const TaxRate = require('models/TaxRate');
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
item: {
|
// item: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Item.default,
|
// modelClass: Item.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.itemId',
|
// from: 'items_entries.itemId',
|
||||||
to: 'items.id',
|
// to: 'items.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
allocatedCostEntries: {
|
// allocatedCostEntries: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: BillLandedCostEntry.default,
|
// modelClass: BillLandedCostEntry.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.referenceId',
|
// from: 'items_entries.referenceId',
|
||||||
to: 'bill_located_cost_entries.entryId',
|
// to: 'bill_located_cost_entries.entryId',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
invoice: {
|
// invoice: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: SaleInvoice.default,
|
// modelClass: SaleInvoice.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.referenceId',
|
// from: 'items_entries.referenceId',
|
||||||
to: 'sales_invoices.id',
|
// to: 'sales_invoices.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
bill: {
|
// bill: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Bill.default,
|
// modelClass: Bill.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.referenceId',
|
// from: 'items_entries.referenceId',
|
||||||
to: 'bills.id',
|
// to: 'bills.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
estimate: {
|
// estimate: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: SaleEstimate.default,
|
// modelClass: SaleEstimate.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.referenceId',
|
// from: 'items_entries.referenceId',
|
||||||
to: 'sales_estimates.id',
|
// to: 'sales_estimates.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Sale receipt reference.
|
// * Sale receipt reference.
|
||||||
*/
|
// */
|
||||||
receipt: {
|
// receipt: {
|
||||||
relation: Model.BelongsToOneRelation,
|
// relation: Model.BelongsToOneRelation,
|
||||||
modelClass: SaleReceipt.default,
|
// modelClass: SaleReceipt.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.referenceId',
|
// from: 'items_entries.referenceId',
|
||||||
to: 'sales_receipts.id',
|
// to: 'sales_receipts.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Project task reference.
|
// * Project task reference.
|
||||||
*/
|
// */
|
||||||
projectTaskRef: {
|
// projectTaskRef: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: ProjectTask.default,
|
// modelClass: ProjectTask.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.projectRefId',
|
// from: 'items_entries.projectRefId',
|
||||||
to: 'tasks.id',
|
// to: 'tasks.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Project expense reference.
|
// * Project expense reference.
|
||||||
*/
|
// */
|
||||||
projectExpenseRef: {
|
// projectExpenseRef: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: Expense.default,
|
// modelClass: Expense.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.projectRefId',
|
// from: 'items_entries.projectRefId',
|
||||||
to: 'expenses_transactions.id',
|
// to: 'expenses_transactions.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Project bill reference.
|
// * Project bill reference.
|
||||||
*/
|
// */
|
||||||
projectBillRef: {
|
// projectBillRef: {
|
||||||
relation: Model.HasManyRelation,
|
// relation: Model.HasManyRelation,
|
||||||
modelClass: Bill.default,
|
// modelClass: Bill.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.projectRefId',
|
// from: 'items_entries.projectRefId',
|
||||||
to: 'bills.id',
|
// to: 'bills.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Tax rate reference.
|
// * Tax rate reference.
|
||||||
*/
|
// */
|
||||||
tax: {
|
// tax: {
|
||||||
relation: Model.HasOneRelation,
|
// relation: Model.HasOneRelation,
|
||||||
modelClass: TaxRate.default,
|
// modelClass: TaxRate.default,
|
||||||
join: {
|
// join: {
|
||||||
from: 'items_entries.taxRateId',
|
// from: 'items_entries.taxRateId',
|
||||||
to: 'tax_rates.id',
|
// to: 'tax_rates.id',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
|||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
providers: [TransformerInjectable],
|
providers: [TransformerInjectable, TenancyContext],
|
||||||
exports: [TransformerInjectable],
|
exports: [TransformerInjectable],
|
||||||
imports: [TenancyContext],
|
imports: [],
|
||||||
})
|
})
|
||||||
export class TransformerModule {}
|
export class TransformerModule {}
|
||||||
|
|||||||
@@ -0,0 +1,296 @@
|
|||||||
|
import { Model, raw, mixin } from 'objection';
|
||||||
|
// import TenantModel from 'models/TenantModel';
|
||||||
|
// import BillSettings from './Bill.Settings';
|
||||||
|
// import ModelSetting from './ModelSetting';
|
||||||
|
// import CustomViewBaseModel from './CustomViewBaseModel';
|
||||||
|
// import { DEFAULT_VIEWS } from '@/services/Purchases/VendorCredits/constants';
|
||||||
|
// import ModelSearchable from './ModelSearchable';
|
||||||
|
// import VendorCreditMeta from './VendorCredit.Meta';
|
||||||
|
import { BaseModel } from '@/models/Model';
|
||||||
|
|
||||||
|
export class VendorCredit extends BaseModel {
|
||||||
|
vendorId: number;
|
||||||
|
amount: number;
|
||||||
|
currencyCode: string;
|
||||||
|
vendorCreditDate: Date;
|
||||||
|
vendorCreditNumber: string;
|
||||||
|
referenceNo: string;
|
||||||
|
refundedAmount: number;
|
||||||
|
invoicedAmount: number;
|
||||||
|
exchangeRate: number;
|
||||||
|
note: string;
|
||||||
|
openedAt: Date;
|
||||||
|
userId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
static get tableName() {
|
||||||
|
return 'vendor_credits';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vendor credit amount in local currency.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get localAmount() {
|
||||||
|
return this.amount * this.exchangeRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model modifiers.
|
||||||
|
*/
|
||||||
|
static get modifiers() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Filters the credit notes in draft status.
|
||||||
|
*/
|
||||||
|
draft(query) {
|
||||||
|
query.where('opened_at', null);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the published vendor credits.
|
||||||
|
*/
|
||||||
|
published(query) {
|
||||||
|
query.whereNot('opened_at', null);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the open vendor credits.
|
||||||
|
*/
|
||||||
|
open(query) {
|
||||||
|
query
|
||||||
|
.where(
|
||||||
|
raw(`COALESCE(REFUNDED_AMOUNT) + COALESCE(INVOICED_AMOUNT) <
|
||||||
|
COALESCE(AMOUNT)`),
|
||||||
|
)
|
||||||
|
.modify('published');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the closed vendor credits.
|
||||||
|
*/
|
||||||
|
closed(query) {
|
||||||
|
query
|
||||||
|
.where(
|
||||||
|
raw(`COALESCE(REFUNDED_AMOUNT) + COALESCE(INVOICED_AMOUNT) =
|
||||||
|
COALESCE(AMOUNT)`),
|
||||||
|
)
|
||||||
|
.modify('published');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status filter.
|
||||||
|
*/
|
||||||
|
filterByStatus(query, filterType) {
|
||||||
|
switch (filterType) {
|
||||||
|
case 'draft':
|
||||||
|
query.modify('draft');
|
||||||
|
break;
|
||||||
|
case 'published':
|
||||||
|
query.modify('published');
|
||||||
|
break;
|
||||||
|
case 'open':
|
||||||
|
default:
|
||||||
|
query.modify('open');
|
||||||
|
break;
|
||||||
|
case 'closed':
|
||||||
|
query.modify('closed');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
sortByStatus(query, order) {
|
||||||
|
query.orderByRaw(
|
||||||
|
`COALESCE(REFUNDED_AMOUNT) + COALESCE(INVOICED_AMOUNT) = COALESCE(AMOUNT) ${order}`,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamps columns.
|
||||||
|
*/
|
||||||
|
get timestamps() {
|
||||||
|
return ['createdAt', 'updatedAt'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual attributes.
|
||||||
|
*/
|
||||||
|
static get virtualAttributes() {
|
||||||
|
return [
|
||||||
|
'localAmount',
|
||||||
|
'isDraft',
|
||||||
|
'isPublished',
|
||||||
|
'isOpen',
|
||||||
|
'isClosed',
|
||||||
|
'creditsRemaining',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the vendor credit is draft.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get isDraft() {
|
||||||
|
return !this.openedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether vendor credit is published.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get isPublished() {
|
||||||
|
return !!this.openedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the credit note is open.
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
get isOpen() {
|
||||||
|
return !!this.openedAt && this.creditsRemaining > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the credit note is closed.
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
get isClosed() {
|
||||||
|
return this.openedAt && this.creditsRemaining === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the credits remaining.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get creditsRemaining() {
|
||||||
|
return Math.max(this.amount - this.refundedAmount - this.invoicedAmount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill model settings.
|
||||||
|
*/
|
||||||
|
// static get meta() {
|
||||||
|
// return BillSettings;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relationship mapping.
|
||||||
|
*/
|
||||||
|
// static get relationMappings() {
|
||||||
|
// const Vendor = require('models/Vendor');
|
||||||
|
// const ItemEntry = require('models/ItemEntry');
|
||||||
|
// const Branch = require('models/Branch');
|
||||||
|
// const Document = require('models/Document');
|
||||||
|
// const Warehouse = require('models/Warehouse');
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// vendor: {
|
||||||
|
// relation: Model.BelongsToOneRelation,
|
||||||
|
// modelClass: Vendor.default,
|
||||||
|
// join: {
|
||||||
|
// from: 'vendor_credits.vendorId',
|
||||||
|
// to: 'contacts.id',
|
||||||
|
// },
|
||||||
|
// filter(query) {
|
||||||
|
// query.where('contact_service', 'vendor');
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
// entries: {
|
||||||
|
// relation: Model.HasManyRelation,
|
||||||
|
// modelClass: ItemEntry.default,
|
||||||
|
// join: {
|
||||||
|
// from: 'vendor_credits.id',
|
||||||
|
// to: 'items_entries.referenceId',
|
||||||
|
// },
|
||||||
|
// filter(builder) {
|
||||||
|
// builder.where('reference_type', 'VendorCredit');
|
||||||
|
// builder.orderBy('index', 'ASC');
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Vendor credit may belongs to branch.
|
||||||
|
// */
|
||||||
|
// branch: {
|
||||||
|
// relation: Model.BelongsToOneRelation,
|
||||||
|
// modelClass: Branch.default,
|
||||||
|
// join: {
|
||||||
|
// from: 'vendor_credits.branchId',
|
||||||
|
// to: 'branches.id',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Vendor credit may has associated warehouse.
|
||||||
|
// */
|
||||||
|
// warehouse: {
|
||||||
|
// relation: Model.BelongsToOneRelation,
|
||||||
|
// modelClass: Warehouse.default,
|
||||||
|
// join: {
|
||||||
|
// from: 'vendor_credits.warehouseId',
|
||||||
|
// to: 'warehouses.id',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Vendor credit may has many attached attachments.
|
||||||
|
// */
|
||||||
|
// attachments: {
|
||||||
|
// relation: Model.ManyToManyRelation,
|
||||||
|
// modelClass: Document.default,
|
||||||
|
// join: {
|
||||||
|
// from: 'vendor_credits.id',
|
||||||
|
// through: {
|
||||||
|
// from: 'document_links.modelId',
|
||||||
|
// to: 'document_links.documentId',
|
||||||
|
// },
|
||||||
|
// to: 'documents.id',
|
||||||
|
// },
|
||||||
|
// filter(query) {
|
||||||
|
// query.where('model_ref', 'VendorCredit');
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// static get meta() {
|
||||||
|
// return VendorCreditMeta;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the default custom views, roles and columns.
|
||||||
|
*/
|
||||||
|
// static get defaultViews() {
|
||||||
|
// return DEFAULT_VIEWS;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model search attributes.
|
||||||
|
*/
|
||||||
|
static get searchRoles() {
|
||||||
|
return [
|
||||||
|
{ fieldKey: 'credit_number', comparator: 'contains' },
|
||||||
|
{ condition: 'or', fieldKey: 'reference_no', comparator: 'contains' },
|
||||||
|
{ condition: 'or', fieldKey: 'amount', comparator: 'equals' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevents mutate base currency since the model is not empty.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static get preventMutateBaseCurrency() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import { mixin, Model } from 'objection';
|
||||||
|
// import TenantModel from 'models/TenantModel';
|
||||||
|
// import ModelSetting from './ModelSetting';
|
||||||
|
// import CustomViewBaseModel from './CustomViewBaseModel';
|
||||||
|
// import ModelSearchable from './ModelSearchable';
|
||||||
|
import { BaseModel } from '@/models/Model';
|
||||||
|
|
||||||
|
export class VendorCreditAppliedBill extends BaseModel {
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
static get tableName() {
|
||||||
|
return 'vendor_credit_applied_bill';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamps columns.
|
||||||
|
*/
|
||||||
|
get timestamps() {
|
||||||
|
return ['created_at', 'updated_at'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relationship mapping.
|
||||||
|
*/
|
||||||
|
static get relationMappings() {
|
||||||
|
const { Bill } = require('../../Bills/models/Bill');
|
||||||
|
const { VendorCredit } = require('../../VendorCredit/models/VendorCredit');
|
||||||
|
|
||||||
|
return {
|
||||||
|
bill: {
|
||||||
|
relation: Model.BelongsToOneRelation,
|
||||||
|
modelClass: Bill,
|
||||||
|
join: {
|
||||||
|
from: 'vendor_credit_applied_bill.billId',
|
||||||
|
to: 'bills.id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
vendorCredit: {
|
||||||
|
relation: Model.BelongsToOneRelation,
|
||||||
|
modelClass: VendorCredit,
|
||||||
|
join: {
|
||||||
|
from: 'vendor_credit_applied_bill.vendorCreditId',
|
||||||
|
to: 'vendor_credits.id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,8 +13,10 @@ import {
|
|||||||
IVendorNewDTO,
|
IVendorNewDTO,
|
||||||
IVendorOpeningBalanceEditDTO,
|
IVendorOpeningBalanceEditDTO,
|
||||||
} from './types/Vendors.types';
|
} from './types/Vendors.types';
|
||||||
|
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||||
|
|
||||||
@Controller('vendors')
|
@Controller('vendors')
|
||||||
|
@PublicRoute()
|
||||||
export class VendorsController {
|
export class VendorsController {
|
||||||
constructor(private vendorsApplication: VendorsApplication) {}
|
constructor(private vendorsApplication: VendorsApplication) {}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class DeleteVendorService {
|
|||||||
constructor(
|
constructor(
|
||||||
private eventPublisher: EventEmitter2,
|
private eventPublisher: EventEmitter2,
|
||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
@Inject(Vendor.name) private contactModel: typeof Vendor,
|
@Inject(Vendor.name) private vendorModel: typeof Vendor,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,9 +29,8 @@ export class DeleteVendorService {
|
|||||||
*/
|
*/
|
||||||
public async deleteVendor(vendorId: number) {
|
public async deleteVendor(vendorId: number) {
|
||||||
// Retrieves the old vendor or throw not found service error.
|
// Retrieves the old vendor or throw not found service error.
|
||||||
const oldVendor = await this.contactModel
|
const oldVendor = await this.vendorModel
|
||||||
.query()
|
.query()
|
||||||
.modify('vendor')
|
|
||||||
.findById(vendorId)
|
.findById(vendorId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
// .queryAndThrowIfHasRelations({
|
// .queryAndThrowIfHasRelations({
|
||||||
@@ -47,7 +46,7 @@ export class DeleteVendorService {
|
|||||||
// Deletes vendor contact under unit-of-work.
|
// Deletes vendor contact under unit-of-work.
|
||||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
// Deletes the vendor contact from the storage.
|
// Deletes the vendor contact from the storage.
|
||||||
await this.contactModel.query(trx).findById(vendorId).delete();
|
await this.vendorModel.query(trx).findById(vendorId).delete();
|
||||||
|
|
||||||
// Triggers `onVendorDeleted` event.
|
// Triggers `onVendorDeleted` event.
|
||||||
await this.eventPublisher.emitAsync(events.vendors.onDeleted, {
|
await this.eventPublisher.emitAsync(events.vendors.onDeleted, {
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export class Vendor extends BaseModel {
|
|||||||
return {
|
return {
|
||||||
bills: {
|
bills: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: Bill.default,
|
modelClass: Bill,
|
||||||
join: {
|
join: {
|
||||||
from: 'contacts.id',
|
from: 'contacts.id',
|
||||||
to: 'bills.vendorId',
|
to: 'bills.vendorId',
|
||||||
@@ -178,7 +178,7 @@ export class Vendor extends BaseModel {
|
|||||||
},
|
},
|
||||||
overdueBills: {
|
overdueBills: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: Bill.default,
|
modelClass: Bill,
|
||||||
join: {
|
join: {
|
||||||
from: 'contacts.id',
|
from: 'contacts.id',
|
||||||
to: 'bills.vendorId',
|
to: 'bills.vendorId',
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ export class GetVendorService {
|
|||||||
const vendor = await this.vendorModel
|
const vendor = await this.vendorModel
|
||||||
.query()
|
.query()
|
||||||
.findById(vendorId)
|
.findById(vendorId)
|
||||||
.modify('vendor')
|
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
// Transformes the vendor.
|
// Transformes the vendor.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { ActivateWarehousesService } from './commands/ActivateWarehouses.service
|
|||||||
import { CreateInitialWarehouse } from './commands/CreateInitialWarehouse.service';
|
import { CreateInitialWarehouse } from './commands/CreateInitialWarehouse.service';
|
||||||
import { WarehousesSettings } from './WarehousesSettings';
|
import { WarehousesSettings } from './WarehousesSettings';
|
||||||
import { I18nContext } from 'nestjs-i18n';
|
import { I18nContext } from 'nestjs-i18n';
|
||||||
|
import { WarehouseTransactionDTOTransform } from './Integrations/WarehouseTransactionDTOTransform';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule],
|
||||||
@@ -36,6 +37,8 @@ import { I18nContext } from 'nestjs-i18n';
|
|||||||
I18nContext,
|
I18nContext,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
|
WarehouseTransactionDTOTransform
|
||||||
],
|
],
|
||||||
|
exports: [WarehouseTransactionDTOTransform],
|
||||||
})
|
})
|
||||||
export class WarehousesModule {}
|
export class WarehousesModule {}
|
||||||
|
|||||||
9
packages/server-nest/src/utils/transform-to-key.ts
Normal file
9
packages/server-nest/src/utils/transform-to-key.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
export const transformToMap = (objects, key) => {
|
||||||
|
const map = new Map();
|
||||||
|
|
||||||
|
objects.forEach((object) => {
|
||||||
|
map.set(object[key], object);
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
};
|
||||||
82
packages/server-nest/test/customers.e2e-spec.ts
Normal file
82
packages/server-nest/test/customers.e2e-spec.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import * as request from 'supertest';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { app } from './init-app-test';
|
||||||
|
|
||||||
|
describe('Customers (e2e)', () => {
|
||||||
|
it('/customers (POST)', () => {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post('/customers')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
customerType: 'business',
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
})
|
||||||
|
.expect(201);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/customers/:id (GET)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/customers')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
customerType: 'business',
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
});
|
||||||
|
const customerId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.get(`/customers/${customerId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/customers/:id (DELETE)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/customers')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
customerType: 'business',
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
});
|
||||||
|
const customerId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.delete(`/customers/${customerId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/customers/:id (PUT)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/customers')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
customerType: 'business',
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
});
|
||||||
|
const customerId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.put(`/customers/${customerId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
33
packages/server-nest/test/sale-invoices.e2e-spec.ts
Normal file
33
packages/server-nest/test/sale-invoices.e2e-spec.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import * as request from 'supertest';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { app } from './init-app-test';
|
||||||
|
|
||||||
|
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...',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.expect(201);
|
||||||
|
});
|
||||||
|
});
|
||||||
80
packages/server-nest/test/sale-receipts.e2e-spec.ts
Normal file
80
packages/server-nest/test/sale-receipts.e2e-spec.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import * as request from 'supertest';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { app } from './init-app-test';
|
||||||
|
|
||||||
|
const receiptRequest = {
|
||||||
|
customerId: 2,
|
||||||
|
depositAccountId: 1000,
|
||||||
|
receiptDate: '2022-02-02',
|
||||||
|
referenceNo: '123',
|
||||||
|
receiptNumber: faker.string.uuid(),
|
||||||
|
branchId: 1,
|
||||||
|
warehouseId: 1,
|
||||||
|
discount: 100,
|
||||||
|
discountType: 'amount',
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
itemId: 1001,
|
||||||
|
quantity: 1,
|
||||||
|
rate: 2000,
|
||||||
|
description: 'asdfsadf',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Sale Receipts (e2e)', () => {
|
||||||
|
it('/sale-reeipts (POST)', () => {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post('/sale-receipts')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send(receiptRequest)
|
||||||
|
.expect(201);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/sale-receipts/:id (DELETE)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/sale-receipts')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send(receiptRequest);
|
||||||
|
|
||||||
|
const receiptId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.delete(`/sale-receipts/${receiptId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/sale-receipts/:id (PUT)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/sale-receipts')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send(receiptRequest);
|
||||||
|
|
||||||
|
const receiptId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.delete(`/sale-receipts/${receiptId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
...receiptRequest,
|
||||||
|
referenceNo: '321',
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/sale-receipts/:id (GET)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/sale-receipts')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send(receiptRequest);
|
||||||
|
|
||||||
|
const receiptId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.get(`/sale-receipts/${receiptId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
75
packages/server-nest/test/vendors.e2e-spec.ts
Normal file
75
packages/server-nest/test/vendors.e2e-spec.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import * as request from 'supertest';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { app } from './init-app-test';
|
||||||
|
|
||||||
|
describe('Vendors (e2e)', () => {
|
||||||
|
it('/vendors (POST)', () => {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post('/vendors')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
})
|
||||||
|
.expect(201);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/vendors/:id (PUT)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/vendors')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
});
|
||||||
|
const vendorId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.put(`/vendors/${vendorId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/vendors/:id (GET)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/vendors')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
});
|
||||||
|
const vendorId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.get(`/vendors/${vendorId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/vendors/:id (DELETE)', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post('/vendors')
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.send({
|
||||||
|
displayName: faker.commerce.productName(),
|
||||||
|
});
|
||||||
|
const vendorId = response.body.id;
|
||||||
|
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.delete(`/vendors/${vendorId}`)
|
||||||
|
.set('organization-id', '4064541lv40nhca')
|
||||||
|
.expect(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user