mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-23 16:19:49 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0868eeaa0e | ||
|
|
17dbe9713b | ||
|
|
ecaf8c99bb | ||
|
|
90bde20674 | ||
|
|
0c61f85707 | ||
|
|
0f678e61c5 | ||
|
|
374f1acf8a | ||
|
|
ada1428193 | ||
|
|
528d447443 | ||
|
|
d6d67b9a51 | ||
|
|
12740223a8 | ||
|
|
f7f77b12c9 | ||
|
|
a6db4fb6df | ||
|
|
b38020d397 | ||
|
|
d090d5a026 | ||
|
|
7b5287ee80 | ||
|
|
ba3ea93a2d |
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
All notable changes to Bigcapital server-side will be in this file.
|
All notable changes to Bigcapital server-side will be in this file.
|
||||||
|
|
||||||
|
## [0.14.0] - 30-01-2024
|
||||||
|
|
||||||
|
* feat: purchases by items exporting by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/327
|
||||||
|
* fix: expense amounts should not be rounded by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/339
|
||||||
|
* feat: get latest exchange rate from third party services by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/340
|
||||||
|
* fix(webapp): inconsistency in currency of universal search items by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/335
|
||||||
|
* hotfix: editing sales and expense transactions don't reflect GL entries by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/342
|
||||||
|
|
||||||
## [0.13.3] - 22-01-2024
|
## [0.13.3] - 22-01-2024
|
||||||
|
|
||||||
* hotfix(server): Unhandled thrown errors of services by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/329
|
* hotfix(server): Unhandled thrown errors of services by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/329
|
||||||
|
|||||||
@@ -26,27 +26,27 @@ export default class ContactsController extends BaseController {
|
|||||||
[...this.autocompleteQuerySchema],
|
[...this.autocompleteQuerySchema],
|
||||||
this.validationResult,
|
this.validationResult,
|
||||||
this.asyncMiddleware(this.autocompleteContacts.bind(this)),
|
this.asyncMiddleware(this.autocompleteContacts.bind(this)),
|
||||||
this.dynamicListService.handlerErrorsToResponse
|
this.dynamicListService.handlerErrorsToResponse,
|
||||||
);
|
);
|
||||||
router.get(
|
router.get(
|
||||||
'/:id',
|
'/:id',
|
||||||
[param('id').exists().isNumeric().toInt()],
|
[param('id').exists().isNumeric().toInt()],
|
||||||
this.validationResult,
|
this.validationResult,
|
||||||
this.asyncMiddleware(this.getContact.bind(this))
|
this.asyncMiddleware(this.getContact.bind(this)),
|
||||||
);
|
);
|
||||||
router.post(
|
router.post(
|
||||||
'/:id/inactivate',
|
'/:id/inactivate',
|
||||||
[param('id').exists().isNumeric().toInt()],
|
[param('id').exists().isNumeric().toInt()],
|
||||||
this.validationResult,
|
this.validationResult,
|
||||||
this.asyncMiddleware(this.inactivateContact.bind(this)),
|
this.asyncMiddleware(this.inactivateContact.bind(this)),
|
||||||
this.handlerServiceErrors
|
this.handlerServiceErrors,
|
||||||
);
|
);
|
||||||
router.post(
|
router.post(
|
||||||
'/:id/activate',
|
'/:id/activate',
|
||||||
[param('id').exists().isNumeric().toInt()],
|
[param('id').exists().isNumeric().toInt()],
|
||||||
this.validationResult,
|
this.validationResult,
|
||||||
this.asyncMiddleware(this.activateContact.bind(this)),
|
this.asyncMiddleware(this.activateContact.bind(this)),
|
||||||
this.handlerServiceErrors
|
this.handlerServiceErrors,
|
||||||
);
|
);
|
||||||
return router;
|
return router;
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ export default class ContactsController extends BaseController {
|
|||||||
try {
|
try {
|
||||||
const contact = await this.contactsService.getContact(
|
const contact = await this.contactsService.getContact(
|
||||||
tenantId,
|
tenantId,
|
||||||
contactId
|
contactId,
|
||||||
);
|
);
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
customer: this.transfromToResponse(contact),
|
customer: this.transfromToResponse(contact),
|
||||||
@@ -105,7 +105,7 @@ export default class ContactsController extends BaseController {
|
|||||||
try {
|
try {
|
||||||
const contacts = await this.contactsService.autocompleteContacts(
|
const contacts = await this.contactsService.autocompleteContacts(
|
||||||
tenantId,
|
tenantId,
|
||||||
filter
|
filter,
|
||||||
);
|
);
|
||||||
return res.status(200).send({ contacts });
|
return res.status(200).send({ contacts });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -153,7 +153,6 @@ export default class ContactsController extends BaseController {
|
|||||||
check('email')
|
check('email')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isString()
|
.isString()
|
||||||
.normalizeEmail()
|
|
||||||
.isEmail()
|
.isEmail()
|
||||||
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('website')
|
check('website')
|
||||||
@@ -380,7 +379,7 @@ export default class ContactsController extends BaseController {
|
|||||||
error: Error,
|
error: Error,
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction,
|
||||||
) {
|
) {
|
||||||
if (error instanceof ServiceError) {
|
if (error instanceof ServiceError) {
|
||||||
if (error.errorType === 'contact_not_found') {
|
if (error.errorType === 'contact_not_found') {
|
||||||
|
|||||||
@@ -560,6 +560,16 @@ export default class BillsController extends BaseController {
|
|||||||
errors: [{ type: 'ITEM_ENTRY_TAX_RATE_ID_NOT_FOUND', code: 1900 }],
|
errors: [{ type: 'ITEM_ENTRY_TAX_RATE_ID_NOT_FOUND', code: 1900 }],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (error.errorType === 'BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT') {
|
||||||
|
return res.boom.badRequest(null, {
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
type: 'BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT',
|
||||||
|
code: 2000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export class CreditNoteTransformer extends Transformer {
|
|||||||
'formattedCreditNoteDate',
|
'formattedCreditNoteDate',
|
||||||
'formattedAmount',
|
'formattedAmount',
|
||||||
'formattedCreditsUsed',
|
'formattedCreditsUsed',
|
||||||
|
'formattedSubtotal',
|
||||||
'entries',
|
'entries',
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -60,6 +61,15 @@ export class CreditNoteTransformer extends Transformer {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the formatted subtotal.
|
||||||
|
* @param {ICreditNote} credit
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected formattedSubtotal = (credit): string => {
|
||||||
|
return formatNumber(credit.amount, { money: false });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the entries of the credit note.
|
* Retrieves the entries of the credit note.
|
||||||
* @param {ICreditNote} credit
|
* @param {ICreditNote} credit
|
||||||
|
|||||||
@@ -252,10 +252,6 @@ export default class TrialBalanceSheet extends FinancialSheet {
|
|||||||
* @return {ITrialBalanceSheetData}
|
* @return {ITrialBalanceSheetData}
|
||||||
*/
|
*/
|
||||||
public reportData(): ITrialBalanceSheetData {
|
public reportData(): ITrialBalanceSheetData {
|
||||||
// Don't return noting if the journal has no transactions.
|
|
||||||
if (this.repository.totalAccountsLedger.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Retrieve accounts nodes.
|
// Retrieve accounts nodes.
|
||||||
const accounts = this.accountsSection(this.repository.accounts);
|
const accounts = this.accountsSection(this.repository.accounts);
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export class TrialBalanceSheetTable extends R.compose(
|
|||||||
*/
|
*/
|
||||||
public tableRows = (): ITableRow[] => {
|
public tableRows = (): ITableRow[] => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.append(this.totalTableRow()),
|
R.unless(R.isEmpty, R.append(this.totalTableRow())),
|
||||||
R.concat(this.accountsTableRows())
|
R.concat(this.accountsTableRows())
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
import TenancyService from '@/services/Tenancy/TenancyService';
|
import TenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { ServiceError } from '@/exceptions';
|
import { ServiceError } from '@/exceptions';
|
||||||
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
|
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
|
||||||
import { BillPayment } from '@/models';
|
|
||||||
import { ERRORS } from './constants';
|
import { ERRORS } from './constants';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -18,19 +17,6 @@ export class BillPaymentValidators {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private tenancy: TenancyService;
|
private tenancy: TenancyService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the payment existance.
|
|
||||||
* @param {BillPayment | undefined | null} payment
|
|
||||||
* @throws {ServiceError(ERRORS.PAYMENT_MADE_NOT_FOUND)}
|
|
||||||
*/
|
|
||||||
public async validateBillPaymentExistance(
|
|
||||||
payment: BillPayment | undefined | null
|
|
||||||
) {
|
|
||||||
if (!payment) {
|
|
||||||
throw new ServiceError(ERRORS.PAYMENT_MADE_NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the bill payment existance.
|
* Validates the bill payment existance.
|
||||||
* @param {Request} req
|
* @param {Request} req
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import UnitOfWork from '@/services/UnitOfWork';
|
import UnitOfWork from '@/services/UnitOfWork';
|
||||||
import { BillPaymentValidators } from './BillPaymentValidators';
|
|
||||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
@@ -21,9 +20,6 @@ export class DeleteBillPayment {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private uow: UnitOfWork;
|
private uow: UnitOfWork;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private validators: BillPaymentValidators;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the bill payment and associated transactions.
|
* Deletes the bill payment and associated transactions.
|
||||||
* @param {number} tenantId - Tenant id.
|
* @param {number} tenantId - Tenant id.
|
||||||
@@ -36,10 +32,8 @@ export class DeleteBillPayment {
|
|||||||
// Retrieve the bill payment or throw not found service error.
|
// Retrieve the bill payment or throw not found service error.
|
||||||
const oldBillPayment = await BillPayment.query()
|
const oldBillPayment = await BillPayment.query()
|
||||||
.withGraphFetched('entries')
|
.withGraphFetched('entries')
|
||||||
.findById(billPaymentId);
|
.findById(billPaymentId)
|
||||||
|
.throwIfNotFound();
|
||||||
// Validates the bill payment existance.
|
|
||||||
this.validators.validateBillPaymentExistance(oldBillPayment);
|
|
||||||
|
|
||||||
// Deletes the bill transactions with associated transactions under
|
// Deletes the bill transactions with associated transactions under
|
||||||
// unit-of-work envirement.
|
// unit-of-work envirement.
|
||||||
|
|||||||
@@ -57,12 +57,12 @@ export class EditBillPayment {
|
|||||||
|
|
||||||
const tenantMeta = await TenantMetadata.query().findOne({ tenantId });
|
const tenantMeta = await TenantMetadata.query().findOne({ tenantId });
|
||||||
|
|
||||||
const oldBillPayment = await BillPayment.query().findById(billPaymentId);
|
const oldBillPayment = await BillPayment.query()
|
||||||
|
.findById(billPaymentId)
|
||||||
|
.withGraphFetched('entries')
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
// Validates the bill payment existance.
|
// Retrieves the bill payment vendor or throw not found error.
|
||||||
this.validators.validateBillPaymentExistance(oldBillPayment);
|
|
||||||
|
|
||||||
//
|
|
||||||
const vendor = await Contact.query()
|
const vendor = await Contact.query()
|
||||||
.modify('vendor')
|
.modify('vendor')
|
||||||
.findById(billPaymentDTO.vendorId)
|
.findById(billPaymentDTO.vendorId)
|
||||||
@@ -126,7 +126,7 @@ export class EditBillPayment {
|
|||||||
trx,
|
trx,
|
||||||
} as IBillPaymentEditingPayload);
|
} as IBillPaymentEditingPayload);
|
||||||
|
|
||||||
// Deletes the bill payment transaction graph from the storage.
|
// Edits the bill payment transaction graph on the storage.
|
||||||
const billPayment = await BillPayment.query(trx).upsertGraphAndFetch({
|
const billPayment = await BillPayment.query(trx).upsertGraphAndFetch({
|
||||||
id: billPaymentId,
|
id: billPaymentId,
|
||||||
...billPaymentObj,
|
...billPaymentObj,
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import { IBillPayment } from '@/interfaces';
|
import { IBillPayment } from '@/interfaces';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { ERRORS } from './constants';
|
|
||||||
import { ServiceError } from '@/exceptions';
|
|
||||||
import { BillPaymentTransformer } from './BillPaymentTransformer';
|
import { BillPaymentTransformer } from './BillPaymentTransformer';
|
||||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||||
import { BillsValidators } from '../Bills/BillsValidators';
|
|
||||||
import { BillPaymentValidators } from './BillPaymentValidators';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class GetBillPayment {
|
export class GetBillPayment {
|
||||||
@@ -16,9 +12,6 @@ export class GetBillPayment {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private transformer: TransformerInjectable;
|
private transformer: TransformerInjectable;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private validators: BillPaymentValidators;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve bill payment.
|
* Retrieve bill payment.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -37,10 +30,8 @@ export class GetBillPayment {
|
|||||||
.withGraphFetched('paymentAccount')
|
.withGraphFetched('paymentAccount')
|
||||||
.withGraphFetched('transactions')
|
.withGraphFetched('transactions')
|
||||||
.withGraphFetched('branch')
|
.withGraphFetched('branch')
|
||||||
.findById(billPyamentId);
|
.findById(billPyamentId)
|
||||||
|
.throwIfNotFound();
|
||||||
// Validates the bill payment existance.
|
|
||||||
this.validators.validateBillPaymentExistance(billPayment);
|
|
||||||
|
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
tenantId,
|
tenantId,
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ export class GetPaymentBills {
|
|||||||
public async getPaymentBills(tenantId: number, billPaymentId: number) {
|
public async getPaymentBills(tenantId: number, billPaymentId: number) {
|
||||||
const { Bill, BillPayment } = this.tenancy.models(tenantId);
|
const { Bill, BillPayment } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const billPayment = await BillPayment.query().findById(billPaymentId);
|
const billPayment = await BillPayment.query()
|
||||||
|
.findById(billPaymentId)
|
||||||
// Validates the bill payment existance.
|
.throwIfNotFound();
|
||||||
this.validators.validateBillPaymentExistance(billPayment);
|
|
||||||
|
|
||||||
const paymentBillsIds = billPayment.entries.map((entry) => entry.id);
|
const paymentBillsIds = billPayment.entries.map((entry) => entry.id);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,20 @@ export class BillsValidators {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the bill amount is bigger than paid amount.
|
||||||
|
* @param {number} billAmount
|
||||||
|
* @param {number} paidAmount
|
||||||
|
*/
|
||||||
|
public validateBillAmountBiggerPaidAmount(
|
||||||
|
billAmount: number,
|
||||||
|
paidAmount: number,
|
||||||
|
) {
|
||||||
|
if (billAmount < paidAmount) {
|
||||||
|
throw new ServiceError(ERRORS.BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the bill number existance.
|
* Validates the bill number existance.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export class EditBill {
|
|||||||
tenantId,
|
tenantId,
|
||||||
billDTO.entries
|
billDTO.entries
|
||||||
);
|
);
|
||||||
|
|
||||||
// Transforms the bill DTO to model object.
|
// Transforms the bill DTO to model object.
|
||||||
const billObj = await this.transformerDTO.billDTOToModel(
|
const billObj = await this.transformerDTO.billDTOToModel(
|
||||||
tenantId,
|
tenantId,
|
||||||
@@ -111,6 +112,11 @@ export class EditBill {
|
|||||||
authorizedUser,
|
authorizedUser,
|
||||||
oldBill
|
oldBill
|
||||||
);
|
);
|
||||||
|
// Validate bill total amount should be bigger than paid amount.
|
||||||
|
this.validators.validateBillAmountBiggerPaidAmount(
|
||||||
|
billObj.amount,
|
||||||
|
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.entriesService.validateLandedCostEntriesNotDeleted(
|
||||||
oldBill.entries,
|
oldBill.entries,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export const ERRORS = {
|
|||||||
LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS:
|
LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS:
|
||||||
'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS',
|
'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS',
|
||||||
BILL_HAS_APPLIED_TO_VENDOR_CREDIT: 'BILL_HAS_APPLIED_TO_VENDOR_CREDIT',
|
BILL_HAS_APPLIED_TO_VENDOR_CREDIT: 'BILL_HAS_APPLIED_TO_VENDOR_CREDIT',
|
||||||
|
BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT: 'BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_VIEW_COLUMNS = [];
|
export const DEFAULT_VIEW_COLUMNS = [];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export class VendorCreditTransformer extends Transformer {
|
|||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return [
|
return [
|
||||||
'formattedAmount',
|
'formattedAmount',
|
||||||
|
'formattedSubtotal',
|
||||||
'formattedVendorCreditDate',
|
'formattedVendorCreditDate',
|
||||||
'formattedCreditsRemaining',
|
'formattedCreditsRemaining',
|
||||||
'entries',
|
'entries',
|
||||||
@@ -37,6 +38,15 @@ export class VendorCreditTransformer extends Transformer {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the vendor credit formatted subtotal.
|
||||||
|
* @param {IVendorCredit} vendorCredit
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected formattedSubtotal = (vendorCredit): string => {
|
||||||
|
return formatNumber(vendorCredit.amount, { money: false });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted credits remaining.
|
* Retrieve formatted credits remaining.
|
||||||
* @param {IVendorCredit} credit
|
* @param {IVendorCredit} credit
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export class SaleEstimateTransfromer extends Transformer {
|
|||||||
*/
|
*/
|
||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return [
|
return [
|
||||||
|
'formattedSubtotal',
|
||||||
'formattedAmount',
|
'formattedAmount',
|
||||||
'formattedEstimateDate',
|
'formattedEstimateDate',
|
||||||
'formattedExpirationDate',
|
'formattedExpirationDate',
|
||||||
@@ -76,6 +77,15 @@ export class SaleEstimateTransfromer extends Transformer {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the formatted invoice subtotal.
|
||||||
|
* @param {ISaleEstimate} estimate
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected formattedSubtotal = (estimate: ISaleEstimate): string => {
|
||||||
|
return formatNumber(estimate.amount, { money: false });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the entries of the sale estimate.
|
* Retrieves the entries of the sale estimate.
|
||||||
* @param {ISaleEstimate} estimate
|
* @param {ISaleEstimate} estimate
|
||||||
|
|||||||
@@ -8,7 +8,16 @@ export class ItemEntryTransformer extends Transformer {
|
|||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return ['rateFormatted', 'totalFormatted'];
|
return ['quantityFormatted', 'rateFormatted', 'totalFormatted'];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the formatted quantitty of item entry.
|
||||||
|
* @param {IItemEntry} entry
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected quantityFormatted = (entry: IItemEntry): string => {
|
||||||
|
return formatNumber(entry.quantity, { money: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ export class EditPaymentReceive {
|
|||||||
// Validate the payment receive existance.
|
// Validate the payment receive existance.
|
||||||
const oldPaymentReceive = await PaymentReceive.query()
|
const oldPaymentReceive = await PaymentReceive.query()
|
||||||
.withGraphFetched('entries')
|
.withGraphFetched('entries')
|
||||||
.findById(paymentReceiveId);
|
.findById(paymentReceiveId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
// Validates the payment existance.
|
// Validates the payment existance.
|
||||||
this.validators.validatePaymentExistance(oldPaymentReceive);
|
this.validators.validatePaymentExistance(oldPaymentReceive);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export class PaymentReceiveTransfromer extends Transformer {
|
|||||||
*/
|
*/
|
||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return [
|
return [
|
||||||
|
'subtotalFormatted',
|
||||||
'formattedPaymentDate',
|
'formattedPaymentDate',
|
||||||
'formattedAmount',
|
'formattedAmount',
|
||||||
'formattedExchangeRate',
|
'formattedExchangeRate',
|
||||||
@@ -26,6 +27,18 @@ export class PaymentReceiveTransfromer extends Transformer {
|
|||||||
return this.formatDate(payment.paymentDate);
|
return this.formatDate(payment.paymentDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the formatted payment subtotal.
|
||||||
|
* @param {IPaymentReceive} payment
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected subtotalFormatted = (payment: IPaymentReceive): string => {
|
||||||
|
return formatNumber(payment.amount, {
|
||||||
|
currencyCode: payment.currencyCode,
|
||||||
|
money: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted payment amount.
|
* Retrieve formatted payment amount.
|
||||||
* @param {ISaleInvoice} invoice
|
* @param {ISaleInvoice} invoice
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export class SaleReceiptTransformer extends Transformer {
|
|||||||
*/
|
*/
|
||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return [
|
return [
|
||||||
|
'formattedSubtotal',
|
||||||
'formattedAmount',
|
'formattedAmount',
|
||||||
'formattedReceiptDate',
|
'formattedReceiptDate',
|
||||||
'formattedClosedAtDate',
|
'formattedClosedAtDate',
|
||||||
@@ -37,6 +38,15 @@ export class SaleReceiptTransformer extends Transformer {
|
|||||||
return this.formatDate(receipt.closedAt);
|
return this.formatDate(receipt.closedAt);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the estimate formatted subtotal.
|
||||||
|
* @param {ISaleReceipt} receipt
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected formattedSubtotal = (receipt: ISaleReceipt): string => {
|
||||||
|
return formatNumber(receipt.amount, { money: false });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted invoice amount.
|
* Retrieve formatted invoice amount.
|
||||||
* @param {ISaleReceipt} estimate
|
* @param {ISaleReceipt} estimate
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function DetailItem({ label, children, name, align, className }) {
|
|||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item__content">{children}</div>
|
<div>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ export const ERROR = {
|
|||||||
SALE_INVOICE_NO_NOT_UNIQUE: 'SALE_INVOICE_NO_NOT_UNIQUE',
|
SALE_INVOICE_NO_NOT_UNIQUE: 'SALE_INVOICE_NO_NOT_UNIQUE',
|
||||||
SALE_ESTIMATE_IS_ALREADY_CONVERTED_TO_INVOICE:
|
SALE_ESTIMATE_IS_ALREADY_CONVERTED_TO_INVOICE:
|
||||||
'SALE_ESTIMATE_IS_ALREADY_CONVERTED_TO_INVOICE',
|
'SALE_ESTIMATE_IS_ALREADY_CONVERTED_TO_INVOICE',
|
||||||
|
INVOICE_AMOUNT_SMALLER_THAN_PAYMENT_AMOUNT:
|
||||||
|
'INVOICE_AMOUNT_SMALLER_THAN_PAYMENT_AMOUNT',
|
||||||
|
|
||||||
// Sales Receipts
|
// Sales Receipts
|
||||||
SALE_RECEIPT_NUMBER_NOT_UNIQUE: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE',
|
SALE_RECEIPT_NUMBER_NOT_UNIQUE: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE',
|
||||||
@@ -17,6 +19,6 @@ export const ERROR = {
|
|||||||
// Bills
|
// Bills
|
||||||
BILL_NUMBER_EXISTS: 'BILL.NUMBER.EXISTS',
|
BILL_NUMBER_EXISTS: 'BILL.NUMBER.EXISTS',
|
||||||
SALE_INVOICE_NO_IS_REQUIRED: 'SALE_INVOICE_NO_IS_REQUIRED',
|
SALE_INVOICE_NO_IS_REQUIRED: 'SALE_INVOICE_NO_IS_REQUIRED',
|
||||||
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:"ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED",
|
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
|
||||||
|
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function LoginFooterLinks() {
|
|||||||
<AuthFooterLinks>
|
<AuthFooterLinks>
|
||||||
{!signupDisabled && (
|
{!signupDisabled && (
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
Don't have an account? <Link to={'/auth/register'}>Sign up</Link>
|
<T id={'dont_have_an_account'} /> <Link to={'/auth/register'}><T id={'sign_up'} /></Link>
|
||||||
</AuthFooterLink>
|
</AuthFooterLink>
|
||||||
)}
|
)}
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ function RegisterFooterLinks() {
|
|||||||
return (
|
return (
|
||||||
<AuthFooterLinks>
|
<AuthFooterLinks>
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
Return to <Link to={'/auth/login'}>Sign In</Link>
|
<T id={'return_to'} /> <Link to={'/auth/login'}><T id={'sign_in'} /></Link>
|
||||||
</AuthFooterLink>
|
</AuthFooterLink>
|
||||||
|
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Formik } from 'formik';
|
|||||||
import { Intent, Position } from '@blueprintjs/core';
|
import { Intent, Position } from '@blueprintjs/core';
|
||||||
import { Link, useParams, useHistory } from 'react-router-dom';
|
import { Link, useParams, useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { AppToaster } from '@/components';
|
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||||
import { useAuthResetPassword } from '@/hooks/query';
|
import { useAuthResetPassword } from '@/hooks/query';
|
||||||
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
||||||
|
|
||||||
@@ -86,11 +86,11 @@ function ResetPasswordFooterLinks() {
|
|||||||
<AuthFooterLinks>
|
<AuthFooterLinks>
|
||||||
{!signupDisabled && (
|
{!signupDisabled && (
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
Don't have an account? <Link to={'/auth/register'}>Sign up</Link>
|
<T id={'dont_have_an_account'} /> <Link to={'/auth/register'}><T id={'sign_up'} /></Link>
|
||||||
</AuthFooterLink>
|
</AuthFooterLink>
|
||||||
)}
|
)}
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
Return to <Link to={'/auth/login'}>Sign In</Link>
|
<T id={'return_to'} /> <Link to={'/auth/login'}><T id={'sign_in'} /></Link>
|
||||||
</AuthFooterLink>
|
</AuthFooterLink>
|
||||||
</AuthFooterLinks>
|
</AuthFooterLinks>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Formik } from 'formik';
|
|||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
|
||||||
import { AppToaster } from '@/components';
|
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||||
import { useAuthSendResetPassword } from '@/hooks/query';
|
import { useAuthSendResetPassword } from '@/hooks/query';
|
||||||
|
|
||||||
import SendResetPasswordForm from './SendResetPasswordForm';
|
import SendResetPasswordForm from './SendResetPasswordForm';
|
||||||
@@ -82,11 +82,11 @@ function SendResetPasswordFooterLinks() {
|
|||||||
<AuthFooterLinks>
|
<AuthFooterLinks>
|
||||||
{!signupDisabled && (
|
{!signupDisabled && (
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
Don't have an account? <Link to={'/auth/register'}>Sign up</Link>
|
<T id={'dont_have_an_account'} /> <Link to={'/auth/register'}><T id={'sign_up'} /></Link>
|
||||||
</AuthFooterLink>
|
</AuthFooterLink>
|
||||||
)}
|
)}
|
||||||
<AuthFooterLink>
|
<AuthFooterLink>
|
||||||
Return to <Link to={'/auth/login'}>Sign In</Link>
|
<T id={'return_to'} /> <Link to={'/auth/login'}><T id={'sign_in'} /></Link>
|
||||||
</AuthFooterLink>
|
</AuthFooterLink>
|
||||||
</AuthFooterLinks>
|
</AuthFooterLinks>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ export default function SendResetPasswordForm({ isSubmitting }) {
|
|||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<TopParagraph>
|
<TopParagraph>
|
||||||
Enter the email address associated with your account and we'll send you
|
<T id={'enter_the_email_address_associated_with_your_account'} />
|
||||||
a link to reset your password.
|
|
||||||
</TopParagraph>
|
</TopParagraph>
|
||||||
|
|
||||||
<FFormGroup name={'crediential'} label={<T id={'email_address'} />}>
|
<FFormGroup name={'crediential'} label={<T id={'email_address'} />}>
|
||||||
@@ -29,7 +28,7 @@ export default function SendResetPasswordForm({ isSubmitting }) {
|
|||||||
large={true}
|
large={true}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
>
|
>
|
||||||
Reset Password
|
<T id={'reset_password'} />
|
||||||
</AuthSubmitButton>
|
</AuthSubmitButton>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
T,
|
T,
|
||||||
TotalLines,
|
TotalLines,
|
||||||
TotalLine,
|
TotalLine,
|
||||||
FormatNumber,
|
|
||||||
TotalLineBorderStyle,
|
TotalLineBorderStyle,
|
||||||
TotalLineTextStyle,
|
TotalLineTextStyle,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
@@ -23,7 +20,7 @@ export default function CreditNoteDetailTableFooter() {
|
|||||||
<CreditNoteTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<CreditNoteTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'credit_note.drawer.label_subtotal'} />}
|
title={<T id={'credit_note.drawer.label_subtotal'} />}
|
||||||
value={<FormatNumber value={creditNote.formatted_amount} />}
|
value={creditNote.formatted_subtotal}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'credit_note.drawer.label_total'} />}
|
title={<T id={'credit_note.drawer.label_total'} />}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
TotalLine,
|
TotalLine,
|
||||||
TotalLineBorderStyle,
|
TotalLineBorderStyle,
|
||||||
TotalLineTextStyle,
|
TotalLineTextStyle,
|
||||||
FormatNumber,
|
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ export default function EstimateDetailTableFooter() {
|
|||||||
<EstimateTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<EstimateTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'estimate.details.subtotal'} />}
|
title={<T id={'estimate.details.subtotal'} />}
|
||||||
value={<FormatNumber value={estimate.amount} />}
|
value={estimate.formatted_subtotal}
|
||||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { getColumnWidth } from '@/utils';
|
import { getColumnWidth } from '@/utils';
|
||||||
import { FormatNumberCell, TextOverviewTooltipCell } from '@/components';
|
import { TextOverviewTooltipCell } from '@/components';
|
||||||
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,9 +35,8 @@ export const useEstimateReadonlyEntriesColumns = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: intl.get('quantity'),
|
Header: intl.get('quantity'),
|
||||||
accessor: 'quantity',
|
accessor: 'quantity_formatted',
|
||||||
Cell: FormatNumberCell,
|
width: getColumnWidth(entries, 'quantity_formatted', {
|
||||||
width: getColumnWidth(entries, 'quantity', {
|
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
magicSpacing: 5,
|
magicSpacing: 5,
|
||||||
}),
|
}),
|
||||||
@@ -59,7 +58,6 @@ export const useEstimateReadonlyEntriesColumns = () => {
|
|||||||
{
|
{
|
||||||
Header: intl.get('amount'),
|
Header: intl.get('amount'),
|
||||||
accessor: 'total_formatted',
|
accessor: 'total_formatted',
|
||||||
Cell: FormatNumberCell,
|
|
||||||
width: getColumnWidth(entries, 'total_formatted', {
|
width: getColumnWidth(entries, 'total_formatted', {
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
magicSpacing: 5,
|
magicSpacing: 5,
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ import React from 'react';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FormatNumber,
|
T,
|
||||||
TotalLineTextStyle,
|
TotalLineTextStyle,
|
||||||
TotalLineBorderStyle,
|
TotalLineBorderStyle,
|
||||||
T,
|
|
||||||
TotalLine,
|
TotalLine,
|
||||||
TotalLines,
|
TotalLines,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
@@ -27,7 +26,7 @@ export default function PaymentReceiveDetailTableFooter() {
|
|||||||
>
|
>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'payment_receive.details.subtotal'} />}
|
title={<T id={'payment_receive.details.subtotal'} />}
|
||||||
value={<FormatNumber value={paymentReceive.amount} />}
|
value={paymentReceive.subtotal_formatted}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'payment_receive.details.total'} />}
|
title={<T id={'payment_receive.details.total'} />}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
Menu,
|
Menu,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { Icon, FormatNumberCell } from '@/components';
|
import { Icon } from '@/components';
|
||||||
import { getColumnWidth } from '@/utils';
|
import { getColumnWidth } from '@/utils';
|
||||||
import { usePaymentReceiveDetailContext } from './PaymentReceiveDetailProvider';
|
import { usePaymentReceiveDetailContext } from './PaymentReceiveDetailProvider';
|
||||||
|
|
||||||
@@ -40,9 +40,8 @@ export const usePaymentReceiveEntriesColumns = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: intl.get('invoice_amount'),
|
Header: intl.get('invoice_amount'),
|
||||||
accessor: 'invoice.balance',
|
accessor: 'invoice.total_formatted',
|
||||||
Cell: FormatNumberCell,
|
width: getColumnWidth(entries, 'invoice.total_formatted', {
|
||||||
width: getColumnWidth(entries, 'invoice.balance', {
|
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
magicSpacing: 5,
|
magicSpacing: 5,
|
||||||
}),
|
}),
|
||||||
@@ -51,10 +50,9 @@ export const usePaymentReceiveEntriesColumns = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: intl.get('amount_due'),
|
Header: intl.get('amount_due'),
|
||||||
accessor: 'invoice.due_amount',
|
accessor: 'invoice.due_amount_formatted',
|
||||||
Cell: FormatNumberCell,
|
|
||||||
align: 'right',
|
align: 'right',
|
||||||
width: getColumnWidth(entries, 'invoice.due_amount', {
|
width: getColumnWidth(entries, 'invoice.due_amount_formatted', {
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
magicSpacing: 5,
|
magicSpacing: 5,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default function ReceiptDetailTableFooter() {
|
|||||||
<ReceiptTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<ReceiptTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'receipt.details.subtotal'} />}
|
title={<T id={'receipt.details.subtotal'} />}
|
||||||
value={receipt.formatted_amount}
|
value={receipt.formatted_subtotal}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'receipt.details.total'} />}
|
title={<T id={'receipt.details.total'} />}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export const useJournalEntriesTransactionsColumns = () => {
|
|||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
Header: intl.get('date'),
|
Header: intl.get('date'),
|
||||||
accessor: 'date',
|
|
||||||
accessor: 'formatted_date',
|
accessor: 'formatted_date',
|
||||||
Cell: FormatDateCell,
|
Cell: FormatDateCell,
|
||||||
width: 140,
|
width: 140,
|
||||||
@@ -34,15 +33,17 @@ export const useJournalEntriesTransactionsColumns = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: intl.get('credit'),
|
Header: intl.get('credit'),
|
||||||
accessor: ({ credit }) => credit.formatted_amount,
|
accessor: 'credit.formatted_amount',
|
||||||
width: 100,
|
width: 100,
|
||||||
className: 'credit',
|
className: 'credit',
|
||||||
|
align: 'right',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: intl.get('debit'),
|
Header: intl.get('debit'),
|
||||||
accessor: ({ debit }) => debit.formatted_amount,
|
accessor: 'debit.formatted_amount',
|
||||||
width: 100,
|
width: 100,
|
||||||
className: 'debit',
|
className: 'debit',
|
||||||
|
align: 'right',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
TotalLine,
|
TotalLine,
|
||||||
TotalLineBorderStyle,
|
TotalLineBorderStyle,
|
||||||
TotalLineTextStyle,
|
TotalLineTextStyle,
|
||||||
FormatNumber,
|
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useVendorCreditDetailDrawerContext } from './VendorCreditDetailDrawerProvider';
|
import { useVendorCreditDetailDrawerContext } from './VendorCreditDetailDrawerProvider';
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ export default function VendorCreditDetailDrawerFooter() {
|
|||||||
<VendorCreditTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<VendorCreditTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'vendor_credit.drawer.label_subtotal'} />}
|
title={<T id={'vendor_credit.drawer.label_subtotal'} />}
|
||||||
value={vendorCredit.formatted_amount}
|
value={vendorCredit.formatted_subtotal}
|
||||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
|
|||||||
@@ -49,9 +49,8 @@ export const useVendorCreditReadonlyEntriesTableColumns = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: intl.get('quantity'),
|
Header: intl.get('quantity'),
|
||||||
accessor: 'quantity',
|
accessor: 'quantity_formatted',
|
||||||
Cell: FormatNumberCell,
|
width: getColumnWidth(entries, 'quantity_formatted', {
|
||||||
width: getColumnWidth(entries, 'quantity', {
|
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
magicSpacing: 5,
|
magicSpacing: 5,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export const ERRORS = {
|
|||||||
BILL_NUMBER_EXISTS: 'BILL.NUMBER.EXISTS',
|
BILL_NUMBER_EXISTS: 'BILL.NUMBER.EXISTS',
|
||||||
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
|
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
|
||||||
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
|
BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT: 'BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT',
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Transformes the bill to initial values of edit form.
|
* Transformes the bill to initial values of edit form.
|
||||||
@@ -200,6 +201,14 @@ export const handleErrors = (errors, { setErrors }) => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
errors.some((e) => e.type === ERRORS.BILL_AMOUNT_SMALLER_THAN_PAID_AMOUNT)
|
||||||
|
) {
|
||||||
|
AppToaster.show({
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
message: intl.get('bill.total_smaller_than_paid_amount'),
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSetPrimaryBranchToForm = () => {
|
export const useSetPrimaryBranchToForm = () => {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export default function PaymentMadeEntriesTable({
|
|||||||
// Formik context.
|
// Formik context.
|
||||||
const {
|
const {
|
||||||
values: { vendor_id },
|
values: { vendor_id },
|
||||||
|
errors,
|
||||||
} = useFormikContext();
|
} = useFormikContext();
|
||||||
|
|
||||||
// Handle update data.
|
// Handle update data.
|
||||||
@@ -63,7 +64,7 @@ export default function PaymentMadeEntriesTable({
|
|||||||
data={entries}
|
data={entries}
|
||||||
spinnerProps={false}
|
spinnerProps={false}
|
||||||
payload={{
|
payload={{
|
||||||
errors: [],
|
errors: errors?.entries || [],
|
||||||
updateData: handleUpdateData,
|
updateData: handleUpdateData,
|
||||||
currencyCode,
|
currencyCode,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -112,6 +112,16 @@ export const transformErrors = (errors, { setErrors }) => {
|
|||||||
intent: Intent.DANGER,
|
intent: Intent.DANGER,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
errors.some(
|
||||||
|
({ type }) => type === ERROR.INVOICE_AMOUNT_SMALLER_THAN_PAYMENT_AMOUNT,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
AppToaster.show({
|
||||||
|
message: intl.get('sale_invoice.total_smaller_than_paid_amount'),
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
errors.some((error) => error.type === ERROR.SALE_INVOICE_NO_IS_REQUIRED)
|
errors.some((error) => error.type === ERROR.SALE_INVOICE_NO_IS_REQUIRED)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export default function PaymentReceiveItemsTable({
|
|||||||
// Formik context.
|
// Formik context.
|
||||||
const {
|
const {
|
||||||
values: { customer_id },
|
values: { customer_id },
|
||||||
|
errors,
|
||||||
} = useFormikContext();
|
} = useFormikContext();
|
||||||
|
|
||||||
// No results message.
|
// No results message.
|
||||||
@@ -58,7 +59,7 @@ export default function PaymentReceiveItemsTable({
|
|||||||
data={entries}
|
data={entries}
|
||||||
spinnerProps={false}
|
spinnerProps={false}
|
||||||
payload={{
|
payload={{
|
||||||
errors: [],
|
errors: errors?.entries || [],
|
||||||
updateData: handleUpdateData,
|
updateData: handleUpdateData,
|
||||||
currencyCode,
|
currencyCode,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
"log_in": "تسجيل الدخول",
|
"log_in": "تسجيل الدخول",
|
||||||
"forget_my_password": "نسيت كلمة المرور الخاصة بي",
|
"forget_my_password": "نسيت كلمة المرور الخاصة بي",
|
||||||
"keep_me_logged_in": "تذكرني",
|
"keep_me_logged_in": "تذكرني",
|
||||||
|
"dont_have_an_account": "ليس لديك حساب؟",
|
||||||
|
"sign_up": "تسجيل",
|
||||||
|
"return_to": "عودة إلى",
|
||||||
|
"sign_in": "صفحة الدخول",
|
||||||
|
"enter_the_email_address_associated_with_your_account": "قم بادخال بريدك الإلكتروني المرتبط بالحساب وسوف نرسل لك رابط لاعادة تعيين كلمة المرور.",
|
||||||
"create_an_account": "إنشاء حساب",
|
"create_an_account": "إنشاء حساب",
|
||||||
"need_bigcapital_account": "تحتاج إلى حساب Bigcapital؟",
|
"need_bigcapital_account": "تحتاج إلى حساب Bigcapital؟",
|
||||||
"show": "عرض",
|
"show": "عرض",
|
||||||
|
|||||||
@@ -19,6 +19,11 @@
|
|||||||
"log_in": "Log in",
|
"log_in": "Log in",
|
||||||
"forget_my_password": "Forget my password",
|
"forget_my_password": "Forget my password",
|
||||||
"keep_me_logged_in": "Keep me logged in",
|
"keep_me_logged_in": "Keep me logged in",
|
||||||
|
"dont_have_an_account": "Don't have an account?",
|
||||||
|
"sign_up": "Sign up",
|
||||||
|
"return_to": "Return to",
|
||||||
|
"sign_in": "Sign In",
|
||||||
|
"enter_the_email_address_associated_with_your_account": "Enter the email address associated with your account and we'll send you a link to reset your password.",
|
||||||
"create_an_account": "Create an account",
|
"create_an_account": "Create an account",
|
||||||
"need_bigcapital_account": "Need a Bigcapital account ?",
|
"need_bigcapital_account": "Need a Bigcapital account ?",
|
||||||
"show": "Show",
|
"show": "Show",
|
||||||
@@ -653,7 +658,9 @@
|
|||||||
"invoice_number_is_not_unqiue": "Invoice number is not unqiue",
|
"invoice_number_is_not_unqiue": "Invoice number is not unqiue",
|
||||||
"sale_receipt_number_not_unique": "Receipt number is not unique",
|
"sale_receipt_number_not_unique": "Receipt number is not unique",
|
||||||
"sale_invoice_number_is_exists": "Sale invoice number is exists",
|
"sale_invoice_number_is_exists": "Sale invoice number is exists",
|
||||||
|
"sale_invoice.total_smaller_than_paid_amount": "The invoice total is smaller than the invoice paid amount.",
|
||||||
"bill_number_exists": "Bill number exists",
|
"bill_number_exists": "Bill number exists",
|
||||||
|
"bill.total_smaller_than_paid_amount": "The bill total is smaller than the bill paid amount.",
|
||||||
"ok": "Ok!",
|
"ok": "Ok!",
|
||||||
"quantity_cannot_be_zero_or_empty": "Quantity cannot be zero or empty.",
|
"quantity_cannot_be_zero_or_empty": "Quantity cannot be zero or empty.",
|
||||||
"customer_email": "Customer email",
|
"customer_email": "Customer email",
|
||||||
|
|||||||
Reference in New Issue
Block a user