Compare commits

...

6 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
53f37f4f48 Merge pull request #546 from bigcapitalhq/remove-views-tabs
feat: Remove the views tabs bar from all tables
2024-07-25 19:21:50 +02:00
Ahmed Bouhuolia
0a7b522b87 chore: remove unused import 2024-07-25 19:21:16 +02:00
Ahmed Bouhuolia
9e6500ac79 feat: remove the views tabs bar from all tables 2024-07-25 19:17:54 +02:00
Ahmed Bouhuolia
b93cb546f4 Merge pull request #545 from bigcapitalhq/excessed-payments-as-credit
Excessed payments as credit
2024-07-25 18:57:31 +02:00
Ahmed Bouhuolia
6d17f9cbeb feat: record excessed payments as credit 2024-07-25 18:46:24 +02:00
Ahmed Bouhuolia
fe214b1b2d feat: push CHANGELOG 2024-07-17 16:53:47 +02:00
48 changed files with 610 additions and 131 deletions

View File

@@ -2,6 +2,14 @@
All notable changes to Bigcapital server-side will be in this file.
## [v0.18.0] - 10-08-2024
* feat: Bank rules for automated categorization by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/511
* feat: Categorize & match bank transaction by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/511
* feat: Reconcile match transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/522
* fix: Issues in matching transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/523
* fix: Cashflow transactions types by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/524
## [v0.17.5] - 17-06-2024
* fix: Balance sheet and P/L nested accounts by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/501

View File

@@ -111,6 +111,7 @@ export default class BillsPayments extends BaseController {
check('vendor_id').exists().isNumeric().toInt(),
check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(),
check('amount').exists().isNumeric().toFloat(),
check('payment_account_id').exists().isNumeric().toInt(),
check('payment_number').optional({ nullable: true }).trim().escape(),
check('payment_date').exists(),
@@ -118,7 +119,7 @@ export default class BillsPayments extends BaseController {
check('reference').optional().trim().escape(),
check('branch_id').optional({ nullable: true }).isNumeric().toInt(),
check('entries').exists().isArray({ min: 1 }),
check('entries').exists().isArray(),
check('entries.*.index').optional().isNumeric().toInt(),
check('entries.*.bill_id').exists().isNumeric().toInt(),
check('entries.*.payment_amount').exists().isNumeric().toFloat(),

View File

@@ -150,6 +150,7 @@ export default class PaymentReceivesController extends BaseController {
check('customer_id').exists().isNumeric().toInt(),
check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(),
check('amount').exists().isNumeric().toFloat(),
check('payment_date').exists(),
check('reference_no').optional(),
check('deposit_account_id').exists().isNumeric().toInt(),
@@ -158,8 +159,7 @@ export default class PaymentReceivesController extends BaseController {
check('branch_id').optional({ nullable: true }).isNumeric().toInt(),
check('entries').isArray({ min: 1 }),
check('entries').isArray({}),
check('entries.*.id').optional({ nullable: true }).isNumeric().toInt(),
check('entries.*.index').optional().isNumeric().toInt(),
check('entries.*.invoice_id').exists().isNumeric().toInt(),

View File

@@ -12,8 +12,7 @@ export default class SeedAccounts extends TenantSeeder {
description: this.i18n.__(account.description),
currencyCode: this.tenant.metadata.baseCurrency,
seededAt: new Date(),
})
);
}));
return knex('accounts').then(async () => {
// Inserts seed entries.
return knex('accounts').insert(data);

View File

@@ -9,6 +9,28 @@ export const TaxPayableAccount = {
predefined: 1,
};
export const UnearnedRevenueAccount = {
name: 'Unearned Revenue',
slug: 'unearned-revenue',
account_type: 'other-current-liability',
parent_account_id: null,
code: '50005',
active: true,
index: 1,
predefined: true,
};
export const PrepardExpenses = {
name: 'Prepaid Expenses',
slug: 'prepaid-expenses',
account_type: 'other-current-asset',
parent_account_id: null,
code: '100010',
active: true,
index: 1,
predefined: true,
};
export default [
{
name: 'Bank Account',
@@ -323,4 +345,6 @@ export default [
index: 1,
predefined: 0,
},
UnearnedRevenueAccount,
PrepardExpenses,
];

View File

@@ -40,7 +40,7 @@ export interface ILedgerEntry {
date: Date | string;
transactionType: string;
transactionSubType: string;
transactionSubType?: string;
transactionId: number;

View File

@@ -525,9 +525,9 @@ export default class Bill extends mixin(TenantModel, [
return notFoundBillsIds;
}
static changePaymentAmount(billId, amount) {
static changePaymentAmount(billId, amount, trx) {
const changeMethod = amount > 0 ? 'increment' : 'decrement';
return this.query()
return this.query(trx)
.where('id', billId)
[changeMethod]('payment_amount', Math.abs(amount));
}

View File

@@ -2,7 +2,12 @@ import { Account } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
import { IAccount } from '@/interfaces';
import { Knex } from 'knex';
import { TaxPayableAccount } from '@/database/seeds/data/accounts';
import {
PrepardExpenses,
TaxPayableAccount,
UnearnedRevenueAccount,
} from '@/database/seeds/data/accounts';
import { TenantMetadata } from '@/system/models';
export default class AccountRepository extends TenantRepository {
/**
@@ -179,4 +184,67 @@ export default class AccountRepository extends TenantRepository {
}
return result;
};
/**
* Finds or creates the unearned revenue.
* @param {Record<string, string>} extraAttrs
* @param {Knex.Transaction} trx
* @returns
*/
public async findOrCreateUnearnedRevenue(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
// Retrieves the given tenant metadata.
const tenantMeta = await TenantMetadata.query().findOne({
tenantId: this.tenantId,
});
const _extraAttrs = {
currencyCode: tenantMeta.baseCurrency,
...extraAttrs,
};
let result = await this.model
.query(trx)
.findOne({ slug: UnearnedRevenueAccount.slug, ..._extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...UnearnedRevenueAccount,
..._extraAttrs,
});
}
return result;
}
/**
* Finds or creates the prepard expenses account.
* @param {Record<string, string>} extraAttrs
* @param {Knex.Transaction} trx
* @returns
*/
public async findOrCreatePrepardExpenses(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
// Retrieves the given tenant metadata.
const tenantMeta = await TenantMetadata.query().findOne({
tenantId: this.tenantId,
});
const _extraAttrs = {
currencyCode: tenantMeta.baseCurrency,
...extraAttrs,
};
let result = await this.model
.query(trx)
.findOne({ slug: PrepardExpenses.slug, ..._extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...PrepardExpenses,
..._extraAttrs,
});
}
return result;
}
}

View File

@@ -4,12 +4,17 @@ import CachableRepository from './CachableRepository';
export default class TenantRepository extends CachableRepository {
repositoryName: string;
tenantId: number;
/**
* Constructor method.
* @param {number} tenantId
* @param {number} tenantId
*/
constructor(knex, cache, i18n) {
super(knex, cache, i18n);
}
}
setTenantId(tenantId: number) {
this.tenantId = tenantId;
}
}

View File

@@ -45,9 +45,9 @@ export class CustomersApplication {
/**
* Creates a new customer.
* @param {number} tenantId
* @param {ICustomerNewDTO} customerDTO
* @param {ISystemUser} authorizedUser
* @param {number} tenantId
* @param {ICustomerNewDTO} customerDTO
* @param {ISystemUser} authorizedUser
* @returns {Promise<ICustomer>}
*/
public createCustomer = (tenantId: number, customerDTO: ICustomerNewDTO) => {
@@ -56,9 +56,9 @@ export class CustomersApplication {
/**
* Edits details of the given customer.
* @param {number} tenantId
* @param {number} customerId
* @param {ICustomerEditDTO} customerDTO
* @param {number} tenantId
* @param {number} customerId
* @param {ICustomerEditDTO} customerDTO
* @return {Promise<ICustomer>}
*/
public editCustomer = (
@@ -75,9 +75,9 @@ export class CustomersApplication {
/**
* Deletes the given customer and associated transactions.
* @param {number} tenantId
* @param {number} customerId
* @param {ISystemUser} authorizedUser
* @param {number} tenantId
* @param {number} customerId
* @param {ISystemUser} authorizedUser
* @returns {Promise<void>}
*/
public deleteCustomer = (
@@ -94,9 +94,9 @@ export class CustomersApplication {
/**
* Changes the opening balance of the given customer.
* @param {number} tenantId
* @param {number} customerId
* @param {Date|string} openingBalanceEditDTO
* @param {number} tenantId
* @param {number} customerId
* @param {Date|string} openingBalanceEditDTO
* @returns {Promise<ICustomer>}
*/
public editOpeningBalance = (

View File

@@ -4,6 +4,7 @@ import { omit, sumBy } from 'lodash';
import { IBillPayment, IBillPaymentDTO, IVendor } from '@/interfaces';
import { BranchTransactionDTOTransform } from '@/services/Branches/Integrations/BranchTransactionDTOTransform';
import { formatDateFields } from '@/utils';
import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service()
export class CommandBillPaymentDTOTransformer {
@@ -23,11 +24,14 @@ export class CommandBillPaymentDTOTransformer {
vendor: IVendor,
oldBillPayment?: IBillPayment
): Promise<IBillPayment> {
const amount =
billPaymentDTO.amount ?? sumBy(billPaymentDTO.entries, 'paymentAmount');
const initialDTO = {
...formatDateFields(omit(billPaymentDTO, ['attachments']), [
'paymentDate',
]),
amount: sumBy(billPaymentDTO.entries, 'paymentAmount'),
amount,
currencyCode: vendor.currencyCode,
exchangeRate: billPaymentDTO.exchangeRate || 1,
entries: billPaymentDTO.entries,

View File

@@ -36,7 +36,9 @@ export class PaymentReceiveDTOTransformer {
paymentReceiveDTO: IPaymentReceiveCreateDTO | IPaymentReceiveEditDTO,
oldPaymentReceive?: IPaymentReceive
): Promise<IPaymentReceive> {
const paymentAmount = sumBy(paymentReceiveDTO.entries, 'paymentAmount');
const amount =
paymentReceiveDTO.amount ??
sumBy(paymentReceiveDTO.entries, 'paymentAmount');
// Retreive the next invoice number.
const autoNextNumber =
@@ -54,7 +56,7 @@ export class PaymentReceiveDTOTransformer {
...formatDateFields(omit(paymentReceiveDTO, ['entries', 'attachments']), [
'paymentDate',
]),
amount: paymentAmount,
amount,
currencyCode: customer.currencyCode,
...(paymentReceiveNo ? { paymentReceiveNo } : {}),
exchangeRate: paymentReceiveDTO.exchangeRate || 1,

View File

@@ -77,7 +77,12 @@ export default class HasTenancyService {
const knex = this.knex(tenantId);
const i18n = this.i18n(tenantId);
return tenantRepositoriesLoader(knex, cache, i18n);
const repositories = tenantRepositoriesLoader(knex, cache, i18n);
Object.values(repositories).forEach((repository) => {
repository.setTenantId(tenantId);
});
return repositories;
});
}

View File

@@ -4,9 +4,9 @@ export const ACCOUNT_TYPE = {
BANK: 'bank',
ACCOUNTS_RECEIVABLE: 'accounts-receivable',
INVENTORY: 'inventory',
OTHER_CURRENT_ASSET: 'other-ACCOUNT_PARENT_TYPE.CURRENT_ASSET',
OTHER_CURRENT_ASSET: 'other-current-asset',
FIXED_ASSET: 'fixed-asset',
NON_CURRENT_ASSET: 'non-ACCOUNT_PARENT_TYPE.CURRENT_ASSET',
NON_CURRENT_ASSET: 'non-current-asset',
ACCOUNTS_PAYABLE: 'accounts-payable',
CREDIT_CARD: 'credit-card',

View File

@@ -7,7 +7,6 @@ import { DashboardPageContent } from '@/components';
import { transformTableStateToQuery, compose } from '@/utils';
import { ManualJournalsListProvider } from './ManualJournalsListProvider';
import ManualJournalsViewTabs from './ManualJournalsViewTabs';
import ManualJournalsDataTable from './ManualJournalsDataTable';
import ManualJournalsActionsBar from './ManualJournalActionsBar';
import withManualJournals from './withManualJournals';
@@ -29,7 +28,6 @@ function ManualJournalsTable({
<ManualJournalsActionsBar />
<DashboardPageContent>
<ManualJournalsViewTabs />
<ManualJournalsDataTable />
</DashboardPageContent>
</ManualJournalsListProvider>

View File

@@ -2,15 +2,15 @@
import React, { useEffect } from 'react';
import '@/style/pages/Accounts/List.scss';
import { DashboardPageContent, DashboardContentTable } from '@/components';
import { DashboardPageContent, DashboardContentTable } from '@/components';
import { AccountsChartProvider } from './AccountsChartProvider';
import AccountsViewsTabs from './AccountsViewsTabs';
import AccountsActionsBar from './AccountsActionsBar';
import AccountsDataTable from './AccountsDataTable';
import withAccounts from '@/containers/Accounts/withAccounts';
import withAccountsTableActions from './withAccountsTableActions';
import { transformAccountsStateToQuery } from './utils';
import { compose } from '@/utils';
@@ -41,8 +41,6 @@ function AccountsChart({
<AccountsActionsBar />
<DashboardPageContent>
<AccountsViewsTabs />
<DashboardContentTable>
<AccountsDataTable />
</DashboardContentTable>

View File

@@ -6,7 +6,6 @@ import '@/style/pages/Customers/List.scss';
import { DashboardPageContent } from '@/components';
import CustomersActionsBar from './CustomersActionsBar';
import CustomersViewsTabs from './CustomersViewsTabs';
import CustomersTable from './CustomersTable';
import { CustomersListProvider } from './CustomersListProvider';
@@ -42,7 +41,6 @@ function CustomersList({
<CustomersActionsBar />
<DashboardPageContent>
<CustomersViewsTabs />
<CustomersTable />
</DashboardPageContent>
</CustomersListProvider>

View File

@@ -6,7 +6,6 @@ import '@/style/pages/Expense/List.scss';
import { DashboardPageContent } from '@/components';
import ExpenseActionsBar from './ExpenseActionsBar';
import ExpenseViewTabs from './ExpenseViewTabs';
import ExpenseDataTable from './ExpenseDataTable';
import withExpenses from './withExpenses';
@@ -42,7 +41,6 @@ function ExpensesList({
<ExpenseActionsBar />
<DashboardPageContent>
<ExpenseViewTabs />
<ExpenseDataTable />
</DashboardPageContent>
</ExpensesListProvider>

View File

@@ -8,7 +8,6 @@ import { DashboardPageContent } from '@/components';
import { ItemsListProvider } from './ItemsListProvider';
import ItemsActionsBar from './ItemsActionsBar';
import ItemsViewsTabs from './ItemsViewsTabs';
import ItemsDataTable from './ItemsDataTable';
import withItems from './withItems';
@@ -41,7 +40,6 @@ function ItemsList({
<ItemsActionsBar />
<DashboardPageContent>
<ItemsViewsTabs />
<ItemsDataTable />
</DashboardPageContent>
</ItemsListProvider>

View File

@@ -7,7 +7,6 @@ import '@/style/pages/Bills/List.scss';
import { BillsListProvider } from './BillsListProvider';
import BillsActionsBar from './BillsActionsBar';
import BillsViewsTabs from './BillsViewsTabs';
import BillsTable from './BillsTable';
import withBills from './withBills';
@@ -42,7 +41,6 @@ function BillsList({
<BillsActionsBar />
<DashboardPageContent>
<BillsViewsTabs />
<BillsTable />
</DashboardPageContent>
</BillsListProvider>

View File

@@ -5,7 +5,6 @@ import '@/style/pages/VendorsCreditNote/List.scss';
import { DashboardPageContent } from '@/components';
import VendorsCreditNoteActionsBar from './VendorsCreditNoteActionsBar';
import VendorsCreditNoteViewTabs from './VendorsCreditNoteViewTabs';
import VendorsCreditNoteDataTable from './VendorsCreditNoteDataTable';
import withVendorsCreditNotes from './withVendorsCreditNotes';
@@ -37,7 +36,6 @@ function VendorsCreditNotesList({
>
<VendorsCreditNoteActionsBar />
<DashboardPageContent>
<VendorsCreditNoteViewTabs />
<VendorsCreditNoteDataTable />
</DashboardPageContent>
</VendorsCreditNoteListProvider>

View File

@@ -0,0 +1,9 @@
import { ExcessPaymentDialog } from './dialogs/PaymentMadeExcessDialog';
export function PaymentMadeDialogs() {
return (
<>
<ExcessPaymentDialog dialogName={'payment-made-excessed-payment'} />
</>
);
}

View File

@@ -2,7 +2,7 @@
import React, { useMemo } from 'react';
import intl from 'react-intl-universal';
import classNames from 'classnames';
import { Formik, Form } from 'formik';
import { Formik, Form, FormikHelpers } from 'formik';
import { Intent } from '@blueprintjs/core';
import { sumBy, defaultTo } from 'lodash';
import { useHistory } from 'react-router-dom';
@@ -14,6 +14,7 @@ import PaymentMadeFloatingActions from './PaymentMadeFloatingActions';
import PaymentMadeFooter from './PaymentMadeFooter';
import PaymentMadeFormBody from './PaymentMadeFormBody';
import PaymentMadeFormTopBar from './PaymentMadeFormTopBar';
import { PaymentMadeDialogs } from './PaymentMadeDialogs';
import { PaymentMadeInnerProvider } from './PaymentMadeInnerProvider';
import { usePaymentMadeFormContext } from './PaymentMadeFormProvider';
@@ -21,6 +22,7 @@ import { compose, orderingLinesIndexes } from '@/utils';
import withSettings from '@/containers/Settings/withSettings';
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import {
EditPaymentMadeFormSchema,
@@ -31,6 +33,7 @@ import {
transformToEditForm,
transformErrors,
transformFormToRequest,
getPaymentExcessAmountFromValues,
} from './utils';
/**
@@ -42,6 +45,9 @@ function PaymentMadeForm({
// #withCurrentOrganization
organization: { base_currency },
// #withDialogActions
openDialog,
}) {
const history = useHistory();
@@ -54,6 +60,7 @@ function PaymentMadeForm({
submitPayload,
createPaymentMadeMutate,
editPaymentMadeMutate,
isExcessConfirmed,
} = usePaymentMadeFormContext();
// Form initial values.
@@ -76,13 +83,11 @@ function PaymentMadeForm({
// Handle the form submit.
const handleSubmitForm = (
values,
{ setSubmitting, resetForm, setFieldError },
{ setSubmitting, resetForm, setFieldError }: FormikHelpers<any>,
) => {
setSubmitting(true);
// Total payment amount of entries.
const totalPaymentAmount = sumBy(values.entries, 'payment_amount');
if (totalPaymentAmount <= 0) {
if (values.amount <= 0) {
AppToaster.show({
message: intl.get('you_cannot_make_payment_with_zero_total_amount'),
intent: Intent.DANGER,
@@ -90,6 +95,16 @@ function PaymentMadeForm({
setSubmitting(false);
return;
}
const excessAmount = getPaymentExcessAmountFromValues(values);
// Show the confirmation popup if the excess amount bigger than zero and
// has not been confirmed yet.
if (excessAmount > 0 && !isExcessConfirmed) {
openDialog('payment-made-excessed-payment');
setSubmitting(false);
return;
}
// Transformes the form values to request body.
const form = transformFormToRequest(values);
@@ -119,11 +134,12 @@ function PaymentMadeForm({
}
setSubmitting(false);
};
if (!isNewMode) {
editPaymentMadeMutate([paymentMadeId, form]).then(onSaved).catch(onError);
return editPaymentMadeMutate([paymentMadeId, form])
.then(onSaved)
.catch(onError);
} else {
createPaymentMadeMutate(form).then(onSaved).catch(onError);
return createPaymentMadeMutate(form).then(onSaved).catch(onError);
}
};
@@ -149,6 +165,7 @@ function PaymentMadeForm({
<PaymentMadeFormBody />
<PaymentMadeFooter />
<PaymentMadeFloatingActions />
<PaymentMadeDialogs />
</PaymentMadeInnerProvider>
</Form>
</Formik>
@@ -163,4 +180,5 @@ export default compose(
preferredPaymentAccount: parseInt(billPaymentSettings?.withdrawalAccount),
})),
withCurrentOrganization(),
withDialogActions,
)(PaymentMadeForm);

View File

@@ -1,17 +1,23 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import { useFormikContext } from 'formik';
import {
T,
TotalLines,
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
FormatNumber,
} from '@/components';
import { usePaymentMadeTotals } from './utils';
import { usePaymentMadeExcessAmount, usePaymentMadeTotals } from './utils';
export function PaymentMadeFormFooterRight() {
const { formattedSubtotal, formattedTotal } = usePaymentMadeTotals();
const excessAmount = usePaymentMadeExcessAmount();
const {
values: { currency_code: currencyCode },
} = useFormikContext();
return (
<PaymentMadeTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
@@ -25,6 +31,11 @@ export function PaymentMadeFormFooterRight() {
value={formattedTotal}
textStyle={TotalLineTextStyle.Bold}
/>
<TotalLine
title={'Excess Amount'}
value={<FormatNumber value={excessAmount} currency={currencyCode} />}
textStyle={TotalLineTextStyle.Regular}
/>
</PaymentMadeTotalLines>
);
}

View File

@@ -1,12 +1,12 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import React from 'react';
import classNames from 'classnames';
import { useFormikContext } from 'formik';
import { sumBy } from 'lodash';
import { CLASSES } from '@/constants/classes';
import { Money, FormattedMessage as T } from '@/components';
import PaymentMadeFormHeaderFields from './PaymentMadeFormHeaderFields';
import { usePaymentmadeTotalAmount } from './utils';
/**
* Payment made header form.
@@ -14,11 +14,10 @@ import PaymentMadeFormHeaderFields from './PaymentMadeFormHeaderFields';
function PaymentMadeFormHeader() {
// Formik form context.
const {
values: { entries, currency_code },
values: { currency_code },
} = useFormikContext();
// Calculate the payment amount of the entries.
const amountPaid = useMemo(() => sumBy(entries, 'payment_amount'), [entries]);
const totalAmount = usePaymentmadeTotalAmount();
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
@@ -30,8 +29,9 @@ function PaymentMadeFormHeader() {
<span class="big-amount__label">
<T id={'amount_received'} />
</span>
<h1 class="big-amount__number">
<Money amount={amountPaid} currency={currency_code} />
<Money amount={totalAmount} currency={currency_code} />
</h1>
</div>
</div>

View File

@@ -2,6 +2,7 @@
import React, { useMemo } from 'react';
import styled from 'styled-components';
import classNames from 'classnames';
import { isEmpty, toSafeInteger } from 'lodash';
import {
FormGroup,
InputGroup,
@@ -13,7 +14,6 @@ import {
import { DateInput } from '@blueprintjs/datetime';
import { FastField, Field, useFormikContext, ErrorMessage } from 'formik';
import { FormattedMessage as T, VendorsSelect } from '@/components';
import { toSafeInteger } from 'lodash';
import { CLASSES } from '@/constants/classes';
import {
@@ -68,7 +68,7 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) {
const fullAmount = safeSumBy(newEntries, 'payment_amount');
setFieldValue('entries', newEntries);
setFieldValue('full_amount', fullAmount);
setFieldValue('amount', fullAmount);
};
// Handles the full-amount field blur.
@@ -115,10 +115,10 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) {
</FastField>
{/* ------------ Full amount ------------ */}
<Field name={'full_amount'}>
<Field name={'amount'}>
{({
form: {
values: { currency_code },
values: { currency_code, entries },
},
field: { value },
meta: { error, touched },
@@ -129,28 +129,30 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) {
className={('form-group--full-amount', Classes.FILL)}
intent={inputIntent({ error, touched })}
labelInfo={<Hint />}
helperText={<ErrorMessage name="full_amount" />}
helperText={<ErrorMessage name="amount" />}
>
<ControlGroup>
<InputPrependText text={currency_code} />
<MoneyInputGroup
value={value}
onChange={(value) => {
setFieldValue('full_amount', value);
setFieldValue('amount', value);
}}
onBlurValue={onFullAmountBlur}
/>
</ControlGroup>
<Button
onClick={handleReceiveFullAmountClick}
className={'receive-full-amount'}
small={true}
minimal={true}
>
<T id={'receive_full_amount'} /> (
<Money amount={payableFullAmount} currency={currency_code} />)
</Button>
{!isEmpty(entries) && (
<Button
onClick={handleReceiveFullAmountClick}
className={'receive-full-amount'}
small={true}
minimal={true}
>
<T id={'receive_full_amount'} /> (
<Money amount={payableFullAmount} currency={currency_code} />)
</Button>
)}
</FormGroup>
)}
</Field>

View File

@@ -1,5 +1,5 @@
// @ts-nocheck
import React, { createContext, useContext } from 'react';
import React, { createContext, useContext, useState } from 'react';
import { Features } from '@/constants';
import { useFeatureCan } from '@/hooks/state';
import {
@@ -71,6 +71,8 @@ function PaymentMadeFormProvider({ query, paymentMadeId, ...props }) {
const isFeatureLoading = isBranchesLoading;
const [isExcessConfirmed, setIsExcessConfirmed] = useState<boolean>(false);
// Provider payload.
const provider = {
paymentMadeId,
@@ -98,6 +100,9 @@ function PaymentMadeFormProvider({ query, paymentMadeId, ...props }) {
setSubmitPayload,
setPaymentVendorId,
isExcessConfirmed,
setIsExcessConfirmed,
};
return (

View File

@@ -0,0 +1,37 @@
// @ts-nocheck
import React from 'react';
import { Dialog, DialogSuspense } from '@/components';
import withDialogRedux from '@/components/DialogReduxConnect';
import { compose } from '@/utils';
const ExcessPaymentDialogContent = React.lazy(() =>
import('./PaymentMadeExcessDialogContent').then((module) => ({
default: module.ExcessPaymentDialogContent,
})),
);
/**
* Exess payment dialog of the payment made form.
*/
function ExcessPaymentDialogRoot({ dialogName, isOpen }) {
return (
<Dialog
name={dialogName}
title={'Excess Payment'}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
style={{ width: 500 }}
>
<DialogSuspense>
<ExcessPaymentDialogContent dialogName={dialogName} />
</DialogSuspense>
</Dialog>
);
}
export const ExcessPaymentDialog = compose(withDialogRedux())(
ExcessPaymentDialogRoot,
);
ExcessPaymentDialog.displayName = 'ExcessPaymentDialog';

View File

@@ -0,0 +1,93 @@
// @ts-nocheck
import * as R from 'ramda';
import React from 'react';
import { Button, Classes, Intent } from '@blueprintjs/core';
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
import { FormatNumber } from '@/components';
import { usePaymentMadeFormContext } from '../../PaymentMadeFormProvider';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { usePaymentMadeExcessAmount } from '../../utils';
interface ExcessPaymentValues {}
function ExcessPaymentDialogContentRoot({ dialogName, closeDialog }) {
const {
submitForm,
values: { currency_code: currencyCode },
} = useFormikContext();
const { setIsExcessConfirmed } = usePaymentMadeFormContext();
// Handles the form submitting.
const handleSubmit = (
values: ExcessPaymentValues,
{ setSubmitting }: FormikHelpers<ExcessPaymentValues>,
) => {
setSubmitting(true);
setIsExcessConfirmed(true);
return submitForm().then(() => {
setSubmitting(false);
closeDialog(dialogName);
});
};
// Handle close button click.
const handleCloseBtn = () => {
closeDialog(dialogName);
};
const excessAmount = usePaymentMadeExcessAmount();
return (
<Formik initialValues={{}} onSubmit={handleSubmit}>
<Form>
<ExcessPaymentDialogContentForm
excessAmount={
<FormatNumber value={excessAmount} currency={currencyCode} />
}
onClose={handleCloseBtn}
/>
</Form>
</Formik>
);
}
export const ExcessPaymentDialogContent = R.compose(withDialogActions)(
ExcessPaymentDialogContentRoot,
);
interface ExcessPaymentDialogContentFormProps {
excessAmount: string | number | React.ReactNode;
onClose?: () => void;
}
function ExcessPaymentDialogContentForm({
excessAmount,
onClose,
}: ExcessPaymentDialogContentFormProps) {
const { submitForm, isSubmitting } = useFormikContext();
const handleCloseBtn = () => {
onClose && onClose();
};
return (
<>
<div className={Classes.DIALOG_BODY}>
<p style={{ marginBottom: 20 }}>
Would you like to record the excess amount of{' '}
<strong>{excessAmount}</strong> as credit payment from the vendor.
</p>
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button
intent={Intent.PRIMARY}
loading={isSubmitting}
onClick={() => submitForm()}
>
Save Payment as Credit
</Button>
<Button onClick={handleCloseBtn}>Cancel</Button>
</div>
</div>
</>
);
}

View File

@@ -0,0 +1 @@
export * from './PaymentMadeExcessDialog';

View File

@@ -37,7 +37,7 @@ export const defaultPaymentMadeEntry = {
// Default initial values of payment made.
export const defaultPaymentMade = {
full_amount: '',
amount: '',
vendor_id: '',
payment_account_id: '',
payment_date: moment(new Date()).format('YYYY-MM-DD'),
@@ -53,10 +53,10 @@ export const defaultPaymentMade = {
export const transformToEditForm = (paymentMade, paymentMadeEntries) => {
const attachments = transformAttachmentsToForm(paymentMade);
const appliedAmount = safeSumBy(paymentMadeEntries, 'payment_amount');
return {
...transformToForm(paymentMade, defaultPaymentMade),
full_amount: safeSumBy(paymentMadeEntries, 'payment_amount'),
entries: [
...paymentMadeEntries.map((paymentMadeEntry) => ({
...transformToForm(paymentMadeEntry, defaultPaymentMadeEntry),
@@ -177,6 +177,30 @@ export const usePaymentMadeTotals = () => {
};
};
export const usePaymentmadeTotalAmount = () => {
const {
values: { amount },
} = useFormikContext();
return amount;
};
export const usePaymentMadeAppliedAmount = () => {
const {
values: { entries },
} = useFormikContext();
// Retrieves the invoice entries total.
return React.useMemo(() => sumBy(entries, 'payment_amount'), [entries]);
};
export const usePaymentMadeExcessAmount = () => {
const appliedAmount = usePaymentMadeAppliedAmount();
const totalAmount = usePaymentmadeTotalAmount();
return Math.abs(totalAmount - appliedAmount);
};
/**
* Detarmines whether the bill has foreign customer.
* @returns {boolean}
@@ -191,3 +215,10 @@ export const usePaymentMadeIsForeignCustomer = () => {
);
return isForeignCustomer;
};
export const getPaymentExcessAmountFromValues = (values) => {
const appliedAmount = sumBy(values.entries, 'payment_amount');
const totalAmount = values.amount;
return Math.abs(totalAmount - appliedAmount);
};

View File

@@ -7,7 +7,6 @@ import { DashboardPageContent } from '@/components';
import { PaymentMadesListProvider } from './PaymentMadesListProvider';
import PaymentMadeActionsBar from './PaymentMadeActionsBar';
import PaymentMadesTable from './PaymentMadesTable';
import PaymentMadeViewTabs from './PaymentMadeViewTabs';
import withPaymentMades from './withPaymentMade';
import withPaymentMadeActions from './withPaymentMadeActions';
@@ -41,7 +40,6 @@ function PaymentMadeList({
<PaymentMadeActionsBar />
<DashboardPageContent>
<PaymentMadeViewTabs />
<PaymentMadesTable />
</DashboardPageContent>
</PaymentMadesListProvider>

View File

@@ -5,7 +5,6 @@ import '@/style/pages/CreditNote/List.scss';
import { DashboardPageContent } from '@/components';
import CreditNotesActionsBar from './CreditNotesActionsBar';
import CreditNotesViewTabs from './CreditNotesViewTabs';
import CreditNotesDataTable from './CreditNotesDataTable';
import withCreditNotes from './withCreditNotes';
@@ -36,8 +35,8 @@ function CreditNotesList({
tableStateChanged={creditNoteTableStateChanged}
>
<CreditNotesActionsBar />
<DashboardPageContent>
<CreditNotesViewTabs />
<CreditNotesDataTable />
</DashboardPageContent>
</CreditNotesListProvider>

View File

@@ -1,11 +1,10 @@
// @ts-nocheck
import React from 'react';
import { DashboardContentTable, DashboardPageContent } from '@/components';
import { DashboardPageContent } from '@/components';
import '@/style/pages/SaleEstimate/List.scss';
import EstimatesActionsBar from './EstimatesActionsBar';
import EstimatesViewTabs from './EstimatesViewTabs';
import EstimatesDataTable from './EstimatesDataTable';
import withEstimates from './withEstimates';
@@ -41,7 +40,6 @@ function EstimatesList({
<EstimatesActionsBar />
<DashboardPageContent>
<EstimatesViewTabs />
<EstimatesDataTable />
</DashboardPageContent>
</EstimatesListProvider>

View File

@@ -6,7 +6,6 @@ import '@/style/pages/SaleInvoice/List.scss';
import { DashboardPageContent } from '@/components';
import { InvoicesListProvider } from './InvoicesListProvider';
import InvoiceViewTabs from './InvoiceViewTabs';
import InvoicesDataTable from './InvoicesDataTable';
import InvoicesActionsBar from './InvoicesActionsBar';
@@ -43,7 +42,6 @@ function InvoicesList({
<InvoicesActionsBar />
<DashboardPageContent>
<InvoiceViewTabs />
<InvoicesDataTable />
</DashboardPageContent>
</InvoicesListProvider>

View File

@@ -1,5 +1,5 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import React, { useMemo, useRef } from 'react';
import { sumBy, isEmpty, defaultTo } from 'lodash';
import intl from 'react-intl-universal';
import classNames from 'classnames';
@@ -21,6 +21,7 @@ import { PaymentReceiveInnerProvider } from './PaymentReceiveInnerProvider';
import withSettings from '@/containers/Settings/withSettings';
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import {
EditPaymentReceiveFormSchema,
@@ -36,6 +37,7 @@ import {
transformFormToRequest,
transformErrors,
resetFormState,
getExceededAmountFromValues,
} from './utils';
import { PaymentReceiveSyncIncrementSettingsToForm } from './components';
@@ -51,6 +53,9 @@ function PaymentReceiveForm({
// #withCurrentOrganization
organization: { base_currency },
// #withDialogActions
openDialog,
}) {
const history = useHistory();
@@ -63,6 +68,7 @@ function PaymentReceiveForm({
submitPayload,
editPaymentReceiveMutate,
createPaymentReceiveMutate,
isExcessConfirmed,
} = usePaymentReceiveFormContext();
// Payment receive number.
@@ -94,18 +100,16 @@ function PaymentReceiveForm({
preferredDepositAccount,
],
);
// Handle form submit.
const handleSubmitForm = (
values,
{ setSubmitting, resetForm, setFieldError },
) => {
setSubmitting(true);
const exceededAmount = getExceededAmountFromValues(values);
// Calculates the total payment amount of entries.
const totalPaymentAmount = sumBy(values.entries, 'payment_amount');
if (totalPaymentAmount <= 0) {
// Validates the amount should be bigger than zero.
if (values.amount <= 0) {
AppToaster.show({
message: intl.get('you_cannot_make_payment_with_zero_total_amount'),
intent: Intent.DANGER,
@@ -113,6 +117,13 @@ function PaymentReceiveForm({
setSubmitting(false);
return;
}
// Show the confirm popup if the excessed amount bigger than zero and
// excess confirmation has not been confirmed yet.
if (exceededAmount > 0 && !isExcessConfirmed) {
setSubmitting(false);
openDialog('payment-received-excessed-payment');
return;
}
// Transformes the form values to request body.
const form = transformFormToRequest(values);
@@ -148,11 +159,11 @@ function PaymentReceiveForm({
};
if (paymentReceiveId) {
editPaymentReceiveMutate([paymentReceiveId, form])
return editPaymentReceiveMutate([paymentReceiveId, form])
.then(onSaved)
.catch(onError);
} else {
createPaymentReceiveMutate(form).then(onSaved).catch(onError);
return createPaymentReceiveMutate(form).then(onSaved).catch(onError);
}
};
return (
@@ -202,4 +213,5 @@ export default compose(
preferredDepositAccount: paymentReceiveSettings?.preferredDepositAccount,
})),
withCurrentOrganization(),
withDialogActions,
)(PaymentReceiveForm);

View File

@@ -2,6 +2,7 @@
import React from 'react';
import { useFormikContext } from 'formik';
import PaymentReceiveNumberDialog from '@/containers/Dialogs/PaymentReceiveNumberDialog';
import { ExcessPaymentDialog } from './dialogs/ExcessPaymentDialog';
/**
* Payment receive form dialogs.
@@ -21,9 +22,12 @@ export default function PaymentReceiveFormDialogs() {
};
return (
<PaymentReceiveNumberDialog
dialogName={'payment-receive-number-form'}
onConfirm={handleUpdatePaymentNumber}
/>
<>
<PaymentReceiveNumberDialog
dialogName={'payment-receive-number-form'}
onConfirm={handleUpdatePaymentNumber}
/>
<ExcessPaymentDialog dialogName={'payment-received-excessed-payment'} />
</>
);
}

View File

@@ -7,11 +7,16 @@ import {
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
FormatNumber,
} from '@/components';
import { usePaymentReceiveTotals } from './utils';
import {
usePaymentReceiveTotals,
usePaymentReceivedTotalExceededAmount,
} from './utils';
export function PaymentReceiveFormFootetRight() {
const { formattedSubtotal, formattedTotal } = usePaymentReceiveTotals();
const exceededAmount = usePaymentReceivedTotalExceededAmount();
return (
<PaymentReceiveTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
@@ -25,6 +30,11 @@ export function PaymentReceiveFormFootetRight() {
value={formattedTotal}
textStyle={TotalLineTextStyle.Bold}
/>
<TotalLine
title={'Exceeded Amount'}
value={<FormatNumber value={exceededAmount} />}
textStyle={TotalLineTextStyle.Regular}
/>
</PaymentReceiveTotalLines>
);
}

View File

@@ -30,15 +30,9 @@ function PaymentReceiveFormHeader() {
function PaymentReceiveFormBigTotal() {
// Formik form context.
const {
values: { currency_code, entries },
values: { currency_code, amount },
} = useFormikContext();
// Calculates the total payment amount from due amount.
const paymentFullAmount = useMemo(
() => sumBy(entries, 'payment_amount'),
[entries],
);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_BIG_NUMBERS)}>
<div class="big-amount">
@@ -46,7 +40,7 @@ function PaymentReceiveFormBigTotal() {
<T id={'amount_received'} />
</span>
<h1 class="big-amount__number">
<Money amount={paymentFullAmount} currency={currency_code} />
<Money amount={amount} currency={currency_code} />
</h1>
</div>
</div>

View File

@@ -1,5 +1,5 @@
// @ts-nocheck
import React, { createContext, useContext } from 'react';
import React, { createContext, useContext, useState } from 'react';
import { Features } from '@/constants';
import { useFeatureCan } from '@/hooks/state';
import { DashboardInsider } from '@/components';
@@ -74,6 +74,8 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
const { mutateAsync: editPaymentReceiveMutate } = useEditPaymentReceive();
const { mutateAsync: createPaymentReceiveMutate } = useCreatePaymentReceive();
const [isExcessConfirmed, setIsExcessConfirmed] = useState<boolean>(false);
// Provider payload.
const provider = {
paymentReceiveId,
@@ -97,6 +99,9 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
editPaymentReceiveMutate,
createPaymentReceiveMutate,
isExcessConfirmed,
setIsExcessConfirmed,
};
return (

View File

@@ -11,7 +11,7 @@ import {
Button,
} from '@blueprintjs/core';
import { DateInput } from '@blueprintjs/datetime';
import { toSafeInteger } from 'lodash';
import { isEmpty, toSafeInteger } from 'lodash';
import { FastField, Field, useFormikContext, ErrorMessage } from 'formik';
import {
@@ -124,11 +124,11 @@ export default function PaymentReceiveHeaderFields() {
</FastField>
{/* ------------ Full amount ------------ */}
<Field name={'full_amount'}>
<Field name={'amount'}>
{({
form: {
setFieldValue,
values: { currency_code },
values: { currency_code, entries },
},
field: { value, onChange },
meta: { error, touched },
@@ -146,21 +146,23 @@ export default function PaymentReceiveHeaderFields() {
<MoneyInputGroup
value={value}
onChange={(value) => {
setFieldValue('full_amount', value);
setFieldValue('amount', value);
}}
onBlurValue={onFullAmountBlur}
/>
</ControlGroup>
<Button
onClick={handleReceiveFullAmountClick}
className={'receive-full-amount'}
small={true}
minimal={true}
>
<T id={'receive_full_amount'} /> (
<Money amount={totalDueAmount} currency={currency_code} />)
</Button>
{!isEmpty(entries) && (
<Button
onClick={handleReceiveFullAmountClick}
className={'receive-full-amount'}
small={true}
minimal={true}
>
<T id={'receive_full_amount'} /> (
<Money amount={totalDueAmount} currency={currency_code} />)
</Button>
)}
</FormGroup>
)}
</Field>

View File

@@ -0,0 +1,37 @@
// @ts-nocheck
import React from 'react';
import { Dialog, DialogSuspense } from '@/components';
import withDialogRedux from '@/components/DialogReduxConnect';
import { compose } from '@/utils';
const ExcessPaymentDialogContent = React.lazy(() =>
import('./ExcessPaymentDialogContent').then((module) => ({
default: module.ExcessPaymentDialogContent,
})),
);
/**
* Excess payment dialog of the payment received form.
*/
function ExcessPaymentDialogRoot({ dialogName, isOpen }) {
return (
<Dialog
name={dialogName}
title={'Excess Payment'}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
style={{ width: 500 }}
>
<DialogSuspense>
<ExcessPaymentDialogContent dialogName={dialogName} />
</DialogSuspense>
</Dialog>
);
}
export const ExcessPaymentDialog = compose(withDialogRedux())(
ExcessPaymentDialogRoot,
);
ExcessPaymentDialog.displayName = 'ExcessPaymentDialog';

View File

@@ -0,0 +1,86 @@
// @ts-nocheck
import * as Yup from 'yup';
import * as R from 'ramda';
import { Button, Classes, Intent } from '@blueprintjs/core';
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
import { FormatNumber } from '@/components';
import { usePaymentReceiveFormContext } from '../../PaymentReceiveFormProvider';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { usePaymentReceivedTotalExceededAmount } from '../../utils';
interface ExcessPaymentValues {}
export function ExcessPaymentDialogContentRoot({ dialogName, closeDialog }) {
const {
submitForm,
values: { currency_code: currencyCode },
} = useFormikContext();
const { setIsExcessConfirmed } = usePaymentReceiveFormContext();
const exceededAmount = usePaymentReceivedTotalExceededAmount();
const handleSubmit = (
values: ExcessPaymentValues,
{ setSubmitting }: FormikHelpers<ExcessPaymentValues>,
) => {
setSubmitting(true);
setIsExcessConfirmed(true);
submitForm().then(() => {
closeDialog(dialogName);
setSubmitting(false);
});
};
const handleClose = () => {
closeDialog(dialogName);
};
return (
<Formik initialValues={{}} onSubmit={handleSubmit}>
<Form>
<ExcessPaymentDialogContentForm
exceededAmount={
<FormatNumber value={exceededAmount} currency={currencyCode} />
}
onClose={handleClose}
/>
</Form>
</Formik>
);
}
export const ExcessPaymentDialogContent = R.compose(withDialogActions)(
ExcessPaymentDialogContentRoot,
);
function ExcessPaymentDialogContentForm({ onClose, exceededAmount }) {
const { submitForm, isSubmitting } = useFormikContext();
const handleCloseBtn = () => {
onClose && onClose();
};
return (
<>
<div className={Classes.DIALOG_BODY}>
<p style={{ marginBottom: 20 }}>
Would you like to record the excess amount of{' '}
<strong>{exceededAmount}</strong> as credit payment from the customer.
</p>
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button
intent={Intent.PRIMARY}
loading={isSubmitting}
disabled={isSubmitting}
onClick={() => submitForm()}
>
Save Payment as Credit
</Button>
<Button onClick={handleCloseBtn}>Cancel</Button>
</div>
</div>
</>
);
}

View File

@@ -0,0 +1 @@
export * from './ExcessPaymentDialog';

View File

@@ -42,12 +42,12 @@ export const defaultPaymentReceive = {
// Holds the payment number that entered manually only.
payment_receive_no_manually: '',
statement: '',
full_amount: '',
amount: '',
currency_code: '',
branch_id: '',
exchange_rate: 1,
entries: [],
attachments: []
attachments: [],
};
export const defaultRequestPaymentEntry = {
@@ -249,6 +249,30 @@ export const usePaymentReceiveTotals = () => {
};
};
export const usePaymentReceivedTotalAppliedAmount = () => {
const {
values: { entries },
} = useFormikContext();
// Retrieves the invoice entries total.
return React.useMemo(() => sumBy(entries, 'payment_amount'), [entries]);
};
export const usePaymentReceivedTotalAmount = () => {
const {
values: { amount },
} = useFormikContext();
return amount;
};
export const usePaymentReceivedTotalExceededAmount = () => {
const totalAmount = usePaymentReceivedTotalAmount();
const totalApplied = usePaymentReceivedTotalAppliedAmount();
return Math.abs(totalAmount - totalApplied);
};
/**
* Detarmines whether the payment has foreign customer.
* @returns {boolean}
@@ -273,3 +297,10 @@ export const resetFormState = ({ initialValues, values, resetForm }) => {
},
});
};
export const getExceededAmountFromValues = (values) => {
const totalApplied = sumBy(values.entries, 'payment_amount');
const totalAmount = values.amount;
return totalAmount - totalApplied;
};

View File

@@ -5,7 +5,6 @@ import '@/style/pages/PaymentReceive/List.scss';
import { DashboardPageContent } from '@/components';
import { PaymentReceivesListProvider } from './PaymentReceiptsListProvider';
import PaymentReceiveViewTabs from './PaymentReceiveViewTabs';
import PaymentReceivesTable from './PaymentReceivesTable';
import PaymentReceiveActionsBar from './PaymentReceiveActionsBar';
@@ -41,7 +40,6 @@ function PaymentReceiveList({
<PaymentReceiveActionsBar />
<DashboardPageContent>
<PaymentReceiveViewTabs />
<PaymentReceivesTable />
</DashboardPageContent>
</PaymentReceivesListProvider>

View File

@@ -7,7 +7,6 @@ import { DashboardPageContent } from '@/components';
import { VendorsListProvider } from './VendorsListProvider';
import VendorActionsBar from './VendorActionsBar';
import VendorViewsTabs from './VendorViewsTabs';
import VendorsTable from './VendorsTable';
import withVendors from './withVendors';
@@ -42,7 +41,6 @@ function VendorsList({
<VendorActionsBar />
<DashboardPageContent>
<VendorViewsTabs />
<VendorsTable />
</DashboardPageContent>
</VendorsListProvider>

View File

@@ -3,7 +3,6 @@ import React from 'react';
import { DashboardPageContent } from '@/components';
import WarehouseTransfersActionsBar from './WarehouseTransfersActionsBar';
import WarehouseTransfersViewTabs from './WarehouseTransfersViewTabs';
import WarehouseTransfersDataTable from './WarehouseTransfersDataTable';
import withWarehouseTransfers from './withWarehouseTransfers';
import withWarehouseTransfersActions from './withWarehouseTransfersActions';
@@ -33,8 +32,8 @@ function WarehouseTransfersList({
tableStateChanged={warehouseTransferTableStateChanged}
>
<WarehouseTransfersActionsBar />
<DashboardPageContent>
<WarehouseTransfersViewTabs />
<WarehouseTransfersDataTable />
</DashboardPageContent>
</WarehouseTransfersListProvider>