mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
fix(Contacts): validate contact associated transcations.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user