Compare commits

...

11 Commits

Author SHA1 Message Date
elforjani13
8bad78b0d3 fix: cashflow statement row_types. 2021-11-10 12:16:17 +02:00
a.bouhuolia
d94d28f709 chore: remove console log. 2021-11-02 21:24:23 +02:00
a.bouhuolia
94e6b64944 fix: sidebar cashflow links. 2021-11-02 17:31:03 +02:00
elforjani13
d8e9be0246 fix: rename inventory adjustment. 2021-11-02 16:16:10 +02:00
a.bouhuolia
7ef72e8955 fix: invoice details popover menu. 2021-11-02 15:46:03 +02:00
elforjani13
d76cc3d2a2 fix: remove white space 2021-11-02 15:03:25 +02:00
elforjani13
3102329ac0 Merge branch 'feature/BadDebt' 2021-11-02 15:00:16 +02:00
elforjani13
fd09ea12ff fix: localization. 2021-11-02 14:22:55 +02:00
a.bouhuolia
7bd09e7326 fix: BIG-157 incorrect formatted date. 2021-11-02 14:19:10 +02:00
elforjani13
cd3105b320 feat: add Bad-debt & cancel bad-bebt. 2021-11-02 00:23:43 +02:00
elforjani13
91b848f158 feat: Bad Debt. 2021-11-01 20:24:01 +02:00
32 changed files with 730 additions and 25 deletions

View File

@@ -0,0 +1,12 @@
import intl from 'react-intl-universal';
export const moreVertOptions = [
{
name: intl.get('bad_debt.dialog.bad_debt'),
value: 'bad debt',
},
{
name: intl.get('bad_debt.dialog.cancel_bad_debt'),
value: 'cancel bad debt',
},
];

View File

@@ -19,6 +19,7 @@ import EstimatePdfPreviewDialog from 'containers/Dialogs/EstimatePdfPreviewDialo
import ReceiptPdfPreviewDialog from '../containers/Dialogs/ReceiptPdfPreviewDialog';
import MoneyInDialog from '../containers/Dialogs/MoneyInDialog';
import MoneyOutDialog from '../containers/Dialogs/MoneyOutDialog';
import BadDebtDialog from '../containers/Dialogs/BadDebtDialog';
/**
* Dialogs container.
@@ -44,6 +45,7 @@ export default function DialogsContainer() {
<ReceiptPdfPreviewDialog dialogName={'receipt-pdf-preview'} />
<MoneyInDialog dialogName={'money-in'} />
<MoneyOutDialog dialogName={'money-out'} />
<BadDebtDialog dialogName={'write-off-bad-debt'} />
</div>
);
}

View File

@@ -0,0 +1,46 @@
import React from 'react';
import {
Button,
PopoverInteractionKind,
MenuItem,
Position,
} from '@blueprintjs/core';
import { Select } from '@blueprintjs/select';
import { Icon } from 'components';
function MoreVertMenutItems({ text, items, onItemSelect, buttonProps }) {
// Menu items renderer.
const itemsRenderer = (item, { handleClick, modifiers, query }) => (
<MenuItem text={item.name} label={item.label} onClick={handleClick} />
);
const handleMenuSelect = (type) => {
onItemSelect && onItemSelect(type);
};
return (
<Select
items={items}
itemRenderer={itemsRenderer}
onItemSelect={handleMenuSelect}
popoverProps={{
minimal: true,
position: Position.BOTTOM_LEFT,
interactionKind: PopoverInteractionKind.CLICK,
modifiers: {
offset: { offset: '0, 4' },
},
}}
filterable={false}
>
<Button
text={text}
icon={<Icon icon={'more-vert'} iconSize={16} />}
minimal={true}
{...buttonProps}
/>
</Select>
);
}
export default MoreVertMenutItems;

View File

@@ -8,7 +8,7 @@ import intl from 'react-intl-universal';
export function FormatDate({ value, format = 'YYYY MMM DD' }) {
const localizedFormat = intl.get(`date_formats.${format}`);
return moment().format(localizedFormat);
return moment(value).format(localizedFormat);
}
/**

View File

@@ -61,6 +61,7 @@ import Card from './Card';
import AvaterCell from './AvaterCell';
import { ItemsMultiSelect } from './Items';
import MoreVertMenutItems from './MoreVertMenutItems';
export * from './Menu';
export * from './AdvancedFilter/AdvancedFilterDropdown';
@@ -85,6 +86,7 @@ export * from './BankAccounts';
export * from './IntersectionObserver'
export * from './Datatable/CellForceWidth';
export * from './Button';
export * from './IntersectionObserver';
const Hint = FieldHint;
@@ -156,4 +158,5 @@ export {
ItemsMultiSelect,
Card,
AvaterCell,
MoreVertMenutItems,
};

View File

@@ -205,19 +205,19 @@ export default [
},
{
text: <T id={'cash_flow.label.add_money_in'} />,
href: '/',
href: '/cashflow-accounts',
},
{
text: <T id={'cash_flow.label.add_money_out'} />,
href: '/',
href: '/cashflow-accounts',
},
{
text: <T id={'cash_flow.label.add_cash_account'} />,
href: '/',
href: '/cashflow-accounts',
},
{
text: <T id={'cash_flow.label.add_bank_account'} />,
href: '/',
href: '/cashflow-accounts',
},
],
},

View File

@@ -0,0 +1,68 @@
import React from 'react';
import { FormattedMessage as T } from 'components';
import intl from 'react-intl-universal';
import { Intent, Alert } from '@blueprintjs/core';
import { AppToaster } from 'components';
import { useCancelBadDebt } from 'hooks/query';
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
import withAlertActions from 'containers/Alert/withAlertActions';
import { compose } from 'utils';
/**
* Cancel bad debt alert.
*/
function CancelBadDebtAlert({
name,
// #withAlertStoreConnect
isOpen,
payload: { invoiceId },
// #withAlertActions
closeAlert,
}) {
// handle cancel alert.
const handleCancel = () => {
closeAlert(name);
};
const { mutateAsync: cancelBadDebtMutate, isLoading } = useCancelBadDebt();
// handleConfirm alert.
const handleConfirm = () => {
cancelBadDebtMutate(invoiceId)
.then(() => {
AppToaster.show({
message: intl.get('bad_debt.cancel_alert.success_message'),
intent: Intent.SUCCESS,
});
})
.catch(() => {})
.finally(() => {
closeAlert(name);
});
};
return (
<Alert
cancelButtonText={<T id={'cancel'} />}
confirmButtonText={<T id={'save'} />}
intent={Intent.WARNING}
isOpen={isOpen}
onCancel={handleCancel}
onConfirm={handleConfirm}
loading={isLoading}
>
<p>
<T id={'bad_debt.cancel_alert.message'} />
</p>
</Alert>
);
}
export default compose(
withAlertStoreConnect(),
withAlertActions,
)(CancelBadDebtAlert);

View File

@@ -23,7 +23,7 @@ function AccountSwitchButton() {
<AccountSwitchButtonBase
minimal={true}
rightIcon={<Icon icon={'arrow-drop-down'} iconSize={24} />}
>
>
<AccountSwitchText>{currentAccount.name}</AccountSwitchText>
</AccountSwitchButtonBase>
);

View File

@@ -0,0 +1,20 @@
import React from 'react';
import 'style/pages/BadDebt/BadDebtDialog.scss';
import { BadDebtFormProvider } from './BadDebtFormProvider';
import BadDebtForm from './BadDebtForm';
/**
* Bad debt dialog content.
*/
export default function BadDebtDialogContent({
// #ownProps
dialogName,
invoice,
}) {
return (
<BadDebtFormProvider invoiceId={invoice} dialogName={dialogName}>
<BadDebtForm />
</BadDebtFormProvider>
);
}

View File

@@ -0,0 +1,86 @@
import React from 'react';
import intl from 'react-intl-universal';
import { Formik } from 'formik';
import { Intent } from '@blueprintjs/core';
import { omit } from 'lodash';
import { AppToaster } from 'components';
import { CreateBadDebtFormSchema } from './BadDebtForm.schema';
import { transformErrors } from './utils';
import BadDebtFormContent from './BadDebtFormContent';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
import { useBadDebtContext } from './BadDebtFormProvider';
import { compose } from 'utils';
const defaultInitialValues = {
expense_account_id: '',
reason: '',
amount: '',
};
function BadDebtForm({
// #withDialogActions
closeDialog,
// #withCurrentOrganization
organization: { base_currency },
}) {
const { invoice, dialogName, createBadDebtMutate, cancelBadDebtMutate } =
useBadDebtContext();
// Initial form values
const initialValues = {
...defaultInitialValues,
currency_code: base_currency,
amount: invoice.due_amount,
};
// Handles the form submit.
const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
const form = {
...omit(values, ['currency_code']),
};
// Handle request response success.
const onSuccess = (response) => {
AppToaster.show({
message: intl.get('bad_debt.dialog.success_message'),
intent: Intent.SUCCESS,
});
closeDialog(dialogName);
};
// Handle request response errors.
const onError = ({
response: {
data: { errors },
},
}) => {
if (errors) {
transformErrors(errors, { setErrors });
}
setSubmitting(false);
};
createBadDebtMutate([invoice.id, form]).then(onSuccess).catch(onError);
};
return (
<Formik
validationSchema={CreateBadDebtFormSchema}
initialValues={initialValues}
onSubmit={handleFormSubmit}
component={BadDebtFormContent}
/>
);
}
export default compose(
withDialogActions,
withCurrentOrganization(),
)(BadDebtForm);

View File

@@ -0,0 +1,17 @@
import * as Yup from 'yup';
import intl from 'react-intl-universal';
import { DATATYPES_LENGTH } from 'common/dataTypes';
const Schema = Yup.object().shape({
expense_account_id: Yup.number()
.required()
.label(intl.get('expense_account_id')),
amount: Yup.number().required().label(intl.get('amount')),
reason: Yup.string()
.required()
.min(3)
.max(DATATYPES_LENGTH.TEXT)
.label(intl.get('reason')),
});
export const CreateBadDebtFormSchema = Schema;

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { Form } from 'formik';
import BadDebtFormFields from './BadDebtFormFields';
import BadDebtFormFloatingActions from './BadDebtFormFloatingActions';
/**
* Bad debt form content.
*/
export default function BadDebtFormContent() {
return (
<Form>
<BadDebtFormFields />
<BadDebtFormFloatingActions />
</Form>
);
}

View File

@@ -0,0 +1,121 @@
import React from 'react';
import { FastField, ErrorMessage } from 'formik';
import { FormattedMessage as T } from 'components';
import { useAutofocus } from 'hooks';
import {
Classes,
FormGroup,
TextArea,
ControlGroup,
Callout,
Intent,
} from '@blueprintjs/core';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import { ACCOUNT_TYPE } from 'common/accountTypes';
import { inputIntent } from 'utils';
import {
AccountsSuggestField,
InputPrependText,
MoneyInputGroup,
FieldRequiredHint,
} from 'components';
import { useBadDebtContext } from './BadDebtFormProvider';
/**
* Bad debt form fields.
*/
function BadDebtFormFields() {
const amountfieldRef = useAutofocus();
const { accounts } = useBadDebtContext();
return (
<div className={Classes.DIALOG_BODY}>
<Callout intent={Intent.PRIMARY}>
<p>
<T id={'bad_debt.dialog.header_note'} />
</p>
</Callout>
{/*------------ Written-off amount -----------*/}
<FastField name={'amount'}>
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<FormGroup
label={<T id={'bad_debt.dialog.written_off_amount'} />}
labelInfo={<FieldRequiredHint />}
className={classNames('form-group--amount', CLASSES.FILL)}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name="amount" />}
>
<ControlGroup>
<InputPrependText text={values.currency_code} />
<MoneyInputGroup
value={value}
minimal={true}
onChange={(amount) => {
setFieldValue('amount', amount);
}}
intent={inputIntent({ error, touched })}
disabled={amountfieldRef}
/>
</ControlGroup>
</FormGroup>
)}
</FastField>
{/*------------ Expense account -----------*/}
<FastField name={'expense_account_id'}>
{({ form, field: { value }, meta: { error, touched } }) => (
<FormGroup
label={<T id={'expense_account_id'} />}
className={classNames(
'form-group--expense_account_id',
'form-group--select-list',
CLASSES.FILL,
)}
labelInfo={<FieldRequiredHint />}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'expense_account_id'} />}
>
<AccountsSuggestField
selectedAccountId={value}
accounts={accounts}
onAccountSelected={({ id }) =>
form.setFieldValue('expense_account_id', id)
}
filterByTypes={[ACCOUNT_TYPE.EXPENSE]}
/>
</FormGroup>
)}
</FastField>
{/*------------ reason -----------*/}
<FastField name={'reason'}>
{({ field, meta: { error, touched } }) => (
<FormGroup
label={<T id={'reason'} />}
labelInfo={<FieldRequiredHint />}
className={'form-group--reason'}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'reason'} />}
>
<TextArea
growVertically={true}
large={true}
intent={inputIntent({ error, touched })}
{...field}
/>
</FormGroup>
)}
</FastField>
</div>
);
}
export default BadDebtFormFields;

View File

@@ -0,0 +1,48 @@
import React from 'react';
import { Intent, Button, Classes } from '@blueprintjs/core';
import { useFormikContext } from 'formik';
import { FormattedMessage as T } from 'components';
import { useBadDebtContext } from './BadDebtFormProvider';
import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils';
/**
* Bad bebt form floating actions.
*/
function BadDebtFormFloatingActions({
// #withDialogActions
closeDialog,
}) {
// bad debt invoice dialog context.
const { dialogName } = useBadDebtContext();
// Formik context.
const { isSubmitting } = useFormikContext();
// Handle close button click.
const handleCancelBtnClick = () => {
closeDialog(dialogName);
};
return (
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button onClick={handleCancelBtnClick} style={{ minWidth: '75px' }}>
<T id={'cancel'} />
</Button>
<Button
intent={Intent.PRIMARY}
loading={isSubmitting}
style={{ minWidth: '75px' }}
type="submit"
>
{<T id={'save'} />}
</Button>
</div>
</div>
);
}
export default compose(withDialogActions)(BadDebtFormFloatingActions);

View File

@@ -0,0 +1,46 @@
import React from 'react';
import { DialogContent } from 'components';
import {
useAccounts,
useInvoice,
useCreateBadDebt,
useCancelBadDebt,
} from 'hooks/query';
const BadDebtContext = React.createContext();
/**
* Bad debt provider.
*/
function BadDebtFormProvider({ invoiceId, dialogName, ...props }) {
// Handle fetch accounts data.
const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
// Handle fetch invoice data.
const { data: invoice, isLoading: isInvoiceLoading } = useInvoice(invoiceId, {
enabled: !!invoiceId,
});
// Create and cancel bad debt mutations.
const { mutateAsync: createBadDebtMutate } = useCreateBadDebt();
// State provider.
const provider = {
accounts,
invoice,
invoiceId,
dialogName,
createBadDebtMutate,
};
return (
<DialogContent isLoading={isAccountsLoading || isInvoiceLoading}>
<BadDebtContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const useBadDebtContext = () => React.useContext(BadDebtContext);
export { BadDebtFormProvider, useBadDebtContext };

View File

@@ -0,0 +1,29 @@
import React from 'react';
import { FormattedMessage as T } from 'components';
import { Dialog, DialogSuspense } from 'components';
import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'redux';
const BadDebtDialogContent = React.lazy(() => import('./BadDebtDialogContent'));
/**
* Bad debt dialog.
*/
function BadDebtDialog({ dialogName, payload: { invoiceId = null }, isOpen }) {
return (
<Dialog
name={dialogName}
title={<T id={'bad_debt.dialog.bad_debt'} />}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
className={'dialog--bad-debt'}
>
<DialogSuspense>
<BadDebtDialogContent dialogName={dialogName} invoice={invoiceId} />
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(BadDebtDialog);

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { Intent } from '@blueprintjs/core';
import { AppToaster } from 'components';
/**
* Transformes the response errors types.
*/
export const transformErrors = (errors, { setErrors }) => {
if (errors.some(({ type }) => type === 'SALE_INVOICE_ALREADY_WRITTEN_OFF')) {
AppToaster.show({
message: 'SALE_INVOICE_ALREADY_WRITTEN_OFF',
// message: intl.get(''),
intent: Intent.DANGER,
});
}
};

View File

@@ -15,7 +15,6 @@ function MoneyInDialog({
payload = { account_type: null, account_id: null, account_name: '' },
isOpen,
}) {
console.log(payload, 'EE');
return (
<Dialog
name={dialogName}

View File

@@ -20,8 +20,6 @@ function UserForm({
// #withDialogActions
closeDialog,
}) {
const {
dialogName,
user,
@@ -29,7 +27,7 @@ function UserForm({
isEditMode,
EditUserMutate,
} = useUserFormContext();
console.log(user, 'EE');
const initialValues = {
...(isEditMode &&
pick(

View File

@@ -38,6 +38,11 @@ export default function BillDrawerDetails() {
id={'landed_cost'}
panel={<LocatedLandedCostTable />}
/>
{/* <Tab
title={intl.get('payment_transactions')}
id={'payment_transactions'}
// panel={}
/> */}
</DrawerMainTabs>
</div>
);

View File

@@ -30,6 +30,11 @@ export default function InvoiceDetail() {
id={'journal_entries'}
panel={<JournalEntriesTable transactions={transactions} />}
/>
{/* <Tab
title={intl.get('payment_transactions')}
id={'payment_transactions'}
// panel={}
/> */}
</DrawerMainTabs>
</div>
);

View File

@@ -6,20 +6,33 @@ import {
NavbarGroup,
Classes,
NavbarDivider,
Popover,
PopoverInteractionKind,
Position,
Intent,
MenuItem,
Menu,
} from '@blueprintjs/core';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import { useInvoiceDetailDrawerContext } from './InvoiceDetailDrawerProvider';
import { moreVertOptions } from '../../../common/moreVertOptions';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { If, Icon, FormattedMessage as T } from 'components';
import {
If,
Icon,
FormattedMessage as T,
// MoreVertMenutItems,
} from 'components';
import { compose } from 'utils';
import { BadDebtMenuItem } from './utils';
/**
* Invoice details action bar.
*/
@@ -59,6 +72,16 @@ function InvoiceDetailActionsBar({
openDialog('quick-payment-receive', { invoiceId });
};
// Handle write-off invoice.
const handleBadDebtInvoice = () => {
openDialog('write-off-bad-debt', { invoiceId });
};
// Handle cancele write-off invoice.
const handleCancelBadDebtInvoice = () => {
openAlert('cancel-bad-debt', { invoiceId });
};
return (
<DashboardActionsBar>
<NavbarGroup>
@@ -91,6 +114,12 @@ function InvoiceDetailActionsBar({
intent={Intent.DANGER}
onClick={handleDeleteInvoice}
/>
<NavbarDivider />
<BadDebtMenuItem
invoice={invoice}
onAlert={handleCancelBadDebtInvoice}
onDialog={handleBadDebtInvoice}
/>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,5 +1,14 @@
import React from 'react';
import intl from 'react-intl-universal';
import {
Button,
Popover,
PopoverInteractionKind,
Position,
MenuItem,
Menu,
} from '@blueprintjs/core';
import { Icon, FormattedMessage as T, Choose } from 'components';
import { FormatNumberCell } from '../../../components';
/**
@@ -48,3 +57,36 @@ export const useInvoiceReadonlyEntriesColumns = () =>
],
[],
);
export const BadDebtMenuItem = ({ invoice, onDialog, onAlert }) => {
return (
<Popover
minimal={true}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_LEFT}
modifiers={{
offset: { offset: '0, 4' },
}}
content={
<Menu>
<Choose>
<Choose.When condition={!invoice.is_writtenoff}>
<MenuItem
text={<T id={'bad_debt.dialog.bad_debt'} />}
onClick={onDialog}
/>
</Choose.When>
<Choose.When condition={invoice.is_writtenoff}>
<MenuItem
onClick={onAlert}
text={<T id={'bad_debt.dialog.cancel_bad_debt'} />}
/>
</Choose.When>
</Choose>
</Menu>
}
>
<Button icon={<Icon icon="more-vert" iconSize={16} />} minimal={true} />
</Popover>
);
};

View File

@@ -32,7 +32,7 @@ export default function CashFlowStatementTable({
const rowClassNames = (row) => {
return [
`row-type--${row.original.rowTypes}`,
`row-type--${row.original.row_types}`,
`row-type--${row.original.id}`,
];
};

View File

@@ -9,7 +9,7 @@ const columnsMapper = (data, index, column) => ({
id: column.key,
key: column.key,
Header: column.label,
Cell: CellForceWidth,
// Cell: CellForceWidth,
accessor: `cells[${index}].value`,
forceWidthAccess: `cells[0].value`,
className: column.key,

View File

@@ -7,10 +7,15 @@ const InvoiceDeliverAlert = React.lazy(() =>
import('../../Alerts/Invoices/InvoiceDeliverAlert'),
);
const CancelBadDebtAlert = React.lazy(() =>
import('../../Alerts/Invoices/CancelBadDebtAlert'),
);
/**
* Invoices alert.
*/
export default [
{ name: 'invoice-delete', component: InvoiceDeleteAlert },
{ name: 'invoice-deliver', component: InvoiceDeliverAlert },
{ name: 'cancel-bad-debt', component: CancelBadDebtAlert },
];

View File

@@ -9,6 +9,7 @@ import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate invoices.
queryClient.invalidateQueries(t.SALE_INVOICES);
queryClient.invalidateQueries(t.SALE_INVOICE);
// Invalidate customers.
queryClient.invalidateQueries(t.CUSTOMERS);
@@ -194,3 +195,38 @@ export function useRefreshInvoices() {
},
};
}
export function useCreateBadDebt(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.post(`sales/invoices/${id}/writeoff`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate
queryClient.invalidateQueries([t.BAD_DEBT, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useCancelBadDebt(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.post(`sales/invoices/${id}/writeoff/cancel`), {
onSuccess: (res, id) => {
// Invalidate
queryClient.invalidateQueries([t.CANCEL_BAD_DEBT, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}

View File

@@ -85,6 +85,8 @@ const SALE_INVOICES = {
SALE_INVOICES: 'SALE_INVOICES',
SALE_INVOICE: 'SALE_INVOICE',
SALE_INVOICES_DUE: 'SALE_INVOICES_DUE',
BAD_DEBT: 'BAD_DEBT',
CANCEL_BAD_DEBT: 'CANCEL_BAD_DEBT',
};
const USERS = {
@@ -137,7 +139,8 @@ const CASH_FLOW_ACCOUNTS = {
CASH_FLOW_ACCOUNTS: 'CASH_FLOW_ACCOUNTS',
CASH_FLOW_TRANSACTIONS: 'CASH_FLOW_TRANSACTIONS',
CASH_FLOW_TRANSACTION: 'CASH_FLOW_TRANSACTION',
CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY: 'CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY'
CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY:
'CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY',
};
export default {

View File

@@ -1012,6 +1012,8 @@
"jump_to_the_bills": "انتقل إلي فواتير الشراء.",
"jump_to_the_manual_journals": "انتقل إلي القيود اليدوية.",
"jump_to_the_items": "انتقل إلي المنتجات.",
"jump_to_the_add_money_in": "انتقل إلي إيداع إلي الحساب.",
"jump_to_the_add_money_out": "انتقل إلي سحب من الحساب.",
"jump_to_the_balance_sheet": "انتقل إلي تقرير الميزانية العمومية.",
"jump_to_the_profit_loss_sheet": "انتقل إلي تقرير قائمة الدخل.",
"jump_to_the_journal_sheet": "انتقل إلي دفتر اليومية العامة.",
@@ -1371,7 +1373,6 @@
"payment_made.empty_status.title": "المنشأة لم تدفع اي اموال إلي الموردين ، إلي حد الأن!.",
"estimate.delete.error.estimate_converted_to_invoice": "لا يمكن حذف عملية عرض اسعار الذي تم تحويلها إلي فاتورة بيع.",
"landed_cost.action.delete.success_message": "The landed cost has been deleted successfully.",
"items.option.only_active": "Only active",
"items.option_all_items.hint": "جميع الاصناف ، بما في ذلك تلك الاصناف لديها رصيد صفر.",
"items.option_with_transactions": "الاصناف مع معاملات",
@@ -1379,22 +1380,18 @@
"items.option_without_zero_balance": "الاصناف ذات رصيد صفر",
"items.option_without_zero_balance.hint": "قم بتضمين الاصناف واستبعاد تلك التي لديها رصيد صفري.",
"items.label_filter_items": "تصفية الاصناف",
"customers.option_all_customers.hint": "All customers, including that ones have zero-balance.",
"customers.option_without_zero_balance": "Customers without zero-balance",
"customers.option_without_zero_balance.hint": "Include customers and exclude that ones have zero-balance.",
"customers.option_with_transactions": "Customers with transactions",
"customers.option_with_transactions.hint": "Include customers that onces have transactions on the given date period only.",
"customers.label_filter_customers": "Filter customers",
"vendors.option_all_vendors.hint": "All vendors, including that ones have zero-balance.",
"vendors.label_filter_vendors": "Filter Vendors",
"vendors.option_without_zero_balance": "Vendors without zero-balance",
"vendors.option_without_zero_balance.hint": "Include vendors and exclude that ones have zero-balance.",
"vendors.option_with_transactions": "Vendors with transactions",
"vendors.option_with_transactions.hint": "Include vendors that onces have transactions on the given date period only.",
"siebar.cashflow": "التدفق النقدي",
"siebar.cashflow.label_cash_and_bank_accounts": "حسابات نقدية والمصارف ",
"cash_flow.label_account_transcations": "معاملات الحساب",
@@ -1405,7 +1402,6 @@
"cash_flow.label.add_bank_account": "اضافة حساب مصرف",
"cash_flow.label.add_money_in": "إيداع إلي الحساب",
"cash_flow.label.add_money_out": "سحب من الحساب",
"cash_flow.owner_contribution": "زيادة رأس المال",
"cash_flow.other_income": "إيراد أخر",
"cash_flow.owner_drawings": "سحب رأس المال",
@@ -1436,5 +1432,12 @@
"cash_flow_money_in": "إيداع",
"cash_flow_money_out": "سحب",
"cash_flow_transaction.switch_item": " {value} معاملة علي حساب",
"cash_flow_transaction.balance_in_bigcapital": "الرصيد في Bigcapital"
"cash_flow_transaction.balance_in_bigcapital": "الرصيد في Bigcapital",
"bad_debt.dialog.written_off_amount": "المبلغ المشطوب",
"bad_debt.dialog.bad_debt": "الديون المعدومة",
"bad_debt.dialog.cancel_bad_debt": "إلغاء الديون المعدومة",
"bad_debt.dialog.header_note": "يمكن للبائع تحميل مبلغ الفاتورة على حساب مصروفات الديون المعدومة عندما يكون من المؤكد أن الفاتورة لن يتم دفعها.",
"bad_debt.dialog.success_message":"تم شطب فاتورة البيع المقدمة بنجاح.",
"bad_debt.cancel_alert.success_message":"تم إلغاء شطب فاتورة البيع المقدمة بنجاح.",
"bad_debt.cancel_alert.message": "هل أنت متأكد أنك تريد شطب هذه الفاتورة؟ "
}

View File

@@ -756,7 +756,7 @@
"category_name_exists": "Category name exists",
"some_customers_have_sales_invoices": "Some customers have sales invoices",
"inventory_adjustments": "Inventory adjustments",
"make_adjustment": "Make a adjustment",
"make_adjustment": "Make an adjustment",
"adjustment_type": "Adjustment type",
"decrement": "Decrement",
"new_quantity": "New quantity",
@@ -1420,5 +1420,13 @@
"AP_aging_summary.filter_options.label": "Filter vendors",
"item.error.type_cannot_change_with_item_has_transactions": "Cannot change item type to inventory with item has associated transactions.",
"item.error.cannot_change_inventory_account": "Cannot change item inventory account while the item has transactions.",
"customer.link.customer_details": "Customer details ({amount})"
}
"customer.link.customer_details": "Customer details ({amount})",
"bad_debt.dialog.written_off_amount": "Written-off amount",
"bad_debt.dialog.bad_debt": "Bad debt",
"bad_debt.dialog.cancel_bad_debt": "Cancel bad debt",
"bad_debt.dialog.header_note": "The seller can charge the amount of an invoice to the bad debt expense account when it is certain that the invoice will not be paid.",
"bad_debt.dialog.success_message":"The given sale invoice has been writte-off successfully.",
"bad_debt.cancel_alert.success_message":"The given sale invoice has been canceled write-off successfully.",
"bad_debt.cancel_alert.message": "Are you sure you want to write off this invoice?"
}

View File

@@ -502,5 +502,11 @@ export default {
'arrow-upward': {
path: ['M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'],
viewBox: '0 0 24 24',
}
},
'more-vert': {
path: [
'M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z',
],
viewBox: '0 0 24 24',
},
};

View File

@@ -0,0 +1,34 @@
.dialog--bad-debt {
max-width: 400px;
.bp3-dialog-body {
.bp3-form-group {
margin-bottom: 15px;
margin-top: 15px;
label.bp3-label {
margin-bottom: 3px;
font-size: 13px;
}
}
.bp3-callout {
font-size: 13px;
}
.form-group {
&--reason {
.bp3-form-content {
textarea {
width: 100%;
min-width: 100%;
font-size: 14px;
}
}
}
}
}
.bp3-dialog-footer {
padding-top: 10px;
}
}