mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-13 11:20:31 +00:00
fix(server): customer/vendor opening balance:
This commit is contained in:
@@ -1,117 +1,103 @@
|
||||
// import { Service, Inject } from 'typedi';
|
||||
// import { AccountNormal, ICustomer, ILedgerEntry } from '@/interfaces';
|
||||
// import Ledger from '@/services/Accounting/Ledger';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { AccountNormal } from '@/interfaces/Account';
|
||||
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||
import { Customer } from './models/Customer';
|
||||
|
||||
// @Service()
|
||||
// export class CustomerGLEntries {
|
||||
// /**
|
||||
// * Retrieves the customer opening balance common entry attributes.
|
||||
// * @param {ICustomer} customer
|
||||
// */
|
||||
// private getCustomerOpeningGLCommonEntry = (customer: ICustomer) => {
|
||||
// return {
|
||||
// exchangeRate: customer.openingBalanceExchangeRate,
|
||||
// currencyCode: customer.currencyCode,
|
||||
@Injectable()
|
||||
export class CustomerGLEntries {
|
||||
/**
|
||||
* Retrieves the customer opening balance common entry attributes.
|
||||
*/
|
||||
private getCustomerOpeningGLCommonEntry = (customer: Customer) => {
|
||||
return {
|
||||
exchangeRate: customer.openingBalanceExchangeRate,
|
||||
currencyCode: customer.currencyCode,
|
||||
|
||||
// transactionType: 'CustomerOpeningBalance',
|
||||
// transactionId: customer.id,
|
||||
transactionType: 'CustomerOpeningBalance',
|
||||
transactionId: customer.id,
|
||||
|
||||
// date: customer.openingBalanceAt,
|
||||
// userId: customer.userId,
|
||||
// contactId: customer.id,
|
||||
date: customer.openingBalanceAt,
|
||||
contactId: customer.id,
|
||||
|
||||
// credit: 0,
|
||||
// debit: 0,
|
||||
credit: 0,
|
||||
debit: 0,
|
||||
|
||||
// branchId: customer.openingBalanceBranchId,
|
||||
// };
|
||||
// };
|
||||
branchId: customer.openingBalanceBranchId,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the customer opening GL credit entry.
|
||||
// * @param {number} ARAccountId
|
||||
// * @param {ICustomer} customer
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getCustomerOpeningGLCreditEntry = (
|
||||
// ARAccountId: number,
|
||||
// customer: ICustomer
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getCustomerOpeningGLCommonEntry(customer);
|
||||
/**
|
||||
* Retrieves the customer opening GL credit entry.
|
||||
*/
|
||||
private getCustomerOpeningGLCreditEntry = (
|
||||
ARAccountId: number,
|
||||
customer: Customer
|
||||
): ILedgerEntry => {
|
||||
const commonEntry = this.getCustomerOpeningGLCommonEntry(customer);
|
||||
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// credit: 0,
|
||||
// debit: customer.localOpeningBalance,
|
||||
// accountId: ARAccountId,
|
||||
// accountNormal: AccountNormal.DEBIT,
|
||||
// index: 1,
|
||||
// };
|
||||
// };
|
||||
return {
|
||||
...commonEntry,
|
||||
credit: 0,
|
||||
debit: customer.localOpeningBalance,
|
||||
accountId: ARAccountId,
|
||||
accountNormal: AccountNormal.DEBIT,
|
||||
index: 1,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the customer opening GL debit entry.
|
||||
// * @param {number} incomeAccountId
|
||||
// * @param {ICustomer} customer
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getCustomerOpeningGLDebitEntry = (
|
||||
// incomeAccountId: number,
|
||||
// customer: ICustomer
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getCustomerOpeningGLCommonEntry(customer);
|
||||
/**
|
||||
* Retrieves the customer opening GL debit entry.
|
||||
*/
|
||||
private getCustomerOpeningGLDebitEntry = (
|
||||
incomeAccountId: number,
|
||||
customer: Customer
|
||||
): ILedgerEntry => {
|
||||
const commonEntry = this.getCustomerOpeningGLCommonEntry(customer);
|
||||
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// credit: customer.localOpeningBalance,
|
||||
// debit: 0,
|
||||
// accountId: incomeAccountId,
|
||||
// accountNormal: AccountNormal.CREDIT,
|
||||
return {
|
||||
...commonEntry,
|
||||
credit: customer.localOpeningBalance,
|
||||
debit: 0,
|
||||
accountId: incomeAccountId,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
|
||||
// index: 2,
|
||||
// };
|
||||
// };
|
||||
index: 2,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the customer opening GL entries.
|
||||
// * @param {number} ARAccountId
|
||||
// * @param {number} incomeAccountId
|
||||
// * @param {ICustomer} customer
|
||||
// * @returns {ILedgerEntry[]}
|
||||
// */
|
||||
// public getCustomerOpeningGLEntries = (
|
||||
// ARAccountId: number,
|
||||
// incomeAccountId: number,
|
||||
// customer: ICustomer
|
||||
// ) => {
|
||||
// const debitEntry = this.getCustomerOpeningGLDebitEntry(
|
||||
// incomeAccountId,
|
||||
// customer
|
||||
// );
|
||||
// const creditEntry = this.getCustomerOpeningGLCreditEntry(
|
||||
// ARAccountId,
|
||||
// customer
|
||||
// );
|
||||
// return [debitEntry, creditEntry];
|
||||
// };
|
||||
/**
|
||||
* Retrieves the customer opening GL entries.
|
||||
*/
|
||||
public getCustomerOpeningGLEntries = (
|
||||
ARAccountId: number,
|
||||
incomeAccountId: number,
|
||||
customer: Customer
|
||||
) => {
|
||||
const debitEntry = this.getCustomerOpeningGLDebitEntry(
|
||||
incomeAccountId,
|
||||
customer
|
||||
);
|
||||
const creditEntry = this.getCustomerOpeningGLCreditEntry(
|
||||
ARAccountId,
|
||||
customer
|
||||
);
|
||||
return [debitEntry, creditEntry];
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the customer opening balance ledger.
|
||||
// * @param {number} ARAccountId
|
||||
// * @param {number} incomeAccountId
|
||||
// * @param {ICustomer} customer
|
||||
// * @returns {ILedger}
|
||||
// */
|
||||
// public getCustomerOpeningLedger = (
|
||||
// ARAccountId: number,
|
||||
// incomeAccountId: number,
|
||||
// customer: ICustomer
|
||||
// ) => {
|
||||
// const entries = this.getCustomerOpeningGLEntries(
|
||||
// ARAccountId,
|
||||
// incomeAccountId,
|
||||
// customer
|
||||
// );
|
||||
// return new Ledger(entries);
|
||||
// };
|
||||
// }
|
||||
/**
|
||||
* Retrieves the customer opening balance ledger.
|
||||
*/
|
||||
public getCustomerOpeningLedger = (
|
||||
ARAccountId: number,
|
||||
incomeAccountId: number,
|
||||
customer: Customer
|
||||
) => {
|
||||
const entries = this.getCustomerOpeningGLEntries(
|
||||
ARAccountId,
|
||||
incomeAccountId,
|
||||
customer
|
||||
);
|
||||
return new Ledger(entries);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,90 +1,79 @@
|
||||
// import { Knex } from 'knex';
|
||||
// import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import { Service, Inject } from 'typedi';
|
||||
// import { CustomerGLEntries } from './CustomerGLEntries';
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { LedgerStorageService } from '@/modules/Ledger/LedgerStorage.service';
|
||||
import { AccountRepository } from '@/modules/Accounts/repositories/Account.repository';
|
||||
import { CustomerGLEntries } from './CustomerGLEntries';
|
||||
import { Customer } from './models/Customer';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
// @Service()
|
||||
// export class CustomerGLEntriesStorage {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
@Injectable()
|
||||
export class CustomerGLEntriesStorage {
|
||||
constructor(
|
||||
private readonly ledgerStorage: LedgerStorageService,
|
||||
private readonly accountRepository: AccountRepository,
|
||||
private readonly customerGLEntries: CustomerGLEntries,
|
||||
|
||||
// @Inject()
|
||||
// private ledegrRepository: LedgerStorageService;
|
||||
@Inject(Customer.name)
|
||||
private readonly customerModel: TenantModelProxy<typeof Customer>,
|
||||
) { }
|
||||
|
||||
// @Inject()
|
||||
// private customerGLEntries: CustomerGLEntries;
|
||||
/**
|
||||
* Customer opening balance journals.
|
||||
*/
|
||||
public writeCustomerOpeningBalance = async (
|
||||
customerId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
const customer = await this.customerModel()
|
||||
.query(trx)
|
||||
.findById(customerId);
|
||||
|
||||
// /**
|
||||
// * Customer opening balance journals.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} customerId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public writeCustomerOpeningBalance = async (
|
||||
// tenantId: number,
|
||||
// customerId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// const { Customer } = this.tenancy.models(tenantId);
|
||||
// const { accountRepository } = this.tenancy.repositories(tenantId);
|
||||
// Finds the income account.
|
||||
const incomeAccount = await this.accountRepository.findOne({
|
||||
slug: 'other-income',
|
||||
});
|
||||
// Find or create the A/R account.
|
||||
const ARAccount =
|
||||
await this.accountRepository.findOrCreateAccountReceivable(
|
||||
customer.currencyCode,
|
||||
{},
|
||||
trx,
|
||||
);
|
||||
// Retrieves the customer opening balance ledger.
|
||||
const ledger = this.customerGLEntries.getCustomerOpeningLedger(
|
||||
ARAccount.id,
|
||||
incomeAccount.id,
|
||||
customer,
|
||||
);
|
||||
// Commits the ledger entries to the storage.
|
||||
await this.ledgerStorage.commit(ledger, trx);
|
||||
};
|
||||
|
||||
// const customer = await Customer.query(trx).findById(customerId);
|
||||
/**
|
||||
* Reverts the customer opening balance GL entries.
|
||||
*/
|
||||
public revertCustomerOpeningBalance = async (
|
||||
customerId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
await this.ledgerStorage.deleteByReference(
|
||||
customerId,
|
||||
'CustomerOpeningBalance',
|
||||
trx,
|
||||
);
|
||||
};
|
||||
|
||||
// // Finds the income account.
|
||||
// const incomeAccount = await accountRepository.findOne({
|
||||
// slug: 'other-income',
|
||||
// });
|
||||
// // Find or create the A/R account.
|
||||
// const ARAccount = await accountRepository.findOrCreateAccountReceivable(
|
||||
// customer.currencyCode,
|
||||
// {},
|
||||
// trx
|
||||
// );
|
||||
// // Retrieves the customer opening balance ledger.
|
||||
// const ledger = this.customerGLEntries.getCustomerOpeningLedger(
|
||||
// ARAccount.id,
|
||||
// incomeAccount.id,
|
||||
// customer
|
||||
// );
|
||||
// // Commits the ledger entries to the storage.
|
||||
// await this.ledegrRepository.commit(tenantId, ledger, trx);
|
||||
// };
|
||||
/**
|
||||
* Writes the customer opening balance GL entries.
|
||||
*/
|
||||
public rewriteCustomerOpeningBalance = async (
|
||||
customerId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Reverts the customer opening balance entries.
|
||||
await this.revertCustomerOpeningBalance(customerId, trx);
|
||||
|
||||
// /**
|
||||
// * Reverts the customer opening balance GL entries.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} customerId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public revertCustomerOpeningBalance = async (
|
||||
// tenantId: number,
|
||||
// customerId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// await this.ledegrRepository.deleteByReference(
|
||||
// tenantId,
|
||||
// customerId,
|
||||
// 'CustomerOpeningBalance',
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Writes the customer opening balance GL entries.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} customerId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public rewriteCustomerOpeningBalance = async (
|
||||
// tenantId: number,
|
||||
// customerId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// // Reverts the customer opening balance entries.
|
||||
// await this.revertCustomerOpeningBalance(tenantId, customerId, trx);
|
||||
|
||||
// // Write the customer opening balance entries.
|
||||
// await this.writeCustomerOpeningBalance(tenantId, customerId, trx);
|
||||
// };
|
||||
// }
|
||||
// Write the customer opening balance entries.
|
||||
await this.writeCustomerOpeningBalance(customerId, trx);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,9 +18,14 @@ import { GetCustomers } from './queries/GetCustomers.service';
|
||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||
import { BulkDeleteCustomersService } from './BulkDeleteCustomers.service';
|
||||
import { ValidateBulkDeleteCustomersService } from './ValidateBulkDeleteCustomers.service';
|
||||
import { LedgerModule } from '../Ledger/Ledger.module';
|
||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||
import { CustomerGLEntries } from './CustomerGLEntries';
|
||||
import { CustomerGLEntriesStorage } from './CustomerGLEntriesStorage';
|
||||
import { CustomerWriteGLOpeningBalanceSubscriber } from './subscribers/CustomerGLEntriesSubscriber';
|
||||
|
||||
@Module({
|
||||
imports: [TenancyDatabaseModule, DynamicListModule],
|
||||
imports: [TenancyDatabaseModule, DynamicListModule, LedgerModule, AccountsModule],
|
||||
controllers: [CustomersController],
|
||||
providers: [
|
||||
ActivateCustomer,
|
||||
@@ -41,6 +46,9 @@ import { ValidateBulkDeleteCustomersService } from './ValidateBulkDeleteCustomer
|
||||
GetCustomers,
|
||||
BulkDeleteCustomersService,
|
||||
ValidateBulkDeleteCustomersService,
|
||||
CustomerGLEntries,
|
||||
CustomerGLEntriesStorage,
|
||||
CustomerWriteGLOpeningBalanceSubscriber,
|
||||
],
|
||||
})
|
||||
export class CustomersModule {}
|
||||
export class CustomersModule { }
|
||||
|
||||
@@ -1,91 +1,63 @@
|
||||
// import { Service, Inject } from 'typedi';
|
||||
// import {
|
||||
// ICustomerEventCreatedPayload,
|
||||
// ICustomerEventDeletedPayload,
|
||||
// ICustomerOpeningBalanceEditedPayload,
|
||||
// } from '@/interfaces';
|
||||
// import events from '@/subscribers/events';
|
||||
// import { CustomerGLEntriesStorage } from '../CustomerGLEntriesStorage';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import {
|
||||
ICustomerEventCreatedPayload,
|
||||
ICustomerEventDeletedPayload,
|
||||
ICustomerOpeningBalanceEditedPayload,
|
||||
} from '../types/Customers.types';
|
||||
import { events } from '@/common/events/events';
|
||||
import { CustomerGLEntriesStorage } from '../CustomerGLEntriesStorage';
|
||||
|
||||
// @Service()
|
||||
// export class CustomerWriteGLOpeningBalanceSubscriber {
|
||||
// @Inject()
|
||||
// private customerGLEntries: CustomerGLEntriesStorage;
|
||||
@Injectable()
|
||||
export class CustomerWriteGLOpeningBalanceSubscriber {
|
||||
constructor(private readonly customerGLEntries: CustomerGLEntriesStorage) { }
|
||||
|
||||
// /**
|
||||
// * Attaches events with handlers.
|
||||
// */
|
||||
// public attach(bus) {
|
||||
// bus.subscribe(
|
||||
// events.customers.onCreated,
|
||||
// this.handleWriteOpenBalanceEntries
|
||||
// );
|
||||
// bus.subscribe(
|
||||
// events.customers.onDeleted,
|
||||
// this.handleRevertOpeningBalanceEntries
|
||||
// );
|
||||
// bus.subscribe(
|
||||
// events.customers.onOpeningBalanceChanged,
|
||||
// this.handleRewriteOpeningEntriesOnChanged
|
||||
// );
|
||||
// }
|
||||
/**
|
||||
* Handles the writing opening balance journal entries once the customer created.
|
||||
*/
|
||||
@OnEvent(events.customers.onCreated)
|
||||
public async handleWriteOpenBalanceEntries({
|
||||
customer,
|
||||
trx,
|
||||
}: ICustomerEventCreatedPayload) {
|
||||
// Writes the customer opening balance journal entries.
|
||||
if (customer.openingBalance) {
|
||||
await this.customerGLEntries.writeCustomerOpeningBalance(
|
||||
customer.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Handles the writing opening balance journal entries once the customer created.
|
||||
// * @param {ICustomerEventCreatedPayload} payload -
|
||||
// */
|
||||
// private handleWriteOpenBalanceEntries = async ({
|
||||
// tenantId,
|
||||
// customer,
|
||||
// trx,
|
||||
// }: ICustomerEventCreatedPayload) => {
|
||||
// // Writes the customer opening balance journal entries.
|
||||
// if (customer.openingBalance) {
|
||||
// await this.customerGLEntries.writeCustomerOpeningBalance(
|
||||
// tenantId,
|
||||
// customer.id,
|
||||
// trx
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
/**
|
||||
* Handles the deleting opening balance journal entries once the customer deleted.
|
||||
*/
|
||||
@OnEvent(events.customers.onDeleted)
|
||||
public async handleRevertOpeningBalanceEntries({
|
||||
customerId,
|
||||
trx,
|
||||
}: ICustomerEventDeletedPayload) {
|
||||
await this.customerGLEntries.revertCustomerOpeningBalance(customerId, trx);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Handles the deleting opeing balance journal entrise once the customer deleted.
|
||||
// * @param {ICustomerEventDeletedPayload} payload -
|
||||
// */
|
||||
// private handleRevertOpeningBalanceEntries = async ({
|
||||
// tenantId,
|
||||
// customerId,
|
||||
// trx,
|
||||
// }: ICustomerEventDeletedPayload) => {
|
||||
// await this.customerGLEntries.revertCustomerOpeningBalance(
|
||||
// tenantId,
|
||||
// customerId,
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Handles the rewrite opening balance entries once opening balnace changed.
|
||||
// * @param {ICustomerOpeningBalanceEditedPayload} payload -
|
||||
// */
|
||||
// private handleRewriteOpeningEntriesOnChanged = async ({
|
||||
// tenantId,
|
||||
// customer,
|
||||
// trx,
|
||||
// }: ICustomerOpeningBalanceEditedPayload) => {
|
||||
// if (customer.openingBalance) {
|
||||
// await this.customerGLEntries.rewriteCustomerOpeningBalance(
|
||||
// tenantId,
|
||||
// customer.id,
|
||||
// trx
|
||||
// );
|
||||
// } else {
|
||||
// await this.customerGLEntries.revertCustomerOpeningBalance(
|
||||
// tenantId,
|
||||
// customer.id,
|
||||
// trx
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
/**
|
||||
* Handles the rewrite opening balance entries once opening balance changed.
|
||||
*/
|
||||
@OnEvent(events.customers.onOpeningBalanceChanged)
|
||||
public async handleRewriteOpeningEntriesOnChanged({
|
||||
customer,
|
||||
trx,
|
||||
}: ICustomerOpeningBalanceEditedPayload) {
|
||||
if (customer.openingBalance) {
|
||||
await this.customerGLEntries.rewriteCustomerOpeningBalance(
|
||||
customer.id,
|
||||
trx,
|
||||
);
|
||||
} else {
|
||||
await this.customerGLEntries.revertCustomerOpeningBalance(
|
||||
customer.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,115 +1,116 @@
|
||||
// import { Service } from 'typedi';
|
||||
// import { IVendor, AccountNormal, ILedgerEntry } from '@/interfaces';
|
||||
// import Ledger from '@/services/Accounting/Ledger';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { AccountNormal } from '@/interfaces/Account';
|
||||
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||
import { Vendor } from './models/Vendor';
|
||||
|
||||
// @Service()
|
||||
// export class VendorGLEntries {
|
||||
// /**
|
||||
// * Retrieves the opening balance GL common entry.
|
||||
// * @param {IVendor} vendor -
|
||||
// */
|
||||
// private getOpeningBalanceGLCommonEntry = (vendor: IVendor) => {
|
||||
// return {
|
||||
// exchangeRate: vendor.openingBalanceExchangeRate,
|
||||
// currencyCode: vendor.currencyCode,
|
||||
@Injectable()
|
||||
export class VendorGLEntries {
|
||||
/**
|
||||
* Retrieves the opening balance GL common entry.
|
||||
* @param {Vendor} vendor -
|
||||
*/
|
||||
private getOpeningBalanceGLCommonEntry = (vendor: Vendor) => {
|
||||
return {
|
||||
exchangeRate: vendor.openingBalanceExchangeRate,
|
||||
currencyCode: vendor.currencyCode,
|
||||
|
||||
// transactionType: 'VendorOpeningBalance',
|
||||
// transactionId: vendor.id,
|
||||
transactionType: 'VendorOpeningBalance',
|
||||
transactionId: vendor.id,
|
||||
|
||||
// date: vendor.openingBalanceAt,
|
||||
// userId: vendor.userId,
|
||||
// contactId: vendor.id,
|
||||
date: vendor.openingBalanceAt,
|
||||
contactId: vendor.id,
|
||||
|
||||
// credit: 0,
|
||||
// debit: 0,
|
||||
credit: 0,
|
||||
debit: 0,
|
||||
|
||||
// branchId: vendor.openingBalanceBranchId,
|
||||
// };
|
||||
// };
|
||||
branchId: vendor.openingBalanceBranchId,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the opening balance GL debit entry.
|
||||
// * @param {number} costAccountId -
|
||||
// * @param {IVendor} vendor
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getOpeningBalanceGLDebitEntry = (
|
||||
// costAccountId: number,
|
||||
// vendor: IVendor
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getOpeningBalanceGLCommonEntry(vendor);
|
||||
/**
|
||||
* Retrieves the opening balance GL debit entry.
|
||||
* @param {number} costAccountId -
|
||||
* @param {Vendor} vendor
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getOpeningBalanceGLDebitEntry = (
|
||||
costAccountId: number,
|
||||
vendor: Vendor
|
||||
): ILedgerEntry => {
|
||||
const commonEntry = this.getOpeningBalanceGLCommonEntry(vendor);
|
||||
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// accountId: costAccountId,
|
||||
// accountNormal: AccountNormal.DEBIT,
|
||||
// debit: vendor.localOpeningBalance,
|
||||
// credit: 0,
|
||||
// index: 2,
|
||||
// };
|
||||
// };
|
||||
return {
|
||||
...commonEntry,
|
||||
accountId: costAccountId,
|
||||
accountNormal: AccountNormal.DEBIT,
|
||||
debit: vendor.localOpeningBalance,
|
||||
credit: 0,
|
||||
index: 2,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the opening balance GL credit entry.
|
||||
// * @param {number} APAccountId
|
||||
// * @param {IVendor} vendor
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getOpeningBalanceGLCreditEntry = (
|
||||
// APAccountId: number,
|
||||
// vendor: IVendor
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getOpeningBalanceGLCommonEntry(vendor);
|
||||
/**
|
||||
* Retrieves the opening balance GL credit entry.
|
||||
* @param {number} APAccountId
|
||||
* @param {Vendor} vendor
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getOpeningBalanceGLCreditEntry = (
|
||||
APAccountId: number,
|
||||
vendor: Vendor
|
||||
): ILedgerEntry => {
|
||||
const commonEntry = this.getOpeningBalanceGLCommonEntry(vendor);
|
||||
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// accountId: APAccountId,
|
||||
// accountNormal: AccountNormal.CREDIT,
|
||||
// credit: vendor.localOpeningBalance,
|
||||
// index: 1,
|
||||
// };
|
||||
// };
|
||||
return {
|
||||
...commonEntry,
|
||||
accountId: APAccountId,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
credit: vendor.localOpeningBalance,
|
||||
index: 1,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the opening balance GL entries.
|
||||
// * @param {number} APAccountId
|
||||
// * @param {number} costAccountId -
|
||||
// * @param {IVendor} vendor
|
||||
// * @returns {ILedgerEntry[]}
|
||||
// */
|
||||
// public getOpeningBalanceGLEntries = (
|
||||
// APAccountId: number,
|
||||
// costAccountId: number,
|
||||
// vendor: IVendor
|
||||
// ): ILedgerEntry[] => {
|
||||
// const debitEntry = this.getOpeningBalanceGLDebitEntry(
|
||||
// costAccountId,
|
||||
// vendor
|
||||
// );
|
||||
// const creditEntry = this.getOpeningBalanceGLCreditEntry(
|
||||
// APAccountId,
|
||||
// vendor
|
||||
// );
|
||||
// return [debitEntry, creditEntry];
|
||||
// };
|
||||
/**
|
||||
* Retrieves the opening balance GL entries.
|
||||
* @param {number} APAccountId
|
||||
* @param {number} costAccountId -
|
||||
* @param {Vendor} vendor
|
||||
* @returns {ILedgerEntry[]}
|
||||
*/
|
||||
public getOpeningBalanceGLEntries = (
|
||||
APAccountId: number,
|
||||
costAccountId: number,
|
||||
vendor: Vendor
|
||||
): ILedgerEntry[] => {
|
||||
const debitEntry = this.getOpeningBalanceGLDebitEntry(
|
||||
costAccountId,
|
||||
vendor
|
||||
);
|
||||
const creditEntry = this.getOpeningBalanceGLCreditEntry(
|
||||
APAccountId,
|
||||
vendor
|
||||
);
|
||||
return [debitEntry, creditEntry];
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the opening balance ledger.
|
||||
// * @param {number} APAccountId
|
||||
// * @param {number} costAccountId -
|
||||
// * @param {IVendor} vendor
|
||||
// * @returns {Ledger}
|
||||
// */
|
||||
// public getOpeningBalanceLedger = (
|
||||
// APAccountId: number,
|
||||
// costAccountId: number,
|
||||
// vendor: IVendor
|
||||
// ) => {
|
||||
// const entries = this.getOpeningBalanceGLEntries(
|
||||
// APAccountId,
|
||||
// costAccountId,
|
||||
// vendor
|
||||
// );
|
||||
// return new Ledger(entries);
|
||||
// };
|
||||
// }
|
||||
/**
|
||||
* Retrieves the opening balance ledger.
|
||||
* @param {number} APAccountId
|
||||
* @param {number} costAccountId -
|
||||
* @param {Vendor} vendor
|
||||
* @returns {Ledger}
|
||||
*/
|
||||
public getOpeningBalanceLedger = (
|
||||
APAccountId: number,
|
||||
costAccountId: number,
|
||||
vendor: Vendor
|
||||
) => {
|
||||
const entries = this.getOpeningBalanceGLEntries(
|
||||
APAccountId,
|
||||
costAccountId,
|
||||
vendor
|
||||
);
|
||||
return new Ledger(entries);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,88 +1,86 @@
|
||||
// import { Knex } from 'knex';
|
||||
// import { Service, Inject } from 'typedi';
|
||||
// import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import { VendorGLEntries } from './VendorGLEntries';
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { LedgerStorageService } from '@/modules/Ledger/LedgerStorage.service';
|
||||
import { AccountRepository } from '@/modules/Accounts/repositories/Account.repository';
|
||||
import { VendorGLEntries } from './VendorGLEntries';
|
||||
import { Vendor } from './models/Vendor';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
// @Service()
|
||||
// export class VendorGLEntriesStorage {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
@Injectable()
|
||||
export class VendorGLEntriesStorage {
|
||||
constructor(
|
||||
private readonly ledgerStorage: LedgerStorageService,
|
||||
private readonly accountRepository: AccountRepository,
|
||||
private readonly vendorGLEntries: VendorGLEntries,
|
||||
|
||||
// @Inject()
|
||||
// private ledegrRepository: LedgerStorageService;
|
||||
@Inject(Vendor.name)
|
||||
private readonly vendorModel: TenantModelProxy<typeof Vendor>,
|
||||
) { }
|
||||
|
||||
// @Inject()
|
||||
// private vendorGLEntries: VendorGLEntries;
|
||||
/**
|
||||
* Vendor opening balance journals.
|
||||
* @param {number} vendorId
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public writeVendorOpeningBalance = async (
|
||||
vendorId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
const vendor = await this.vendorModel()
|
||||
.query(trx)
|
||||
.findById(vendorId);
|
||||
|
||||
// /**
|
||||
// * Vendor opening balance journals.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} vendorId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public writeVendorOpeningBalance = async (
|
||||
// tenantId: number,
|
||||
// vendorId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// const { Vendor } = this.tenancy.models(tenantId);
|
||||
// const { accountRepository } = this.tenancy.repositories(tenantId);
|
||||
// Finds the expense account.
|
||||
const expenseAccount = await this.accountRepository.findOrCreateOtherExpensesAccount(
|
||||
{},
|
||||
trx,
|
||||
);
|
||||
// Find or create the A/P account.
|
||||
const APAccount =
|
||||
await this.accountRepository.findOrCreateAccountsPayable(
|
||||
vendor.currencyCode,
|
||||
{},
|
||||
trx,
|
||||
);
|
||||
// Retrieves the vendor opening balance ledger.
|
||||
const ledger = this.vendorGLEntries.getOpeningBalanceLedger(
|
||||
APAccount.id,
|
||||
expenseAccount.id,
|
||||
vendor,
|
||||
);
|
||||
// Commits the ledger entries to the storage.
|
||||
await this.ledgerStorage.commit(ledger, trx);
|
||||
};
|
||||
|
||||
// const vendor = await Vendor.query(trx).findById(vendorId);
|
||||
/**
|
||||
* Reverts the vendor opening balance GL entries.
|
||||
* @param {number} vendorId
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public revertVendorOpeningBalance = async (
|
||||
vendorId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
await this.ledgerStorage.deleteByReference(
|
||||
vendorId,
|
||||
'VendorOpeningBalance',
|
||||
trx,
|
||||
);
|
||||
};
|
||||
|
||||
// // Finds the expense account.
|
||||
// const expenseAccount = await accountRepository.findOne({
|
||||
// slug: 'other-expenses',
|
||||
// });
|
||||
// // Find or create the A/P account.
|
||||
// const APAccount = await accountRepository.findOrCreateAccountsPayable(
|
||||
// vendor.currencyCode,
|
||||
// {},
|
||||
// trx
|
||||
// );
|
||||
// // Retrieves the vendor opening balance ledger.
|
||||
// const ledger = this.vendorGLEntries.getOpeningBalanceLedger(
|
||||
// APAccount.id,
|
||||
// expenseAccount.id,
|
||||
// vendor
|
||||
// );
|
||||
// // Commits the ledger entries to the storage.
|
||||
// await this.ledegrRepository.commit(tenantId, ledger, trx);
|
||||
// };
|
||||
/**
|
||||
* Writes the vendor opening balance GL entries.
|
||||
* @param {number} vendorId
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public rewriteVendorOpeningBalance = async (
|
||||
vendorId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Reverts the vendor opening balance entries first.
|
||||
await this.revertVendorOpeningBalance(vendorId, trx);
|
||||
|
||||
// /**
|
||||
// * Reverts the vendor opening balance GL entries.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} vendorId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public revertVendorOpeningBalance = async (
|
||||
// tenantId: number,
|
||||
// vendorId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// await this.ledegrRepository.deleteByReference(
|
||||
// tenantId,
|
||||
// vendorId,
|
||||
// 'VendorOpeningBalance',
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Writes the vendor opening balance GL entries.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} vendorId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public rewriteVendorOpeningBalance = async (
|
||||
// tenantId: number,
|
||||
// vendorId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// await this.writeVendorOpeningBalance(tenantId, vendorId, trx);
|
||||
|
||||
// await this.revertVendorOpeningBalance(tenantId, vendorId, trx);
|
||||
// };
|
||||
// }
|
||||
// Write the vendor opening balance entries.
|
||||
await this.writeVendorOpeningBalance(vendorId, trx);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,9 +18,14 @@ import { VendorsExportable } from './VendorsExportable';
|
||||
import { VendorsImportable } from './VendorsImportable';
|
||||
import { BulkDeleteVendorsService } from './BulkDeleteVendors.service';
|
||||
import { ValidateBulkDeleteVendorsService } from './ValidateBulkDeleteVendors.service';
|
||||
import { LedgerModule } from '../Ledger/Ledger.module';
|
||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||
import { VendorGLEntries } from './VendorGLEntries';
|
||||
import { VendorGLEntriesStorage } from './VendorGLEntriesStorage';
|
||||
import { VendorsWriteGLOpeningSubscriber } from './subscribers/VendorGLEntriesSubscriber';
|
||||
|
||||
@Module({
|
||||
imports: [TenancyDatabaseModule, DynamicListModule],
|
||||
imports: [TenancyDatabaseModule, DynamicListModule, LedgerModule, AccountsModule],
|
||||
controllers: [VendorsController],
|
||||
providers: [
|
||||
ActivateVendorService,
|
||||
@@ -38,7 +43,10 @@ import { ValidateBulkDeleteVendorsService } from './ValidateBulkDeleteVendors.se
|
||||
TransformerInjectable,
|
||||
TenancyContext,
|
||||
VendorsExportable,
|
||||
VendorsImportable
|
||||
VendorsImportable,
|
||||
VendorGLEntries,
|
||||
VendorGLEntriesStorage,
|
||||
VendorsWriteGLOpeningSubscriber,
|
||||
],
|
||||
})
|
||||
export class VendorsModule {}
|
||||
export class VendorsModule { }
|
||||
|
||||
@@ -36,6 +36,7 @@ export class Vendor extends TenantBaseModel {
|
||||
openingBalance: number;
|
||||
openingBalanceExchangeRate: number;
|
||||
openingBalanceAt: Date | string;
|
||||
openingBalanceBranchId?: number;
|
||||
|
||||
salutation: string;
|
||||
firstName: string;
|
||||
|
||||
@@ -1,91 +1,71 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import events from '@/subscribers/events';
|
||||
// import { VendorGLEntriesStorage } from '../VendorGLEntriesStorage';
|
||||
// import {
|
||||
// IVendorEventCreatedPayload,
|
||||
// IVendorEventDeletedPayload,
|
||||
// IVendorOpeningBalanceEditedPayload,
|
||||
// } from '@/interfaces';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { VendorGLEntriesStorage } from '../VendorGLEntriesStorage';
|
||||
import {
|
||||
IVendorEventCreatedPayload,
|
||||
IVendorEventDeletedPayload,
|
||||
IVendorOpeningBalanceEditedPayload,
|
||||
} from '../types/Vendors.types';
|
||||
|
||||
// @Service()
|
||||
// export class VendorsWriteGLOpeningSubscriber {
|
||||
// @Inject()
|
||||
// private vendorGLEntriesStorage: VendorGLEntriesStorage;
|
||||
@Injectable()
|
||||
export class VendorsWriteGLOpeningSubscriber {
|
||||
constructor(
|
||||
private readonly vendorGLEntriesStorage: VendorGLEntriesStorage,
|
||||
) {}
|
||||
|
||||
// /**
|
||||
// * Constructor method.
|
||||
// */
|
||||
// public attach(bus) {
|
||||
// bus.subscribe(
|
||||
// events.vendors.onCreated,
|
||||
// this.handleWriteOpeningBalanceEntries
|
||||
// );
|
||||
// bus.subscribe(
|
||||
// events.vendors.onDeleted,
|
||||
// this.handleRevertOpeningBalanceEntries
|
||||
// );
|
||||
// bus.subscribe(
|
||||
// events.vendors.onOpeningBalanceChanged,
|
||||
// this.handleRewriteOpeningEntriesOnChanged
|
||||
// );
|
||||
// }
|
||||
/**
|
||||
* Writes the open balance journal entries once the vendor created.
|
||||
* @param {IVendorEventCreatedPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.vendors.onCreated)
|
||||
public async handleWriteOpeningBalanceEntries({
|
||||
vendor,
|
||||
trx,
|
||||
}: IVendorEventCreatedPayload) {
|
||||
// Writes the vendor opening balance journal entries.
|
||||
if (vendor.openingBalance) {
|
||||
await this.vendorGLEntriesStorage.writeVendorOpeningBalance(
|
||||
vendor.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Writes the open balance journal entries once the vendor created.
|
||||
// * @param {IVendorEventCreatedPayload} payload -
|
||||
// */
|
||||
// private handleWriteOpeningBalanceEntries = async ({
|
||||
// tenantId,
|
||||
// vendor,
|
||||
// trx,
|
||||
// }: IVendorEventCreatedPayload) => {
|
||||
// // Writes the vendor opening balance journal entries.
|
||||
// if (vendor.openingBalance) {
|
||||
// await this.vendorGLEntriesStorage.writeVendorOpeningBalance(
|
||||
// tenantId,
|
||||
// vendor.id,
|
||||
// trx
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
/**
|
||||
* Revert the opening balance journal entries once the vendor deleted.
|
||||
* @param {IVendorEventDeletedPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.vendors.onDeleted)
|
||||
public async handleRevertOpeningBalanceEntries({
|
||||
vendorId,
|
||||
trx,
|
||||
}: IVendorEventDeletedPayload) {
|
||||
await this.vendorGLEntriesStorage.revertVendorOpeningBalance(
|
||||
vendorId,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Revert the opening balance journal entries once the vendor deleted.
|
||||
// * @param {IVendorEventDeletedPayload} payload -
|
||||
// */
|
||||
// private handleRevertOpeningBalanceEntries = async ({
|
||||
// tenantId,
|
||||
// vendorId,
|
||||
// trx,
|
||||
// }: IVendorEventDeletedPayload) => {
|
||||
// await this.vendorGLEntriesStorage.revertVendorOpeningBalance(
|
||||
// tenantId,
|
||||
// vendorId,
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Handles the rewrite opening balance entries once opening balnace changed.
|
||||
// * @param {ICustomerOpeningBalanceEditedPayload} payload -
|
||||
// */
|
||||
// private handleRewriteOpeningEntriesOnChanged = async ({
|
||||
// tenantId,
|
||||
// vendor,
|
||||
// trx,
|
||||
// }: IVendorOpeningBalanceEditedPayload) => {
|
||||
// if (vendor.openingBalance) {
|
||||
// await this.vendorGLEntriesStorage.rewriteVendorOpeningBalance(
|
||||
// tenantId,
|
||||
// vendor.id,
|
||||
// trx
|
||||
// );
|
||||
// } else {
|
||||
// await this.vendorGLEntriesStorage.revertVendorOpeningBalance(
|
||||
// tenantId,
|
||||
// vendor.id,
|
||||
// trx
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
/**
|
||||
* Handles the rewrite opening balance entries once opening balance changed.
|
||||
* @param {IVendorOpeningBalanceEditedPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.vendors.onOpeningBalanceChanged)
|
||||
public async handleRewriteOpeningEntriesOnChanged({
|
||||
vendor,
|
||||
trx,
|
||||
}: IVendorOpeningBalanceEditedPayload) {
|
||||
if (vendor.openingBalance) {
|
||||
await this.vendorGLEntriesStorage.rewriteVendorOpeningBalance(
|
||||
vendor.id,
|
||||
trx,
|
||||
);
|
||||
} else {
|
||||
await this.vendorGLEntriesStorage.revertVendorOpeningBalance(
|
||||
vendor.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user