fix(Contacts): validate contact associated transcations.

This commit is contained in:
a.bouhuolia
2021-03-22 15:21:52 +02:00
parent 1f6aca63e2
commit d79be910f9
20 changed files with 382 additions and 384 deletions

View File

@@ -15,6 +15,7 @@ import {
IPaymentReceiveEntry,
IPaymentReceiveEntryDTO,
IPaymentReceivesFilter,
IPaymentsReceiveService,
ISaleInvoice,
ISystemUser,
} from 'interfaces';
@@ -37,8 +38,8 @@ import { ERRORS } from './constants';
* Payment receive service.
* @service
*/
@Service()
export default class PaymentReceiveService {
@Service('PaymentReceives')
export default class PaymentReceiveService implements IPaymentsReceiveService {
@Inject()
accountsService: AccountsService;
@@ -522,7 +523,7 @@ export default class PaymentReceiveService {
public async deletePaymentReceive(
tenantId: number,
paymentReceiveId: number,
authorizedUser: ISystemUser,
authorizedUser: ISystemUser
) {
const { PaymentReceive, PaymentReceiveEntry } = this.tenancy.models(
tenantId
@@ -772,4 +773,24 @@ export default class PaymentReceiveService {
});
await Promise.all([...opers]);
}
/**
* Validate the given customer has no payments receives.
* @param {number} tenantId
* @param {number} customerId - Customer id.
*/
public async validateCustomerHasNoPayments(
tenantId: number,
customerId: number
) {
const { PaymentReceive } = this.tenancy.models(tenantId);
const paymentReceives = await PaymentReceive.query().where(
'customer_id',
customerId
);
if (paymentReceives.length > 0) {
throw new ServiceError(ERRORS.CUSTOMER_HAS_PAYMENT_RECEIVES);
}
}
}

View File

@@ -10,4 +10,5 @@ export const ERRORS = {
PAYMENT_RECEIVE_NO_IS_REQUIRED: 'PAYMENT_RECEIVE_NO_IS_REQUIRED',
PAYMENT_RECEIVE_NO_REQUIRED: 'PAYMENT_RECEIVE_NO_REQUIRED',
PAYMENT_CUSTOMER_SHOULD_NOT_UPDATE: 'PAYMENT_CUSTOMER_SHOULD_NOT_UPDATE',
CUSTOMER_HAS_PAYMENT_RECEIVES: 'CUSTOMER_HAS_PAYMENT_RECEIVES'
};

View File

@@ -6,6 +6,7 @@ import {
IPaginationMeta,
ISaleEstimate,
ISaleEstimateDTO,
ISalesEstimatesService,
} from 'interfaces';
import {
EventDispatcher,
@@ -32,14 +33,15 @@ const ERRORS = {
SALE_ESTIMATE_ALREADY_APPROVED: 'SALE_ESTIMATE_ALREADY_APPROVED',
SALE_ESTIMATE_NOT_DELIVERED: 'SALE_ESTIMATE_NOT_DELIVERED',
SALE_ESTIMATE_NO_IS_REQUIRED: 'SALE_ESTIMATE_NO_IS_REQUIRED',
CUSTOMER_HAS_SALES_ESTIMATES: 'CUSTOMER_HAS_SALES_ESTIMATES',
};
/**
* Sale estimate service.
* @Service
*/
@Service()
export default class SaleEstimateService {
@Service('SalesEstimates')
export default class SaleEstimateService implements ISalesEstimatesService{
@Inject()
tenancy: TenancyService;
@@ -174,7 +176,8 @@ export default class SaleEstimateService {
const autoNextNumber = this.getNextEstimateNumber(tenantId);
// Retreive the next estimate number.
const estimateNumber = estimateDTO.estimateNumber ||
const estimateNumber =
estimateDTO.estimateNumber ||
oldSaleEstimate?.estimateNumber ||
autoNextNumber;
@@ -201,9 +204,9 @@ export default class SaleEstimateService {
})),
// Avoid rewrite the deliver date in edit mode when already published.
...(estimateDTO.delivered &&
!oldSaleEstimate?.deliveredAt && {
deliveredAt: moment().toMySqlDateTime(),
}),
!oldSaleEstimate?.deliveredAt && {
deliveredAt: moment().toMySqlDateTime(),
}),
};
}
@@ -233,10 +236,7 @@ export default class SaleEstimateService {
this.logger.info('[sale_estimate] inserting sale estimate to the storage.');
// Transform DTO object ot model object.
const estimateObj = await this.transformDTOToModel(
tenantId,
estimateDTO
);
const estimateObj = await this.transformDTOToModel(tenantId, estimateDTO);
// Validate estimate number uniquiness on the storage.
await this.validateEstimateNumberExistance(
tenantId,
@@ -583,4 +583,24 @@ export default class SaleEstimateService {
approvedAt: null,
});
}
/**
* Validate the given customer has no sales estimates.
* @param {number} tenantId
* @param {number} customerId - Customer id.
*/
public async validateCustomerHasNoEstimates(
tenantId: number,
customerId: number
) {
const { SaleEstimate } = this.tenancy.models(tenantId);
const estimates = await SaleEstimate.query().where(
'customer_id',
customerId
);
if (estimates.length > 0) {
throw new ServiceError(ERRORS.CUSTOMER_HAS_SALES_ESTIMATES);
}
}
}

View File

@@ -15,6 +15,7 @@ import {
ISystemUser,
IItem,
IItemEntry,
ISalesInvoicesService
} from 'interfaces';
import JournalPoster from 'services/Accounting/JournalPoster';
import JournalCommands from 'services/Accounting/JournalCommands';
@@ -36,8 +37,8 @@ import { ERRORS } from './constants';
* Sales invoices service
* @service
*/
@Service()
export default class SaleInvoicesService {
@Service('SalesInvoices')
export default class SaleInvoicesService implements ISalesInvoicesService {
@Inject()
tenancy: TenancyService;
@@ -665,4 +666,22 @@ export default class SaleInvoicesService {
return salesInvoices;
}
/**
* Validate the given customer has no sales invoices.
* @param {number} tenantId
* @param {number} customerId - Customer id.
*/
public async validateCustomerHasNoInvoices(
tenantId: number,
customerId: number
) {
const { SaleInvoice } = this.tenancy.models(tenantId);
const invoices = await SaleInvoice.query().where('customer_id', customerId);
if (invoices.length > 0) {
throw new ServiceError(ERRORS.CUSTOMER_HAS_SALES_INVOICES);
}
}
}

View File

@@ -8,11 +8,18 @@ import {
import events from 'subscribers/events';
import JournalPoster from 'services/Accounting/JournalPoster';
import JournalCommands from 'services/Accounting/JournalCommands';
import { ISaleReceipt, ISaleReceiptDTO, IItemEntry, IItem } from 'interfaces';
import {
IFilterMeta,
IPaginationMeta,
ISaleReceipt,
ISaleReceiptDTO,
ISalesReceiptsService,
IItemEntry,
IItem,
} from 'interfaces';
import JournalPosterService from 'services/Sales/JournalPosterService';
import TenancyService from 'services/Tenancy/TenancyService';
import { formatDateFields } from 'utils';
import { IFilterMeta, IPaginationMeta } from 'interfaces';
import DynamicListingService from 'services/DynamicListing/DynamicListService';
import { ServiceError } from 'exceptions';
import ItemsEntriesService from 'services/Items/ItemsEntriesService';
@@ -29,10 +36,11 @@ const ERRORS = {
SALE_RECEIPT_NUMBER_NOT_UNIQUE: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE',
SALE_RECEIPT_IS_ALREADY_CLOSED: 'SALE_RECEIPT_IS_ALREADY_CLOSED',
SALE_RECEIPT_NO_IS_REQUIRED: 'SALE_RECEIPT_NO_IS_REQUIRED',
CUSTOMER_HAS_SALES_INVOICES: 'CUSTOMER_HAS_SALES_INVOICES',
};
@Service()
export default class SalesReceiptService {
@Service('SalesReceipts')
export default class SalesReceiptService implements ISalesReceiptsService {
@Inject()
tenancy: TenancyService;
@@ -548,4 +556,22 @@ export default class SalesReceiptService {
'SaleReceipt'
);
}
/**
* Validate the given customer has no sales receipts.
* @param {number} tenantId
* @param {number} customerId - Customer id.
*/
public async validateCustomerHasNoReceipts(
tenantId: number,
customerId: number
) {
const { SaleReceipt } = this.tenancy.models(tenantId);
const receipts = await SaleReceipt.query().where('customer_id', customerId);
if (receipts.length > 0) {
throw new ServiceError(ERRORS.CUSTOMER_HAS_SALES_INVOICES);
}
}
}

View File

@@ -9,5 +9,6 @@ export const ERRORS = {
'INVOICE_AMOUNT_SMALLER_THAN_PAYMENT_AMOUNT',
INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES:
'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES',
SALE_INVOICE_NO_IS_REQUIRED: 'SALE_INVOICE_NO_IS_REQUIRED'
SALE_INVOICE_NO_IS_REQUIRED: 'SALE_INVOICE_NO_IS_REQUIRED',
CUSTOMER_HAS_SALES_INVOICES: 'CUSTOMER_HAS_SALES_INVOICES'
};