feat: remove path alias.

feat: remove Webpack and depend on nodemon.
feat: refactoring expenses.
feat: optimize system users with caching.
feat: architecture tenant optimize.
This commit is contained in:
Ahmed Bouhuolia
2020-09-15 00:51:39 +02:00
parent ad00f140d1
commit a22c8395f3
293 changed files with 3391 additions and 1637 deletions

View File

@@ -1,12 +1,13 @@
import { Inject, Service } from 'typedi';
import { difference } from 'lodash';
import { ServiceError } from "@/exceptions";
import TenancyService from '@/services/Tenancy/TenancyService';
import { difference, upperFirst } from 'lodash';
import { ServiceError } from "exceptions";
import TenancyService from 'services/Tenancy/TenancyService';
import {
IContact,
IContactNewDTO,
IContactEditDTO,
} from "@/interfaces";
} from "interfaces";
import JournalPoster from '../Accounting/JournalPoster';
type TContactService = 'customer' | 'vendor';
@@ -128,4 +129,31 @@ export default class ContactsService {
await Contact.query().whereIn('id', contactsIds).delete();
}
/**
* Reverts journal entries of the given contacts.
* @param {number} tenantId
* @param {number[]} contactsIds
* @param {TContactService} contactService
*/
async revertJEntriesContactsOpeningBalance(
tenantId: number,
contactsIds: number[],
contactService: TContactService
) {
const { AccountTransaction } = this.tenancy.models(tenantId);
const journal = new JournalPoster(tenantId);
const contactsTransactions = await AccountTransaction.query()
.whereIn('reference_id', contactsIds)
.where('reference_type', `${upperFirst(contactService)}OpeningBalance`);
journal.loadEntries(contactsTransactions);
journal.removeEntries();
await Promise.all([
journal.saveBalance(),
journal.deleteEntries(),
]);
}
}

View File

@@ -1,14 +1,14 @@
import { Inject, Service } from 'typedi';
import { omit, difference } from 'lodash';
import JournalPoster from "@/services/Accounting/JournalPoster";
import JournalCommands from "@/services/Accounting/JournalCommands";
import ContactsService from '@/services/Contacts/ContactsService';
import JournalPoster from "services/Accounting/JournalPoster";
import JournalCommands from "services/Accounting/JournalCommands";
import ContactsService from 'services/Contacts/ContactsService';
import {
ICustomerNewDTO,
ICustomerEditDTO,
} from '@/interfaces';
import { ServiceError } from '@/exceptions';
import TenancyService from '@/services/Tenancy/TenancyService';
} from 'interfaces';
import { ServiceError } from 'exceptions';
import TenancyService from 'services/Tenancy/TenancyService';
import { ICustomer } from 'src/interfaces';
@Service()
@@ -44,7 +44,7 @@ export default class CustomersService {
const customer = await this.contactService.newContact(tenantId, contactDTO, 'customer');
// Writes the customer opening balance journal entries.
if (customer.openingBalance) {
if (customer.openingBalance) {
await this.writeCustomerOpeningBalanceJournal(
tenantId,
customer.id,
@@ -71,8 +71,16 @@ export default class CustomersService {
* @return {Promise<void>}
*/
async deleteCustomer(tenantId: number, customerId: number) {
const { Contact } = this.tenancy.models(tenantId);
await this.getCustomerByIdOrThrowError(tenantId, customerId);
await this.customerHasNoInvoicesOrThrowError(tenantId, customerId);
return this.contactService.deleteContact(tenantId, customerId, 'customer');
await Contact.query().findById(customerId).delete();
await this.contactService.revertJEntriesContactsOpeningBalance(
tenantId, [customerId], 'customer',
);
}
/**
@@ -107,6 +115,15 @@ export default class CustomersService {
]);
}
/**
* Retrieve the given customer by id or throw not found.
* @param {number} tenantId
* @param {number} customerId
*/
getCustomerByIdOrThrowError(tenantId: number, customerId: number) {
return this.contactService.getContactByIdOrThrowError(tenantId, customerId, 'customer');
}
/**
* Retrieve the given customers or throw error if one of them not found.
* @param {numebr} tenantId
@@ -129,6 +146,12 @@ export default class CustomersService {
await this.customersHaveNoInvoicesOrThrowError(tenantId, customersIds);
await Contact.query().whereIn('id', customersIds).delete();
await this.contactService.revertJEntriesContactsOpeningBalance(
tenantId,
customersIds,
'Customer'
);
}
/**

View File

@@ -1,15 +1,15 @@
import { Inject, Service } from 'typedi';
import { difference } from 'lodash';
import JournalPoster from "@/services/Accounting/JournalPoster";
import JournalCommands from "@/services/Accounting/JournalCommands";
import ContactsService from '@/services/Contacts/ContactsService';
import JournalPoster from "services/Accounting/JournalPoster";
import JournalCommands from "services/Accounting/JournalCommands";
import ContactsService from 'services/Contacts/ContactsService';
import {
IVendorNewDTO,
IVendorEditDTO,
IVendor
} from '@/interfaces';
import { ServiceError } from '@/exceptions';
import TenancyService from '@/services/Tenancy/TenancyService';
} from 'interfaces';
import { ServiceError } from 'exceptions';
import TenancyService from 'services/Tenancy/TenancyService';
@Service()
export default class VendorsService {
@@ -39,7 +39,8 @@ export default class VendorsService {
* @return {Promise<void>}
*/
async newVendor(tenantId: number, vendorDTO: IVendorNewDTO) {
const contactDTO = this.vendorToContactDTO(vendorDTO)
const contactDTO = this.vendorToContactDTO(vendorDTO);
const vendor = await this.contactService.newContact(tenantId, contactDTO, 'vendor');
// Writes the vendor opening balance journal entries.
@@ -63,6 +64,15 @@ export default class VendorsService {
return this.contactService.editContact(tenantId, vendorId, contactDTO, 'vendor');
}
/**
* Retrieve the given vendor details by id or throw not found.
* @param {number} tenantId
* @param {number} customerId
*/
getVendorByIdOrThrowError(tenantId: number, customerId: number) {
return this.contactService.getContactByIdOrThrowError(tenantId, customerId, 'vendor');
}
/**
* Deletes the given vendor from the storage.
* @param {number} tenantId
@@ -70,8 +80,16 @@ export default class VendorsService {
* @return {Promise<void>}
*/
async deleteVendor(tenantId: number, vendorId: number) {
const { Contact } = this.tenancy.models(tenantId);
await this.getVendorByIdOrThrowError(tenantId, vendorId);
await this.vendorHasNoBillsOrThrowError(tenantId, vendorId);
return this.contactService.deleteContact(tenantId, vendorId, 'vendor');
await Contact.query().findById(vendorId).delete();
await this.contactService.revertJEntriesContactsOpeningBalance(
tenantId, [vendorId], 'vendor',
);
}
/**
@@ -128,6 +146,10 @@ export default class VendorsService {
await this.vendorsHaveNoBillsOrThrowError(tenantId, vendorsIds);
await Contact.query().whereIn('id', vendorsIds).delete();
await this.contactService.revertJEntriesContactsOpeningBalance(
tenantId, vendorsIds, 'vendor',
);
}
/**
@@ -139,7 +161,7 @@ export default class VendorsService {
const { vendorRepository } = this.tenancy.repositories(tenantId);
const bills = await vendorRepository.getBills(vendorId);
if (bills) {
if (bills.length > 0) {
throw new ServiceError('vendor_has_bills')
}
}