diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcca15ca3..582810e3a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,13 +2,43 @@
All notable changes to Bigcapital server-side will be in this file.
+## [1.5.0] - 20-12-2021
+### Added
+- Add credit note on sales module.
+- Add vendor credit on purchases module.
+- Optimize landed costs on purchase invoices.
+- Display associated payment transactions on sale invoice drawer.
+- Display associated pamyment transactions on purchase invoice drawer.
+- Display item associate invoice, bill, estimate and receipt transactions.
+- Transactions locking on all transactions or individual modules.
+- Roles and permissions access control module.
+- Optimize readonly details style of invoice, receipt, estimate, payment receive,
+ purchase invoice, expense, manual journal, inventory adjustment and cashflow transaction.
+
+### Changed
+- Dashboard meta boot and authenticated user request query.
+
+## [1.4.0] - 11-09-2021
+
+### Added
+- Add SMS notification on sale invoice, receipt, customers payments modules.
+- Customer quick create in customers list.
+- Item quick create in items list.
+
+### Changes
+ change: BIG-171 alerts in global scope and lazy loading.
+### Fixed
+ fix: BIG-140 - Reordering sell, cost and inventory account on item details.
+ fix: BIG-144 - Typo adjustment dialog success message.
+ fix: BIG-148 - Items entries ordered by index.
+ fix: BIG-132 AR/AP aging summary report filter by none transactions/zero contacts.
+
## [1.2.0-RC] - 03-09-2021
Here we write upgrading notes for brands. It's a team effort to make them as
straightforward as possible.
### Added
-
- Add slidable sub-sidebar to improve user experience instead of sub-menu.
- Add Subscription guard to ensure the organization's subscription is active or
redirect all routes to subscription billing page.
@@ -35,13 +65,11 @@ straightforward as possible.
- Add clickable datatable rows to display each row details.
### Changed
-
- Optimize style of datatable selection checkbox.
- Disable animation in dashboard views tabs.
- Optimize Arabic localization.
### Fixed
-
- fix: disable submit buttons in pereferences pages.
- fix: inventory adjustment cost field max/min range to avoid out of range error.
- fix: transactions by customers/vendors report localization.
diff --git a/package.json b/package.json
index 38afbca86..0ef5d4084 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"cross-env": "^7.0.2",
"css-loader": "3.4.2",
"deep-map-keys": "^2.0.1",
+ "dependency-graph": "^0.11.0",
"dotenv": "8.2.0",
"dotenv-expand": "5.1.0",
"eslint": "^6.6.0",
@@ -46,6 +47,7 @@
"eslint-plugin-jsx-a11y": "6.2.3",
"eslint-plugin-react": "7.18.0",
"eslint-plugin-react-hooks": "^1.6.1",
+ "fast-deep-equal": "^3.1.3",
"file-loader": "4.3.0",
"flow-bin": "^0.123.0",
"formik": "^2.2.5",
@@ -106,6 +108,7 @@
"semver": "6.3.0",
"style-loader": "0.23.1",
"styled-components": "^5.3.1",
+ "stylis-rtlcss": "^2.1.1",
"terser-webpack-plugin": "2.3.4",
"ts-pnp": "1.1.5",
"url-loader": "2.3.0",
diff --git a/src/common/TableStyle.js b/src/common/TableStyle.js
new file mode 100644
index 000000000..d570a00fb
--- /dev/null
+++ b/src/common/TableStyle.js
@@ -0,0 +1,6 @@
+
+
+export const TableStyle = {
+ Constrant: 'constrant',
+ Regular: 'regular'
+}
\ No newline at end of file
diff --git a/src/common/abilityOption.js b/src/common/abilityOption.js
index 1a5625ca3..7f586f047 100644
--- a/src/common/abilityOption.js
+++ b/src/common/abilityOption.js
@@ -17,6 +17,8 @@ export const AbilitySubject = {
Preferences: 'Preferences',
ExchangeRate: 'ExchangeRate',
SubscriptionBilling: 'SubscriptionBilling',
+ CreditNote: 'CreditNote',
+ VendorCredit: 'VendorCredit',
};
export const ItemAction = {
@@ -46,7 +48,7 @@ export const SaleInvoiceAction = {
Create: 'Create',
Edit: 'Edit',
Delete: 'Delete',
- Writeoff: 'Writeoff',
+ Writeoff: 'bad-debt',
NotifyBySms: 'NotifyBySms',
};
@@ -66,6 +68,21 @@ export const PaymentReceiveAction = {
NotifyBySms: 'NotifyBySms',
};
+export const CreditNoteAction = {
+ View: 'View',
+ Create: 'Create',
+ Edit: 'Edit',
+ Delete: 'Delete',
+ Refund: 'Refund'
+};
+
+export const VendorCreditAction = {
+ View: 'View',
+ Create: 'Create',
+ Edit: 'Edit',
+ Delete: 'Delete',
+ Refund: 'Refund'
+};
export const BillAction = {
View: 'View',
Create: 'Create',
diff --git a/src/common/classes.js b/src/common/classes.js
index e1df0b33f..6b0872396 100644
--- a/src/common/classes.js
+++ b/src/common/classes.js
@@ -39,6 +39,8 @@ const CLASSES = {
PAGE_FORM_ITEM: 'page-form--item',
PAGE_FORM_MAKE_JOURNAL: 'page-form--make-journal-entries',
PAGE_FORM_EXPENSE: 'page-form--expense',
+ PAGE_FORM_CREDIT_NOTE:'page-form--credit-note',
+ PAGE_FORM_VENDOR_CREDIT_NOTE:'page-form--vendor-credit-note',
FORM_GROUP_LIST_SELECT: 'form-group--select-list',
diff --git a/src/common/drawers.js b/src/common/drawers.js
index 3a1b21032..5ec6d05a2 100644
--- a/src/common/drawers.js
+++ b/src/common/drawers.js
@@ -14,4 +14,8 @@ export const DRAWERS = {
QUICK_WRITE_VENDOR: 'quick-write-vendor',
QUICK_CREATE_CUSTOMER: 'quick-create-customer',
QUICK_CREATE_ITEM: 'quick-create-item',
+ CREDIT_NOTE_DETAIL_DRAWER: 'credit-note-detail-drawer',
+ VENDOR_CREDIT_DETAIL_DRAWER: 'vendor-credit-detail-drawer',
+ REFUND_CREDIT_NOTE_DETAIL_DRAWER:'refund-credit-detail-drawer',
+ REFUND_VENDOR_CREDIT_DETAIL_DRAWER:'refund-vendor-detail-drawer'
};
diff --git a/src/common/index.js b/src/common/index.js
new file mode 100644
index 000000000..25821fa35
--- /dev/null
+++ b/src/common/index.js
@@ -0,0 +1,4 @@
+
+
+
+export * from './TableStyle';
\ No newline at end of file
diff --git a/src/common/itemPaymentTranactionsOption.js b/src/common/itemPaymentTranactionsOption.js
new file mode 100644
index 000000000..0811c5183
--- /dev/null
+++ b/src/common/itemPaymentTranactionsOption.js
@@ -0,0 +1,51 @@
+import intl from 'react-intl-universal';
+import {
+ AbilitySubject,
+ SaleEstimateAction,
+ SaleReceiptAction,
+ SaleInvoiceAction,
+ BillAction,
+} from '../common/abilityOption';
+import { useAbilitiesFilter } from '../hooks';
+
+export const getItemPaymentTransactions = () => [
+ {
+ name: 'invoices',
+ label: intl.get('invoices'),
+ permission: {
+ subject: AbilitySubject.Invoice,
+ ability: SaleInvoiceAction.View,
+ },
+ },
+ {
+ name: 'estimates',
+ label: intl.get('estimates'),
+ permission: {
+ subject: AbilitySubject.Estimate,
+ ability: SaleEstimateAction.View,
+ },
+ },
+ {
+ name: 'receipts',
+ label: intl.get('receipts'),
+ permission: {
+ subject: AbilitySubject.Receipt,
+ ability: SaleReceiptAction.View,
+ },
+ },
+ {
+ name: 'bills',
+ label: intl.get('bills'),
+ permission: {
+ subject: AbilitySubject.Bill,
+ ability: BillAction.View,
+ },
+ },
+];
+
+export const useGetItemPaymentTransactionsMenu = () => {
+ const itemTransactionMenu = getItemPaymentTransactions();
+ const abilitiesFilter = useAbilitiesFilter();
+
+ return abilitiesFilter(itemTransactionMenu);
+};
diff --git a/src/common/permissionsSchema.js b/src/common/permissionsSchema.js
new file mode 100644
index 000000000..38347abf8
--- /dev/null
+++ b/src/common/permissionsSchema.js
@@ -0,0 +1,659 @@
+import { chain } from 'lodash';
+import intl from 'react-intl-universal';
+import {
+ AbilitySubject,
+ AccountAction,
+ BillAction,
+ CreditNoteAction,
+ CustomerAction,
+ ExpenseAction,
+ ItemAction,
+ ManualJournalAction,
+ PaymentMadeAction,
+ PaymentReceiveAction,
+ ReportsAction,
+ SaleEstimateAction,
+ SaleInvoiceAction,
+ SaleReceiptAction,
+ VendorAction,
+ VendorCreditAction,
+} from './abilityOption';
+
+export const ModulePermissionsStyle = {
+ Columns: 'columns',
+ Vertical: 'vertical',
+};
+
+const PermissionColumn = {
+ View: 'view',
+ Create: 'create',
+ Delete: 'delete',
+ Edit: 'edit',
+};
+
+export const getPermissionsSchema = () => [
+ {
+ label: intl.get('permissions.items_inventory'),
+ type: ModulePermissionsStyle.Columns,
+ serviceFullAccess: true,
+ columns: [
+ { label: intl.get('permissions.column.view'), key: 'view' },
+ { label: intl.get('permissions.column.create'), key: 'create' },
+ { label: intl.get('permissions.column.edit'), key: 'edit' },
+ { label: intl.get('permissions.column.delete'), key: 'delete' },
+ ],
+ services: [
+ {
+ label: intl.get('permissions.items'),
+ subject: AbilitySubject.Item,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: ItemAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: ItemAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: ItemAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: ItemAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: ItemAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: ItemAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: ItemAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.inventory_adjustment'),
+ subject: AbilitySubject.InventoryAdjustment,
+ permissions: [
+ {
+ label: 'View',
+ key: ItemAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: 'Create',
+ key: ItemAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: ItemAction.View }],
+ },
+ {
+ label: 'Edit',
+ key: ItemAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: ItemAction.Create }],
+ },
+ {
+ label: 'Delete',
+ key: ItemAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: ItemAction.Edit }],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.contacts'),
+ type: ModulePermissionsStyle.Columns,
+ serviceFullAccess: true,
+ moduleFullAccess: true,
+ columns: [
+ { label: intl.get('permissions.column.view'), key: 'view' },
+ { label: intl.get('permissions.column.create'), key: 'create' },
+ { label: intl.get('permissions.column.edit'), key: 'edit' },
+ { label: intl.get('permissions.column.delete'), key: 'delete' },
+ ],
+ services: [
+ {
+ label: intl.get('permissions.customers'),
+ subject: AbilitySubject.Customer,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: CustomerAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: CustomerAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: CustomerAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: CustomerAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: CustomerAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: CustomerAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: CustomerAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.vendors'),
+ subject: AbilitySubject.Vendor,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: VendorAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: VendorAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: VendorAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: VendorAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: VendorAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: VendorAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: VendorAction.Edit }],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.sales'),
+ type: ModulePermissionsStyle.Columns,
+ serviceFullAccess: true,
+ moduleFullAccess: true,
+ columns: [
+ { label: intl.get('permissions.column.view'), key: 'view' },
+ { label: intl.get('permissions.column.create'), key: 'create' },
+ { label: intl.get('permissions.column.edit'), key: 'edit' },
+ { label: intl.get('permissions.column.delete'), key: 'delete' },
+ ],
+ services: [
+ {
+ label: intl.get('permissions.sale_invoice'),
+ subject: AbilitySubject.Invoice,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: SaleInvoiceAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: SaleInvoiceAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: SaleInvoiceAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: SaleInvoiceAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: SaleInvoiceAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: SaleInvoiceAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: SaleInvoiceAction.Edit }],
+ },
+ {
+ label: intl.get('permissions.column.written_off_invoice'),
+ key: SaleInvoiceAction.Writeoff,
+ depend: [{ key: SaleInvoiceAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.sale_estimate'),
+ subject: AbilitySubject.Estimate,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: SaleEstimateAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: SaleEstimateAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: SaleEstimateAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: SaleEstimateAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: SaleEstimateAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: SaleEstimateAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: SaleEstimateAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.sale_receipt'),
+ subject: AbilitySubject.Receipt,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: SaleReceiptAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: SaleReceiptAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: SaleReceiptAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: SaleReceiptAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: SaleReceiptAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: SaleReceiptAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: SaleReceiptAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.credit_note'),
+ subject: AbilitySubject.CreditNote,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: CreditNoteAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: CreditNoteAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: CreditNoteAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: CreditNoteAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: CreditNoteAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: CreditNoteAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: CreditNoteAction.Edit }],
+ },
+ {
+ label: intl.get('permissions.column.refund_credit_note'),
+ key: CreditNoteAction.Refund,
+ depend: [{ key: CreditNoteAction.View }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.payment_receive'),
+ subject: AbilitySubject.PaymentReceive,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: PaymentReceiveAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: PaymentReceiveAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: PaymentReceiveAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: PaymentReceiveAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: PaymentReceiveAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: PaymentReceiveAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: PaymentReceiveAction.Edit }],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.purchases'),
+ type: ModulePermissionsStyle.Columns,
+ serviceFullAccess: true,
+ moduleFullAccess: true,
+ columns: [
+ { label: intl.get('permissions.column.view'), key: 'view' },
+ { label: intl.get('permissions.column.create'), key: 'create' },
+ { label: intl.get('permissions.column.edit'), key: 'edit' },
+ { label: intl.get('permissions.column.delete'), key: 'delete' },
+ ],
+ services: [
+ {
+ label: intl.get('permissions.bills'),
+ subject: AbilitySubject.Bill,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: BillAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: BillAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: BillAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: BillAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: BillAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: BillAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: BillAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.vendor_credits'),
+ subject: AbilitySubject.VendorCredit,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: VendorCreditAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: VendorCreditAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: VendorCreditAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: VendorCreditAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: VendorCreditAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: VendorCreditAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: VendorCreditAction.Edit }],
+ },
+ {
+ label: intl.get('permissions.column.refund_vendor_credit'),
+ key: VendorCreditAction.Refund,
+ depend: [{ key: VendorCreditAction.View }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.payment_made'),
+ subject: AbilitySubject.PaymentMade,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: PaymentMadeAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: PaymentMadeAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: PaymentMadeAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: PaymentMadeAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: PaymentMadeAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: PaymentMadeAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: PaymentMadeAction.Edit }],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.financial_accounting'),
+ type: ModulePermissionsStyle.Columns,
+ serviceFullAccess: true,
+ moduleFullAccess: true,
+ columns: [
+ { label: intl.get('permissions.column.view'), key: 'view' },
+ { label: intl.get('permissions.column.create'), key: 'create' },
+ { label: intl.get('permissions.column.edit'), key: 'edit' },
+ { label: intl.get('permissions.column.delete'), key: 'delete' },
+ ],
+ services: [
+ {
+ label: intl.get('permissions.manual_journals'),
+ subject: AbilitySubject.ManualJournal,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: ManualJournalAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: ManualJournalAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: ManualJournalAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: ManualJournalAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: ManualJournalAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: ManualJournalAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: ManualJournalAction.Edit }],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.chart_of_accounts'),
+ subject: AbilitySubject.Account,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: AccountAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: AccountAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: AccountAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: AccountAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: AccountAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: AccountAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: AccountAction.Edit }],
+ },
+ {
+ label: intl.get('permissions.column.transactions_locking'),
+ key: AccountAction.TransactionsLocking,
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.expenses'),
+ subject: AbilitySubject.Expense,
+ permissions: [
+ {
+ label: intl.get('permissions.column.view'),
+ key: ExpenseAction.View,
+ relatedColumn: PermissionColumn.View,
+ },
+ {
+ label: intl.get('permissions.column.create'),
+ key: ExpenseAction.Create,
+ relatedColumn: PermissionColumn.Create,
+ depend: [{ key: ExpenseAction.View }],
+ },
+ {
+ label: intl.get('permissions.column.edit'),
+ key: ExpenseAction.Edit,
+ relatedColumn: PermissionColumn.Edit,
+ depend: [{ key: ExpenseAction.Create }],
+ },
+ {
+ label: intl.get('permissions.column.delete'),
+ key: ExpenseAction.Delete,
+ relatedColumn: PermissionColumn.Delete,
+ depend: [{ key: ExpenseAction.Edit }],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ label: intl.get('permissions.reports'),
+ type: ModulePermissionsStyle.Vertical,
+ serviceFullAccess: true,
+ moduleFullAccess: true,
+ services: [
+ {
+ label: intl.get('permissions.financial_reports'),
+ subject: AbilitySubject.Report,
+ permissions: [
+ {
+ label: intl.get('permissions.balance_sheet'),
+ key: ReportsAction.READ_BALANCE_SHEET,
+ },
+ {
+ label: intl.get('permissions.trial_balance_sheet'),
+ key: ReportsAction.READ_TRIAL_BALANCE_SHEET,
+ },
+ {
+ label: intl.get('permissions.profit_loss_sheet'),
+ key: ReportsAction.READ_PROFIT_LOSS,
+ },
+ {
+ label: intl.get('permissions.cash_flow_sheet'),
+ key: ReportsAction.READ_CASHFLOW,
+ },
+ {
+ label: intl.get('permissions.journal_sheet'),
+ key: ReportsAction.READ_JOURNAL,
+ },
+ {
+ label: intl.get('permissions.general_ledger'),
+ key: ReportsAction.READ_GENERAL_LEDGET,
+ },
+ {
+ label: intl.get('permissions.a_r_aging_summary_report'),
+ key: ReportsAction.READ_AR_AGING_SUMMARY,
+ },
+ {
+ label: intl.get('permissions.a_r_aging_summary_report'),
+ key: ReportsAction.READ_AP_AGING_SUMMARY,
+ },
+ {
+ label: intl.get('permissions.purchases_by_items'),
+ key: ReportsAction.READ_PURCHASES_BY_ITEMS,
+ },
+ {
+ label: intl.get('permissions.sales_by_items'),
+ key: ReportsAction.READ_SALES_BY_ITEMS,
+ },
+ {
+ label: intl.get('permissions.customers_transactions'),
+ key: ReportsAction.READ_CUSTOMERS_TRANSACTIONS,
+ },
+ {
+ label: intl.get('permissions.vendors_transactions'),
+ key: ReportsAction.READ_VENDORS_TRANSACTIONS,
+ },
+ {
+ label: intl.get('permissions.customers_summary_balance'),
+ key: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE,
+ },
+ {
+ label: intl.get('permissions.vendors_summary_balance'),
+ key: ReportsAction.READ_VENDORS_SUMMARY_BALANCE,
+ },
+ {
+ label: intl.get('permissions.inventory_valuation_summary'),
+ key: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY,
+ },
+ {
+ label: intl.get('permissions.inventory_items_details'),
+ key: ReportsAction.READ_INVENTORY_ITEM_DETAILS,
+ },
+ {
+ label: intl.get('permissions.cashflow_account_transactions'),
+ key: ReportsAction.READ_CASHFLOW_ACCOUNT_TRANSACTION,
+ },
+ ],
+ },
+ ],
+ },
+];
+
+export function getPermissionsSchemaService(subject) {
+ const permissions = getPermissionsSchema();
+
+ return chain(permissions)
+ .map((perm) => perm.services)
+ .flatten()
+ .find((service) => service.subject === subject)
+ .value();
+}
+
+export function getPermissionsSchemaServices() {
+ const permissions = getPermissionsSchema();
+
+ return chain(permissions)
+ .map((module) => module.services)
+ .flatten()
+ .value();
+}
diff --git a/src/common/resourcesTypes.js b/src/common/resourcesTypes.js
index 12ec85401..91e981aa8 100644
--- a/src/common/resourcesTypes.js
+++ b/src/common/resourcesTypes.js
@@ -11,4 +11,6 @@ export const RESOURCES_TYPES = {
EXPENSE: 'expense',
MANUAL_JOURNAL: 'manual_journal',
ACCOUNT: 'account',
+ CREDIT_NOTE: 'credit_note',
+ VENDOR_CREDIT:'vendor_credit'
};
diff --git a/src/common/tables.js b/src/common/tables.js
index 9acd9bd5c..59d6ca127 100644
--- a/src/common/tables.js
+++ b/src/common/tables.js
@@ -14,6 +14,8 @@ export const TABLES = {
EXPENSES: 'expenses',
CASHFLOW_ACCOUNTS: 'cashflow_accounts',
CASHFLOW_Transactions: 'cashflow_transactions',
+ CREDIT_NOTES: 'credit_notes',
+ VENDOR_CREDITS: 'vendor_credits',
};
export const TABLE_SIZE = {
diff --git a/src/components/Alert/index.js b/src/components/Alert/index.js
index 680f8da5a..e0c3dd61a 100644
--- a/src/components/Alert/index.js
+++ b/src/components/Alert/index.js
@@ -1,17 +1,60 @@
import React from 'react';
import clsx from 'classnames';
+import styled from 'styled-components';
-import Style from './style.module.scss';
-
-export function Alert({ title, description, intent }) {
+export function Alert({ title, description, children, intent, className }) {
return (
-
- {title &&
{title}
}
- {description &&
{description}
}
-
+
+ {title && {title}}
+ {description && {description}}
+ {children && {children}}
+
);
}
+
+const AlertRoot = styled.div`
+ border: 1px solid rgb(223, 227, 230);
+ padding: 12px;
+ border-radius: 6px;
+ margin-bottom: 20px;
+
+ ${(props) =>
+ props.intent === 'danger' &&
+ `
+ border-color: rgb(249, 198, 198);
+ background: rgb(255, 248, 248);
+
+ ${AlertDesc} {
+ color: #d95759;
+ }
+ ${AlertTitle} {
+ color: rgb(205, 43, 49);
+ }
+ `}
+
+ ${(props) =>
+ props.intent === 'primary' &&
+ `
+ background: #fff;
+ border-color: #98a8ee;
+
+ ${AlertTitle} {
+ color: #1a3bd4;
+ }
+ ${AlertDesc} {
+ color: #455883;
+ }
+ `}
+`;
+
+export const AlertTitle = styled.h3`
+ color: rgb(17, 24, 28);
+ margin-bottom: 4px;
+ font-size: 14px;
+ font-weight: 600;
+`;
+
+export const AlertDesc = styled.p`
+ color: rgb(104, 112, 118);
+ margin: 0;
+`;
diff --git a/src/components/Alert/style.module.scss b/src/components/Alert/style.module.scss
deleted file mode 100644
index be866addf..000000000
--- a/src/components/Alert/style.module.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-.root {
- border: 1px solid rgb(223, 227, 230);
- padding: 12px;
- border-radius: 6px;
- margin-bottom: 20px;
-
- &_danger {
- border-color: rgb(249, 198, 198);
- background: rgb(255, 248, 248);
-
- .description {
- color: #d95759;
- }
-
- .title {
- color: rgb(205, 43, 49);
- }
- }
-}
-
-
-.title {
- color: rgb(17, 24, 28);
- margin-bottom: 4px;
- font-size: 14px;
- font-weight: 600;
-}
-
-.description {
- color: rgb(104, 112, 118);
- margin: 0;
-}
\ No newline at end of file
diff --git a/src/components/BankAccounts/index.js b/src/components/BankAccounts/index.js
index 0022eddfa..875889670 100644
--- a/src/components/BankAccounts/index.js
+++ b/src/components/BankAccounts/index.js
@@ -4,7 +4,6 @@ import styled from 'styled-components';
import { Classes } from '@blueprintjs/core';
import clsx from 'classnames';
import Icon from '../Icon';
-import { whenRtl, whenLtr } from 'utils/styled-components';
const ACCOUNT_TYPE = {
CASH: 'cash',
@@ -185,9 +184,7 @@ const MetaLineValue = styled.div`
text-align: center;
color: rgb(23, 43, 77);
font-size: 11px;
-
- ${whenLtr(`margin-left: auto;`)}
- ${whenRtl(`margin-right: auto;`)}
+ margin-left: auto;
`;
const BankAccountMeta = styled.div`
@@ -204,7 +201,5 @@ const AccountIconWrap = styled.div`
position: absolute;
top: 14px;
color: #abb3bb;
-
- ${whenLtr(`right: 12px;`)}
- ${whenRtl(`left: 12px;`)}
+ right: 12px;
`;
diff --git a/src/components/Button/ButtonLink.js b/src/components/Button/ButtonLink.js
index 655cdc615..739f12ecc 100644
--- a/src/components/Button/ButtonLink.js
+++ b/src/components/Button/ButtonLink.js
@@ -5,6 +5,7 @@ export const ButtonLink = styled.button`
border: 0;
background: transparent;
cursor: pointer;
+ text-align: inherit;
&:hover,
&:active {
diff --git a/src/components/Card.js b/src/components/Card.js
deleted file mode 100644
index 65dd41eed..000000000
--- a/src/components/Card.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react';
-import classNames from 'classnames';
-
-export default function Card({ className, children }) {
- return {children}
;
-}
diff --git a/src/components/Card/index.js b/src/components/Card/index.js
new file mode 100644
index 000000000..598085686
--- /dev/null
+++ b/src/components/Card/index.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import styled from 'styled-components';
+
+export function Card({ className, children }) {
+ return {children};
+}
+
+const CardRoot = styled.div`
+ padding: 15px;
+ margin: 15px;
+ background: #fff;
+ border: 1px solid #d2dce2;
+`;
+
+export const CardFooterActions = styled.div`
+ padding-top: 16px;
+ border-top: 1px solid #e0e7ea;
+ margin-top: 30px;
+
+ .bp3-button {
+ min-width: 70px;
+
+ + .bp3-button {
+ margin-left: 10px;
+ }
+ }
+`;
diff --git a/src/components/CommercialDoc/index.js b/src/components/CommercialDoc/index.js
new file mode 100644
index 000000000..c8e2c593b
--- /dev/null
+++ b/src/components/CommercialDoc/index.js
@@ -0,0 +1,25 @@
+import styled from 'styled-components';
+import { Card } from '../Card';
+import DataTable from '../DataTable';
+
+export const CommercialDocBox = styled(Card)`
+ padding: 22px 20px;
+`;
+
+export const CommercialDocHeader = styled.div`
+ margin-bottom: 25px;
+`;
+
+export const CommercialDocTopHeader = styled.div`
+ margin-bottom: 25px;
+`;
+
+export const CommercialDocEntriesTable = styled(DataTable)`
+ .tbody .tr:last-child .td {
+ border-bottom: 1px solid #d2dce2;
+ }
+`;
+
+export const CommercialDocFooter = styled.div`
+ margin-top: 25px;
+`;
diff --git a/src/components/Customers/CustomerDrawerLink.js b/src/components/Customers/CustomerDrawerLink.js
new file mode 100644
index 000000000..e99c20244
--- /dev/null
+++ b/src/components/Customers/CustomerDrawerLink.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import * as R from 'ramda';
+
+import { ButtonLink } from 'components';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+function CustomerDrawerLinkComponent({
+ // #ownProps
+ children,
+ customerId,
+
+ // #withDrawerActions
+ openDrawer,
+}) {
+ // Handle view customer drawer.
+ const handleCustomerDrawer = () => {
+ openDrawer('customer-details-drawer', { customerId });
+ };
+
+ return {children};
+}
+
+export const CustomerDrawerLink = R.compose(withDrawerActions)(
+ CustomerDrawerLinkComponent,
+);
diff --git a/src/components/Customers/index.js b/src/components/Customers/index.js
new file mode 100644
index 000000000..124141b39
--- /dev/null
+++ b/src/components/Customers/index.js
@@ -0,0 +1 @@
+export * from './CustomerDrawerLink';
diff --git a/src/components/Dashboard/DashboardActionsBar.js b/src/components/Dashboard/DashboardActionsBar.js
index b0ed85942..5d1795d5d 100644
--- a/src/components/Dashboard/DashboardActionsBar.js
+++ b/src/components/Dashboard/DashboardActionsBar.js
@@ -1,16 +1,19 @@
import React from 'react';
-import classnames from 'classnames';
+import clsx from 'classnames';
import { Navbar } from '@blueprintjs/core';
-export default function DashboardActionsBar({ children, name }) {
+export default function DashboardActionsBar({ className, children, name }) {
return (
- {children}
+ {children}
);
}
diff --git a/src/components/Dashboard/DashboardThemeProvider.js b/src/components/Dashboard/DashboardThemeProvider.js
index 23300ddb9..7a4289e75 100644
--- a/src/components/Dashboard/DashboardThemeProvider.js
+++ b/src/components/Dashboard/DashboardThemeProvider.js
@@ -1,9 +1,16 @@
import React from 'react';
-import { ThemeProvider } from 'styled-components';
+import { ThemeProvider, StyleSheetManager } from 'styled-components';
+import rtlcss from 'stylis-rtlcss';
import { useAppIntlContext } from '../AppIntlProvider';
export function DashboardThemeProvider({ children }) {
const { direction } = useAppIntlContext();
- return {children};
+ return (
+
+ {children}
+
+ );
}
diff --git a/src/components/Datatable/TableWrapper.js b/src/components/Datatable/TableWrapper.js
index 78646ea03..d98fab9b0 100644
--- a/src/components/Datatable/TableWrapper.js
+++ b/src/components/Datatable/TableWrapper.js
@@ -16,6 +16,7 @@ export default function TableWrapper({ children }) {
expandable,
virtualizedRows,
className,
+ styleName,
size,
},
} = useContext(TableContext);
@@ -28,6 +29,7 @@ export default function TableWrapper({ children }) {
'is-expandable': expandable,
'is-loading': loading,
'has-virtualized-rows': virtualizedRows,
+ [`table--${styleName}`]: styleName,
})}
>
diff --git a/src/components/Details/index.js b/src/components/Details/index.js
index ef1690f3c..ef480e1f2 100644
--- a/src/components/Details/index.js
+++ b/src/components/Details/index.js
@@ -17,6 +17,7 @@ const useDetailsMenuContext = () => React.useContext(DetailsMenuContext);
export function DetailsMenu({
children,
direction = DIRECTION.VERTICAL,
+ textAlign,
minLabelSize,
className,
}) {
@@ -27,6 +28,7 @@ export function DetailsMenu({
{
'details-menu--vertical': direction === DIRECTION.VERTICAL,
'details-menu--horizantal': direction === DIRECTION.HORIZANTAL,
+ [`align-${textAlign}`]: textAlign,
},
className,
)}
diff --git a/src/components/Dialog/DialogFooterActions.js b/src/components/Dialog/DialogFooterActions.js
index e24461203..bf7514527 100644
--- a/src/components/Dialog/DialogFooterActions.js
+++ b/src/components/Dialog/DialogFooterActions.js
@@ -2,6 +2,10 @@ import React from 'react';
import styled from 'styled-components';
import { Classes } from '@blueprintjs/core';
+/**
+ * Dialog footer actions.
+ * @returns {React.JSX}
+ */
export function DialogFooterActions({ alignment = 'right', children }) {
return (
;
+}
+
+const DialogFooterRoot = styled.div`
+ flex: 0 0 auto;
+ margin: 0 20px;
+`;
+
const DialogFooterActionsRoot = styled.div`
${(props) =>
props.alignment === 'right' ? 'margin-left: auto;' : 'margin-right: auto;'};
diff --git a/src/components/DialogsContainer.js b/src/components/DialogsContainer.js
index 871e38a58..d9d3609c5 100644
--- a/src/components/DialogsContainer.js
+++ b/src/components/DialogsContainer.js
@@ -25,7 +25,13 @@ import NotifyReceiptViaSMSDialog from '../containers/Dialogs/NotifyReceiptViaSMS
import NotifyEstimateViaSMSDialog from '../containers/Dialogs/NotifyEstimateViaSMSDialog';
import NotifyPaymentReceiveViaSMSDialog from '../containers/Dialogs/NotifyPaymentReceiveViaSMSDialog';
import SMSMessageDialog from '../containers/Dialogs/SMSMessageDialog';
-import TransactionsLockingDialog from '../containers/Dialogs/TransactionsLockingDialog';
+import RefundCreditNoteDialog from '../containers/Dialogs/RefundCreditNoteDialog';
+import RefundVendorCreditDialog from '../containers/Dialogs/RefundVendorCreditDialog';
+import ReconcileCreditNoteDialog from '../containers/Dialogs/ReconcileCreditNoteDialog';
+import ReconcileVendorCreditDialog from '../containers/Dialogs/ReconcileVendorCreditDialog';
+import LockingTransactionsDialog from '../containers/Dialogs/LockingTransactionsDialog';
+import UnlockingTransactionsDialog from '../containers/Dialogs/UnlockingTransactionsDialog';
+import UnlockingPartialTransactionsDialog from '../containers/Dialogs/UnlockingPartialTransactionsDialog';
/**
* Dialogs container.
@@ -59,7 +65,15 @@ export default function DialogsContainer() {
-
+
+
+
+
+
+
+
);
}
diff --git a/src/components/Drawer/DrawerActionsBar.js b/src/components/Drawer/DrawerActionsBar.js
new file mode 100644
index 000000000..d79be8b16
--- /dev/null
+++ b/src/components/Drawer/DrawerActionsBar.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import styled from 'styled-components';
+
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+
+export function DrawerActionsBar({ ...props }) {
+ return ;
+}
+
+const DrawerActionsBarRoot = styled(DashboardActionsBar)`
+ border-bottom: 1px solid #d9d9da;
+`;
diff --git a/src/components/Drawer/DrawerMainTabs.js b/src/components/Drawer/DrawerMainTabs.js
index 89ab0a52c..d2052e1f2 100644
--- a/src/components/Drawer/DrawerMainTabs.js
+++ b/src/components/Drawer/DrawerMainTabs.js
@@ -1,15 +1,54 @@
import React from 'react';
import { Tabs } from '@blueprintjs/core';
+import styled from 'styled-components';
/**
* Drawer main tabs.
*/
export function DrawerMainTabs({ children, ...restProps }) {
return (
-
+
{children}
-
+
);
}
+
+const DrawerMainTabsRoot = styled.div`
+ .bp3-tabs {
+ .bp3-tab-list {
+ position: relative;
+ background-color: #fff;
+ padding: 0 15px;
+ border-bottom: 2px solid #e1e2e8;
+
+ > *:not(:last-child) {
+ margin-right: 25px;
+ }
+
+ &.bp3-large > .bp3-tab {
+ font-size: 15px;
+ color: #7f8596;
+ margin: 0 1rem;
+
+ &[aria-selected='true'],
+ &:not([aria-disabled='true']):hover {
+ color: #0052cc;
+ }
+ }
+ .bp3-tab-indicator-wrapper .bp3-tab-indicator {
+ height: 2px;
+ bottom: -2px;
+ }
+ }
+
+ .bp3-tab-panel {
+ margin-top: 0;
+
+ .card {
+ margin: 15px;
+ }
+ }
+ }
+`;
diff --git a/src/components/Drawer/index.js b/src/components/Drawer/index.js
index 005735517..d39c1d758 100644
--- a/src/components/Drawer/index.js
+++ b/src/components/Drawer/index.js
@@ -13,3 +13,5 @@ export function DrawerLoading({ loading, mount = false, children }) {
export function DrawerBody({ children }) {
return {children}
;
}
+
+export * from './DrawerActionsBar';
\ No newline at end of file
diff --git a/src/components/DrawersContainer.js b/src/components/DrawersContainer.js
index 135dcb8a3..e508519bd 100644
--- a/src/components/DrawersContainer.js
+++ b/src/components/DrawersContainer.js
@@ -17,6 +17,10 @@ import CashflowTransactionDetailDrawer from '../containers/Drawers/CashflowTrans
import QuickCreateCustomerDrawer from '../containers/Drawers/QuickCreateCustomerDrawer';
import QuickCreateItemDrawer from '../containers/Drawers/QuickCreateItemDrawer';
import QuickWriteVendorDrawer from '../containers/Drawers/QuickWriteVendorDrawer';
+import CreditNoteDetailDrawer from '../containers/Drawers/CreditNoteDetailDrawer';
+import VendorCreditDetailDrawer from '../containers/Drawers/VendorCreditDetailDrawer';
+import RefundCreditNoteDetailDrawer from '../containers/Drawers/RefundCreditNoteDetailDrawer';
+import RefundVendorCreditDetailDrawer from '../containers/Drawers/RefundVendorCreditDetailDrawer';
import { DRAWERS } from 'common/drawers';
@@ -47,6 +51,14 @@ export default function DrawersContainer() {
+
+
+
+
);
}
diff --git a/src/components/Forms/FormikObserver.js b/src/components/Forms/FormikObserver.js
new file mode 100644
index 000000000..a93b06864
--- /dev/null
+++ b/src/components/Forms/FormikObserver.js
@@ -0,0 +1,14 @@
+
+import { useDeepCompareEffect } from 'hooks/utils';
+
+export function FormikObserver({ onChange, values }) {
+ useDeepCompareEffect(() => {
+ onChange(values);
+ }, [values]);
+
+ return null;
+}
+
+FormikObserver.defaultProps = {
+ onChange: () => null,
+};
diff --git a/src/components/Forms/index.js b/src/components/Forms/index.js
index 8deddad40..c531c474b 100644
--- a/src/components/Forms/index.js
+++ b/src/components/Forms/index.js
@@ -1 +1,2 @@
-export * from './FormObserver';
\ No newline at end of file
+export * from './FormObserver';
+export * from './FormikObserver';
\ No newline at end of file
diff --git a/src/components/Preferences/PreferencesPage.js b/src/components/Preferences/PreferencesPage.js
index a0e23dc97..f6be83dda 100644
--- a/src/components/Preferences/PreferencesPage.js
+++ b/src/components/Preferences/PreferencesPage.js
@@ -1,6 +1,8 @@
import React from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import classNames from 'classnames';
+import * as R from 'ramda';
+
import { CLASSES } from 'common/classes';
import PreferencesTopbar from 'components/Preferences/PreferencesTopbar';
@@ -8,18 +10,28 @@ import PreferencesContentRoute from 'components/Preferences/PreferencesContentRo
import DashboardErrorBoundary from 'components/Dashboard/DashboardErrorBoundary';
import PreferencesSidebar from 'components/Preferences/PreferencesSidebar';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+
import 'style/pages/Preferences/Page.scss';
/**
* Preferences page.
*/
-export default function PreferencesPage() {
+function PreferencesPage({ toggleSidebarExpand }) {
+ // Shrink the dashboard sidebar once open application preferences page.
+ React.useEffect(() => {
+ toggleSidebarExpand(false);
+ }, [toggleSidebarExpand]);
+
return (
-
+
@@ -32,3 +44,5 @@ export default function PreferencesPage() {
);
}
+
+export default R.compose(withDashboardActions)(PreferencesPage);
diff --git a/src/components/Table/index.js b/src/components/Table/index.js
new file mode 100644
index 000000000..9c5afe084
--- /dev/null
+++ b/src/components/Table/index.js
@@ -0,0 +1,33 @@
+import styled from 'styled-components';
+
+export const Table = styled.table`
+ width: 100%;
+ vertical-align: top;
+ border-color: #dee2e6;
+ border-spacing: 0;
+`;
+export const TBody = styled.tbody``;
+export const TR = styled.tr``;
+export const TD = styled.td`
+ padding: 0.5rem 0.5rem;
+ border-bottom-width: 1px;
+ border-bottom-color: inherit;
+ border-bottom-style: solid;
+
+ ${(props) =>
+ props.textAlign === 'right' &&
+ `
+ text-align: right;`}
+`;
+
+export const TRDarkSingleLine = styled(TR)`
+ ${TD} {
+ border-bottom: 1px solid #000;
+ }
+`;
+
+export const TRDarkDoubleLines = styled(TR)`
+ ${TD} {
+ border-bottom: 3px double #000;
+ }
+`;
diff --git a/src/components/Tags/CurrencyTag.js b/src/components/Tags/CurrencyTag.js
new file mode 100644
index 000000000..a427c0230
--- /dev/null
+++ b/src/components/Tags/CurrencyTag.js
@@ -0,0 +1,11 @@
+import styled from 'styled-components';
+
+export const CurrencyTag = styled.span`
+ background: #3e9215;
+ color: #fff;
+ display: inline-block;
+ border-radius: 3px;
+ padding: 2px 4px;
+ line-height: 1;
+ margin-left: 4px;
+`;
diff --git a/src/components/Tags/index.js b/src/components/Tags/index.js
new file mode 100644
index 000000000..7eca83954
--- /dev/null
+++ b/src/components/Tags/index.js
@@ -0,0 +1,3 @@
+
+
+export * from './CurrencyTag';
\ No newline at end of file
diff --git a/src/components/TextStatus/index.js b/src/components/TextStatus/index.js
new file mode 100644
index 000000000..186956a41
--- /dev/null
+++ b/src/components/TextStatus/index.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import styled from 'styled-components';
+
+export function TextStatus({ intent, children }) {
+ return
{children};
+}
+
+const TextStatusRoot = styled.span`
+ ${(props) =>
+ props.intent === 'warning' &&
+ `
+ color: #ec5b0a;`}
+
+ ${(props) =>
+ props.intent === 'success' &&
+ `
+ color: #2ba01d;`}
+
+ ${(props) =>
+ props.intent === 'none' &&
+ `
+ color: #777;`}
+
+ ${(props) =>
+ props.intent === 'primary' &&
+ `
+ color: #1652c8;`}
+`;
diff --git a/src/components/TotalLines/TotalLines.module.scss b/src/components/TotalLines/TotalLines.module.scss
deleted file mode 100644
index 5c92246b5..000000000
--- a/src/components/TotalLines/TotalLines.module.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-.total_lines {}
-
-
-.total_line {
- display: flex;
- border-bottom: 1px solid #d2dde2;
-
- :global .amount,
- :global .title{
- padding: 8px;
- }
-}
\ No newline at end of file
diff --git a/src/components/TotalLines/index.js b/src/components/TotalLines/index.js
index 793f70c0d..1b2d88fc6 100644
--- a/src/components/TotalLines/index.js
+++ b/src/components/TotalLines/index.js
@@ -1,23 +1,93 @@
import React from 'react';
-import clsx from 'classnames';
+import styled from 'styled-components';
-import TotalLinesCls from './TotalLines.module.scss';
+export const TotalLineBorderStyle = {
+ SingleDark: 'SingleDark',
+ DoubleDark: 'DoubleDark',
+};
-export function TotalLines({ children, className }) {
+export const TotalLineTextStyle = {
+ Regular: 'Regular',
+ Bold: 'Bold',
+};
+
+export function TotalLines({
+ children,
+ amountColWidth,
+ labelColWidth,
+ className,
+}) {
return (
-
+
{children}
-
+
);
}
-export function TotalLine({ title, value, className }) {
+export function TotalLine({ title, value, borderStyle, textStyle, className }) {
return (
-
+
);
}
+
+export const TotalLinesRoot = styled.div`
+ display: table;
+
+ ${(props) =>
+ props.amountColWidth &&
+ `
+ .amount{
+ width: ${props.amountColWidth}
+ }
+ `}
+
+ ${(props) =>
+ props.labelColWidth &&
+ `
+ .title{
+ width: ${props.labelColWidth}
+ }
+ `}
+`;
+
+export const TotalLineRoot = styled.div`
+ display: table-row;
+
+ .amount,
+ .title {
+ display: table-cell;
+ padding: 8px;
+ border-bottom: 1px solid #d2dde2;
+
+ ${(props) =>
+ props.borderStyle === TotalLineBorderStyle.DoubleDark &&
+ `
+ border-bottom: 3px double #000;
+ `}
+ ${(props) =>
+ props.borderStyle === TotalLineBorderStyle.SingleDark &&
+ `
+ border-bottom: 1px double #000;
+ `}
+ ${(props) =>
+ props.textStyle === TotalLineTextStyle.Bold &&
+ `
+ font-weight: 600;
+ `}
+ }
+
+ .amount {
+ text-align: right;
+ }
+`;
diff --git a/src/components/Typo/Paragraph.js b/src/components/Typo/Paragraph.js
new file mode 100644
index 000000000..526425de3
--- /dev/null
+++ b/src/components/Typo/Paragraph.js
@@ -0,0 +1,6 @@
+import React from 'react';
+import clsx from 'classnames';
+
+export function Paragraph({ className, children }) {
+ return
{children}
;
+}
\ No newline at end of file
diff --git a/src/components/Typo/index.js b/src/components/Typo/index.js
new file mode 100644
index 000000000..6d06a82b4
--- /dev/null
+++ b/src/components/Typo/index.js
@@ -0,0 +1,2 @@
+
+export * from './Paragraph';
\ No newline at end of file
diff --git a/src/components/Utils/Join.js b/src/components/Utils/Join.js
new file mode 100644
index 000000000..a2314599e
--- /dev/null
+++ b/src/components/Utils/Join.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+export function Join({ items, sep }) {
+ return items.length > 0
+ ? items.reduce((result, item) => (
+ <>
+ {result}
+ {sep}
+ {item}
+ >
+ ))
+ : null;
+}
diff --git a/src/components/Utils/index.js b/src/components/Utils/index.js
index f1104e044..5be485ebc 100644
--- a/src/components/Utils/index.js
+++ b/src/components/Utils/index.js
@@ -1,4 +1,5 @@
export * from './FormatNumber';
-export * from './FormatDate';
\ No newline at end of file
+export * from './FormatDate';
+export * from './Join';
\ No newline at end of file
diff --git a/src/components/Vendors/VendorDrawerLink.js b/src/components/Vendors/VendorDrawerLink.js
new file mode 100644
index 000000000..91b528e6f
--- /dev/null
+++ b/src/components/Vendors/VendorDrawerLink.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import * as R from 'ramda';
+
+import { ButtonLink } from 'components';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+function VendorDrawerLinkComponent({
+ // #ownProps
+ children,
+ vendorId,
+
+ // #withDrawerActions
+ openDrawer,
+}) {
+ // Handle view customer drawer.
+ const handleVendorDrawer = () => {
+ openDrawer('vendor-details-drawer', { vendorId });
+ };
+
+ return
{children};
+}
+
+export const VendorDrawerLink = R.compose(withDrawerActions)(VendorDrawerLinkComponent);
diff --git a/src/components/Vendors/index.js b/src/components/Vendors/index.js
new file mode 100644
index 000000000..8f9cc7544
--- /dev/null
+++ b/src/components/Vendors/index.js
@@ -0,0 +1 @@
+export * from './VendorDrawerLink'
\ No newline at end of file
diff --git a/src/components/index.js b/src/components/index.js
index f30398145..5e14f2288 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -54,7 +54,6 @@ import Postbox from './Postbox';
import AccountsSuggestField from './AccountsSuggestField';
import MaterialProgressBar from './MaterialProgressBar';
import { MoneyFieldCell } from './DataTableCells';
-import Card from './Card';
import AvaterCell from './AvaterCell';
import { ItemsMultiSelect } from './Items';
@@ -87,6 +86,15 @@ export * from './Button';
export * from './IntersectionObserver';
export * from './SMSPreview';
export * from './Contacts';
+export * from './Utils/Join';
+export * from './Typo';
+export * from './TextStatus';
+export * from './Tags';
+export * from './CommercialDoc';
+export * from './Card';
+export * from './Customers'
+export * from './Vendors'
+export * from './Table';
const Hint = FieldHint;
@@ -153,7 +161,6 @@ export {
MaterialProgressBar,
MoneyFieldCell,
ItemsMultiSelect,
- Card,
AvaterCell,
MoreMenuItems,
};
diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js
index a847f8e52..1ea65f2a0 100644
--- a/src/config/sidebarMenu.js
+++ b/src/config/sidebarMenu.js
@@ -158,6 +158,10 @@ export default [
ability: SaleReceiptAction.View,
},
},
+ {
+ text: ,
+ href: '/credit-notes',
+ },
{
text:
,
href: '/payment-receives',
@@ -233,6 +237,10 @@ export default [
ability: SaleReceiptAction.Create,
},
},
+ {
+ text:
,
+ href: '/credit-notes/new',
+ },
{
text:
,
href: '/payment-receives/new',
@@ -254,6 +262,10 @@ export default [
ability: BillAction.View,
},
},
+ {
+ text: ,
+ href: '/vendor-credits',
+ },
{
text:
,
href: '/payment-mades',
@@ -298,6 +310,14 @@ export default [
ability: BillAction.Create,
},
},
+ {
+ text:
,
+ href: '/vendor-credits/new',
+ permission: {
+ subject: AbilitySubject.Bill,
+ ability: BillAction.Create,
+ },
+ },
{
text:
,
href: '/payment-mades/new',
@@ -408,10 +428,10 @@ export default [
{
text: ,
href: '/transactions-locking',
- permission: {
- subject: AbilitySubject.ManualJournal,
- ability: ManualJournalAction.TransactionLocking,
- },
+ // permission: {
+ // subject: AbilitySubject.ManualJournal,
+ // ability: ManualJournalAction.TransactionLocking,
+ // },
},
{
text:
,
diff --git a/src/containers/Accounting/JournalsLanding/ManualJournalsListProvider.js b/src/containers/Accounting/JournalsLanding/ManualJournalsListProvider.js
index 595e9e3fb..15052ec05 100644
--- a/src/containers/Accounting/JournalsLanding/ManualJournalsListProvider.js
+++ b/src/containers/Accounting/JournalsLanding/ManualJournalsListProvider.js
@@ -46,8 +46,7 @@ function ManualJournalsListProvider({ query, tableStateChanged, ...props }) {
isEmptyStatus,
};
- const isPageLoading =
- isManualJournalsLoading || isViewsLoading || isResourceMetaLoading;
+ const isPageLoading = isViewsLoading || isResourceMetaLoading;
return (
diff --git a/src/containers/Accounting/JournalsLanding/components.js b/src/containers/Accounting/JournalsLanding/components.js
index fab711e72..1384e3a87 100644
--- a/src/containers/Accounting/JournalsLanding/components.js
+++ b/src/containers/Accounting/JournalsLanding/components.js
@@ -101,13 +101,13 @@ export const StatusAccessor = (row) => {
return (
-
+
-
+
@@ -179,6 +179,7 @@ export const ActionsMenu = ({
/>
+
}
diff --git a/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js b/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js
index a95429551..469f722d1 100644
--- a/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js
+++ b/src/containers/Accounting/MakeJournal/MakeJournalFormFloatingActions.js
@@ -151,6 +151,7 @@ export default function MakeJournalFloatingAction() {
disabled={isSubmitting}
intent={Intent.PRIMARY}
onClick={handleSubmitPublishBtnClick}
+ style={{ minWidth: '85px' }}
text={}
/>
{
+ closeAlert(name);
+ };
+ const handleConfirmCreditNoteDelete = () => {
+ deleteCreditNoteMutate(creditNoteId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('credit_note.alert.delete_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDrawer('credit-note-detail-drawer');
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ handleDeleteErrors(errors);
+ },
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDeleteAlert}
+ onConfirm={handleConfirmCreditNoteDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+ withDrawerActions,
+)(CreditNoteDeleteAlert);
diff --git a/src/containers/Alerts/CreditNotes/CreditNoteOpenedAlert.js b/src/containers/Alerts/CreditNotes/CreditNoteOpenedAlert.js
new file mode 100644
index 000000000..58b9e8554
--- /dev/null
+++ b/src/containers/Alerts/CreditNotes/CreditNoteOpenedAlert.js
@@ -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 { useOpenCreditNote } from 'hooks/query';
+import { AppToaster } from 'components';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * Credit note opened alert.
+ */
+function CreditNoteOpenedAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { creditNoteId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: openCreditNoteMutate, isLoading } = useOpenCreditNote();
+
+ // Handle cancel opened credit note alert.
+ const handleAlertCancel = () => {
+ closeAlert(name);
+ };
+
+ // Handle confirm credit note opened.
+ const handleAlertConfirm = () => {
+ openCreditNoteMutate(creditNoteId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('credit_note_opened.alert.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch((error) => {})
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={isOpen}
+ onCancel={handleAlertCancel}
+ onConfirm={handleAlertConfirm}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(CreditNoteOpenedAlert);
diff --git a/src/containers/Alerts/CreditNotes/ReconcileCreditNoteDeleteAlert.js b/src/containers/Alerts/CreditNotes/ReconcileCreditNoteDeleteAlert.js
new file mode 100644
index 000000000..7322fbf9d
--- /dev/null
+++ b/src/containers/Alerts/CreditNotes/ReconcileCreditNoteDeleteAlert.js
@@ -0,0 +1,87 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { useDeleteReconcileCredit } from 'hooks/query';
+import { handleDeleteErrors } from '../../Sales/CreditNotes/CreditNotesLanding/utils';
+import { compose } from 'utils';
+
+/**
+ * Reconcile credit note delete alert.
+ */
+function ReconcileCreditNoteDeleteAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { creditNoteId },
+
+ // #withAlertActions
+ closeAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+}) {
+ const { isLoading, mutateAsync: deleteReconcileCreditMutate } =
+ useDeleteReconcileCredit();
+
+ // handle cancel delete credit note alert.
+ const handleCancelDeleteAlert = () => {
+ closeAlert(name);
+ };
+
+ const handleConfirmVendorCreditDelete = () => {
+ deleteReconcileCreditMutate(creditNoteId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('reconcile_credit_note.alert.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ // handleDeleteErrors(errors);
+ },
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDeleteAlert}
+ onConfirm={handleConfirmVendorCreditDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+ withDrawerActions,
+)(ReconcileCreditNoteDeleteAlert);
diff --git a/src/containers/Alerts/CreditNotes/RefundCreditNoteDeleteAlert.js b/src/containers/Alerts/CreditNotes/RefundCreditNoteDeleteAlert.js
new file mode 100644
index 000000000..da575c2af
--- /dev/null
+++ b/src/containers/Alerts/CreditNotes/RefundCreditNoteDeleteAlert.js
@@ -0,0 +1,76 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+import { useDeleteRefundCreditNote } from 'hooks/query';
+
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { compose } from 'utils';
+
+/**
+ * Refund credit transactions delete alert
+ */
+function RefundCreditNoteDeleteAlert({
+ name,
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { creditNoteId },
+ // #withAlertActions
+ closeAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+}) {
+ const { mutateAsync: deleteRefundCreditMutate, isLoading } =
+ useDeleteRefundCreditNote();
+
+ // Handle cancel delete.
+ const handleCancelAlert = () => {
+ closeAlert(name);
+ };
+
+ // Handle confirm delete .
+ const handleConfirmRefundCreditDelete = () => {
+ deleteRefundCreditMutate(creditNoteId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('refund_credit_transactions.alert.delete_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDrawer('refund-credit-detail-drawer');
+ })
+ .catch(() => {})
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelAlert}
+ onConfirm={handleConfirmRefundCreditDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+ withDrawerActions,
+)(RefundCreditNoteDeleteAlert);
diff --git a/src/containers/Alerts/TransactionLocking/cancelUnlockingPartialAlert.js b/src/containers/Alerts/TransactionLocking/cancelUnlockingPartialAlert.js
new file mode 100644
index 000000000..d3e8ba0bc
--- /dev/null
+++ b/src/containers/Alerts/TransactionLocking/cancelUnlockingPartialAlert.js
@@ -0,0 +1,81 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+
+import { useCancelUnlockingPartialTransactions } from 'hooks/query';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * Cancel Unlocking partial transactions alerts.
+ */
+function CancelUnlockingPartialTarnsactions({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { module },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: cancelUnlockingPartial, isLoading } =
+ useCancelUnlockingPartialTransactions();
+
+ // Handle cancel.
+ const handleCancel = () => {
+ closeAlert(name);
+ };
+
+ // Handle confirm.
+ const handleConfirm = () => {
+ const values = {
+ module: module,
+ };
+ cancelUnlockingPartial(values)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get(
+ 'unlocking_partial_transactions.alert.cancel_message',
+ ),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {},
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancel}
+ onConfirm={handleConfirm}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(CancelUnlockingPartialTarnsactions);
diff --git a/src/containers/Alerts/VendorCeditNotes/ReconcileVendorCreditDeleteAlert.js b/src/containers/Alerts/VendorCeditNotes/ReconcileVendorCreditDeleteAlert.js
new file mode 100644
index 000000000..bf493b47d
--- /dev/null
+++ b/src/containers/Alerts/VendorCeditNotes/ReconcileVendorCreditDeleteAlert.js
@@ -0,0 +1,83 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { useDeleteReconcileVendorCredit } from 'hooks/query';
+import { compose } from 'utils';
+
+/**
+ * Reconcile vendor credit delete alert.
+ */
+function ReconcileVendorCreditDeleteAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { vendorCreditId },
+
+ // #withAlertActions
+ closeAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+}) {
+ const { isLoading, mutateAsync: deleteReconcileVendorCreditMutate } =
+ useDeleteReconcileVendorCredit();
+
+ // handle cancel delete credit note alert.
+ const handleCancelDeleteAlert = () => {
+ closeAlert(name);
+ };
+
+ const handleConfirmReconcileVendorCreditDelete = () => {
+ deleteReconcileVendorCreditMutate(vendorCreditId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('reconcile_vendor_credit.alert.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ // closeDrawer('vendor-credit-detail-drawer');
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {},
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDeleteAlert}
+ onConfirm={handleConfirmReconcileVendorCreditDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+ withDrawerActions,
+)(ReconcileVendorCreditDeleteAlert);
diff --git a/src/containers/Alerts/VendorCeditNotes/RefundVendorCreditDeleteAlert.js b/src/containers/Alerts/VendorCeditNotes/RefundVendorCreditDeleteAlert.js
new file mode 100644
index 000000000..4e17eb2ec
--- /dev/null
+++ b/src/containers/Alerts/VendorCeditNotes/RefundVendorCreditDeleteAlert.js
@@ -0,0 +1,78 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+import { useDeleteRefundVendorCredit } from 'hooks/query';
+
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { compose } from 'utils';
+
+/**
+ * Refund Vendor transactions delete alert.
+ */
+function RefundVendorCreditDeleteAlert({
+ name,
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { vendorCreditId },
+ // #withAlertActions
+ closeAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+}) {
+ const { mutateAsync: deleteRefundVendorCreditMutate, isLoading } =
+ useDeleteRefundVendorCredit();
+
+ // Handle cancel delete.
+ const handleCancelAlert = () => {
+ closeAlert(name);
+ };
+
+ // Handle confirm delete .
+ const handleConfirmRefundVendorCreditDelete = () => {
+ deleteRefundVendorCreditMutate(vendorCreditId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get(
+ 'refund_vendor_credit_transactions.alert.delete_message',
+ ),
+ intent: Intent.SUCCESS,
+ });
+ closeDrawer('refund-vendor-detail-drawer');
+ })
+ .catch(() => {})
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelAlert}
+ onConfirm={handleConfirmRefundVendorCreditDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+ withDrawerActions,
+)(RefundVendorCreditDeleteAlert);
diff --git a/src/containers/Alerts/VendorCeditNotes/VendorCreditDeleteAlert.js b/src/containers/Alerts/VendorCeditNotes/VendorCreditDeleteAlert.js
new file mode 100644
index 000000000..165b7000c
--- /dev/null
+++ b/src/containers/Alerts/VendorCeditNotes/VendorCreditDeleteAlert.js
@@ -0,0 +1,84 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
+import { Intent, Alert } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+import { handleDeleteErrors } from '../../Purchases/CreditNotes/CreditNotesLanding/utils';
+import { useDeleteVendorCredit } from 'hooks/query';
+import { compose } from 'utils';
+
+/**
+ * Vendor Credit delete alert.
+ */
+function VendorCreditDeleteAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { vendorCreditId },
+
+ // #withAlertActions
+ closeAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+}) {
+ const { isLoading, mutateAsync: deleteVendorCreditMutate } =
+ useDeleteVendorCredit();
+
+ // handle cancel delete credit note alert.
+ const handleCancelDeleteAlert = () => {
+ closeAlert(name);
+ };
+ const handleConfirmCreditDelete = () => {
+ deleteVendorCreditMutate(vendorCreditId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('vendor_credits.alert.delete_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDrawer('vendor-credit-detail-drawer');
+ })
+ .catch(
+ ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ handleDeleteErrors(errors);
+ },
+ )
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelDeleteAlert}
+ onConfirm={handleConfirmCreditDelete}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+ withDrawerActions,
+)(VendorCreditDeleteAlert);
diff --git a/src/containers/Alerts/VendorCeditNotes/VendorCreditOpenedAlert.js b/src/containers/Alerts/VendorCeditNotes/VendorCreditOpenedAlert.js
new file mode 100644
index 000000000..56c0fe5bf
--- /dev/null
+++ b/src/containers/Alerts/VendorCeditNotes/VendorCreditOpenedAlert.js
@@ -0,0 +1,69 @@
+import React from 'react';
+import { FormattedMessage as T } from 'components';
+import intl from 'react-intl-universal';
+import { Intent, Alert } from '@blueprintjs/core';
+
+import { useOpenVendorCredit } from 'hooks/query';
+import { AppToaster } from 'components';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * Vendor credit opened alert.
+ */
+function VendorCreditOpenedAlert({
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { vendorCreditId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { mutateAsync: openVendorCreditMutate, isLoading } =
+ useOpenVendorCredit();
+
+ // Handle cancel opened credit note alert.
+ const handleAlertCancel = () => {
+ closeAlert(name);
+ };
+
+ // Handle confirm vendor credit as opened.
+ const handleAlertConfirm = () => {
+ openVendorCreditMutate(vendorCreditId)
+ .then(() => {
+ AppToaster.show({
+ message: intl.get('vendor_credit_opened.alert.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch((error) => {})
+ .finally(() => {
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={isOpen}
+ onCancel={handleAlertCancel}
+ onConfirm={handleAlertConfirm}
+ loading={isLoading}
+ >
+
+
+
+
+ );
+}
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(VendorCreditOpenedAlert);
diff --git a/src/containers/AlertsContainer/registered.js b/src/containers/AlertsContainer/registered.js
index d0e77fcfb..57d66288a 100644
--- a/src/containers/AlertsContainer/registered.js
+++ b/src/containers/AlertsContainer/registered.js
@@ -17,6 +17,9 @@ import AccountTransactionsAlerts from '../CashFlow/AccountTransactions/AccountTr
import UsersAlerts from '../Preferences/Users/UsersAlerts';
import CurrenciesAlerts from '../Preferences/Currencies/CurrenciesAlerts';
import RolesAlerts from '../Preferences/Users/Roles/RolesAlerts';
+import CreditNotesAlerts from '../Sales/CreditNotes/CreditNotesAlerts';
+import VendorCreditNotesAlerts from '../Purchases/CreditNotes/VendorCreditNotesAlerts';
+import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts'
export default [
...AccountsAlerts,
@@ -38,4 +41,7 @@ export default [
...UsersAlerts,
...CurrenciesAlerts,
...RolesAlerts,
+ ...CreditNotesAlerts,
+ ...VendorCreditNotesAlerts,
+ ...TransactionsLockingAlerts
];
diff --git a/src/containers/CashFlow/AccountTransactions/AccountTransactionsDataTable.js b/src/containers/CashFlow/AccountTransactions/AccountTransactionsDataTable.js
index f6ebecbe4..8b1621db2 100644
--- a/src/containers/CashFlow/AccountTransactions/AccountTransactionsDataTable.js
+++ b/src/containers/CashFlow/AccountTransactions/AccountTransactionsDataTable.js
@@ -18,7 +18,6 @@ import { useAccountTransactionsContext } from './AccountTransactionsProvider';
import { handleCashFlowTransactionType } from './utils';
import { compose } from 'utils';
-import { whenRtl, whenLtr } from 'utils/styled-components';
/**
* Account transactions data table.
@@ -129,8 +128,7 @@ const CashflowTransactionsTable = styled(DashboardConstrantTable)`
.tbody-inner {
.tr .td:not(:first-child) {
- ${whenLtr(`border-left: 1px solid #e6e6e6;`)}
- ${whenRtl(`border-right: 1px solid #e6e6e6;`)}
+ border-left: 1px solid #e6e6e6;
}
}
}
diff --git a/src/containers/CashFlow/AccountTransactions/AccountTransactionsDetailsBar.js b/src/containers/CashFlow/AccountTransactions/AccountTransactionsDetailsBar.js
index a41068f09..bdec0f6b0 100644
--- a/src/containers/CashFlow/AccountTransactions/AccountTransactionsDetailsBar.js
+++ b/src/containers/CashFlow/AccountTransactions/AccountTransactionsDetailsBar.js
@@ -14,7 +14,6 @@ import { curry } from 'lodash/fp';
import { Icon } from '../../../components';
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
-import { whenRtl, whenLtr } from 'utils/styled-components';
function AccountSwitchButton() {
const { currentAccount } = useAccountTransactionsContext();
@@ -23,7 +22,7 @@ function AccountSwitchButton() {
}
- >
+ >
{currentAccount.name}
);
@@ -161,8 +160,7 @@ const AccountBalanceAmount = styled.span`
font-weight: 600;
display: inline-block;
color: rgb(31, 50, 85);
- ${whenLtr(`margin-left: 10px;`)}
- ${whenRtl(`margin-right: 10px;`)}
+ margin-left: 10px;
`;
const AccountSwitchItemName = styled.div`
@@ -180,7 +178,6 @@ const AccountSwitchItemUpdatedAt = styled.div`
const AccountSwitchButtonBase = styled(Button)`
.bp3-button-text {
- ${whenLtr(`margin-right: 5px;`)}
- ${whenRtl(`margin-left: 5px;`)}
+ margin-right: 5px;
}
`;
diff --git a/src/containers/CashFlow/AccountTransactions/utils.js b/src/containers/CashFlow/AccountTransactions/utils.js
index 59f8b43ea..567422ea6 100644
--- a/src/containers/CashFlow/AccountTransactions/utils.js
+++ b/src/containers/CashFlow/AccountTransactions/utils.js
@@ -71,6 +71,14 @@ export const handleCashFlowTransactionType = (reference, openDrawer) => {
return openDrawer('payment-made-detail-drawer', {
paymentMadeId: reference.reference_id,
});
+ case 'RefundCreditNote':
+ return openDrawer('refund-credit-detail-drawer', {
+ refundTransactionId: reference.reference_id,
+ });
+ case 'RefundVendorCredit':
+ return openDrawer('refund-vendor-detail-drawer', {
+ refundTransactionId: reference.reference_id,
+ });
default:
return openDrawer('cashflow-transaction-drawer', {
diff --git a/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsGrid.js b/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsGrid.js
index cf06161b9..dc6104046 100644
--- a/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsGrid.js
+++ b/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsGrid.js
@@ -271,6 +271,7 @@ function CashflowAccountContextMenu({
+
}
diff --git a/src/containers/Customers/CustomersLanding/CustomersListProvider.js b/src/containers/Customers/CustomersLanding/CustomersListProvider.js
index cd38e45a5..6fcb66ad1 100644
--- a/src/containers/Customers/CustomersLanding/CustomersListProvider.js
+++ b/src/containers/Customers/CustomersLanding/CustomersListProvider.js
@@ -53,7 +53,7 @@ function CustomersListProvider({ tableState, tableStateChanged, ...props }) {
return (
diff --git a/src/containers/Customers/CustomersLanding/components.js b/src/containers/Customers/CustomersLanding/components.js
index 9d878bbf4..2eacc0103 100644
--- a/src/containers/Customers/CustomersLanding/components.js
+++ b/src/containers/Customers/CustomersLanding/components.js
@@ -63,6 +63,7 @@ export function ActionsMenu({
+
}
text={intl.get('delete_customer')}
diff --git a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostEntriesTable.js b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostEntriesTable.js
index bd307ddbb..20f094ed1 100644
--- a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostEntriesTable.js
+++ b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostEntriesTable.js
@@ -1,7 +1,10 @@
import React from 'react';
-import intl from 'react-intl-universal';
-import { MoneyFieldCell, DataTableEditable } from 'components';
+import styled from 'styled-components';
+
+import { DataTableEditable } from 'components';
+
import { compose, updateTableCell } from 'utils';
+import { useAllocateLandedCostEntriesTableColumns } from './utils';
/**
* Allocate landed cost entries table.
@@ -11,42 +14,7 @@ export default function AllocateLandedCostEntriesTable({
entries,
}) {
// Allocate landed cost entries table columns.
- const columns = React.useMemo(
- () => [
- {
- Header: intl.get('item'),
- accessor: 'item.name',
- disableSortBy: true,
- width: '150',
- },
- {
- Header: intl.get('quantity'),
- accessor: 'quantity',
- disableSortBy: true,
- width: '100',
- },
- {
- Header: intl.get('rate'),
- accessor: 'rate',
- disableSortBy: true,
- width: '100',
- },
- {
- Header: intl.get('amount'),
- accessor: 'amount',
- disableSortBy: true,
- width: '100',
- },
- {
- Header: intl.get('cost'),
- accessor: 'cost',
- width: '150',
- Cell: MoneyFieldCell,
- disableSortBy: true,
- },
- ],
- [],
- );
+ const columns = useAllocateLandedCostEntriesTableColumns();
// Handle update data.
const handleUpdateData = React.useCallback(
@@ -60,7 +28,7 @@ export default function AllocateLandedCostEntriesTable({
);
return (
-
);
}
+
+export const AllocateLandeedCostEntriesEditableTable = styled(
+ DataTableEditable,
+)`
+ .table {
+ .thead .tr .th {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ }
+
+ .tbody .tr .td {
+ padding: 0.25rem;
+ }
+ }
+`;
diff --git a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFloatingActions.js b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFloatingActions.js
index de5b7e16e..121f86aa5 100644
--- a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFloatingActions.js
+++ b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFloatingActions.js
@@ -12,12 +12,18 @@ import { useAllocateLandedConstDialogContext } from './AllocateLandedCostDialogP
import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils';
+/**
+ * Allocate landed cost floating actions.
+ * @returns {React.JSX}
+ */
function AllocateLandedCostFloatingActions({
// #withDialogActions
closeDialog,
}) {
// Formik context.
const { isSubmitting } = useFormikContext();
+
+ // Allocate landed cost dialog context.
const { dialogName, costTransactionEntry, formattedUnallocatedCostAmount } =
useAllocateLandedConstDialogContext();
@@ -27,7 +33,7 @@ function AllocateLandedCostFloatingActions({
};
return (
-
+
{costTransactionEntry && (
@@ -43,19 +49,23 @@ function AllocateLandedCostFloatingActions({
-
+
);
}
export default compose(withDialogActions)(AllocateLandedCostFloatingActions);
+const AllocateDialogFooter = styled(DialogFooter)`
+ display: flex;
+`;
+
const UnallocatedAmount = styled.div`
color: #3f5278;
align-self: center;
diff --git a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostForm.js b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostForm.js
index 5cb1a2fa2..e4ac664cd 100644
--- a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostForm.js
+++ b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostForm.js
@@ -11,21 +11,7 @@ import { useAllocateLandedConstDialogContext } from './AllocateLandedCostDialogP
import AllocateLandedCostFormContent from './AllocateLandedCostFormContent';
import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose, transformToForm } from 'utils';
-
-const defaultInitialItem = {
- entry_id: '',
- cost: '',
-};
-
-// Default form initial values.
-const defaultInitialValues = {
- transaction_type: 'Bill',
- transaction_id: '',
- transaction_entry_id: '',
- amount: '',
- allocation_method: 'quantity',
- items: [defaultInitialItem],
-};
+import { defaultInitialValues } from './utils';
/**
* Allocate landed cost form.
@@ -34,13 +20,8 @@ function AllocateLandedCostForm({
// #withDialogActions
closeDialog,
}) {
- const {
- dialogName,
- bill,
- billId,
- createLandedCostMutate,
- unallocatedCostAmount,
- } = useAllocateLandedConstDialogContext();
+ const { dialogName, bill, billId, createLandedCostMutate } =
+ useAllocateLandedConstDialogContext();
// Initial form values.
const initialValues = {
@@ -51,7 +32,6 @@ function AllocateLandedCostForm({
cost: '',
})),
};
-
// Handle form submit.
const handleFormSubmit = (values, { setSubmitting }) => {
setSubmitting(true);
@@ -78,20 +58,33 @@ function AllocateLandedCostForm({
setSubmitting(false);
closeDialog(dialogName);
};
-
// Handle the request error.
- const onError = () => {
+ const onError = (res) => {
+ const { errors } = res.response.data;
setSubmitting(false);
- AppToaster.show({
- message: 'Something went wrong!',
- intent: Intent.DANGER,
- });
+
+ if (
+ errors.some(
+ (e) => e.type === 'COST_AMOUNT_BIGGER_THAN_UNALLOCATED_AMOUNT',
+ )
+ ) {
+ AppToaster.show({
+ message:
+ 'The total located cost is bigger than the transaction line.',
+ intent: Intent.DANGER,
+ });
+ } else {
+ AppToaster.show({
+ message: 'Something went wrong!',
+ intent: Intent.DANGER,
+ });
+ }
};
createLandedCostMutate([billId, form]).then(onSuccess).catch(onError);
};
// Computed validation schema.
- const validationSchema = AllocateLandedCostFormSchema(unallocatedCostAmount);
+ const validationSchema = AllocateLandedCostFormSchema();
return (
+export const AllocateLandedCostFormSchema = () =>
Yup.object().shape({
- transaction_type: Yup.string()
- .required()
- .label(intl.get('transaction_type')),
- transaction_id: Yup.string()
- .required()
- .label(intl.get('transaction_number')),
- transaction_entry_id: Yup.string()
- .required()
- .label(intl.get('transaction_line')),
- amount: Yup.number().max(maxAmount).label(intl.get('amount')),
- allocation_method: Yup.string().required().trim(),
+ transaction_type: Yup.string().label(intl.get('transaction_type')),
+ transaction_date: Yup.date().label(intl.get('transaction_date')),
+ transaction_id: Yup.string().label(intl.get('transaction_number')),
+ transaction_entry_id: Yup.string().label(intl.get('transaction_line')),
+ amount: Yup.number().label(intl.get('amount')),
+ allocation_method: Yup.string().trim(),
items: Yup.array().of(
Yup.object().shape({
entry_id: Yup.number().nullable(),
diff --git a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFormFields.js b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFormFields.js
index d71ebab2c..5dec5e145 100644
--- a/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFormFields.js
+++ b/src/containers/Dialogs/AllocateLandedCostDialog/AllocateLandedCostFormFields.js
@@ -103,8 +103,10 @@ export default function AllocateLandedCostFormFields() {
selectedItem={value}
selectedItemProp={'id'}
textProp={'name'}
- labelProp={'id'}
- defaultText={intl.get('Select transaction')}
+ labelProp={'formatted_unallocated_cost_amount'}
+ defaultText={intl.get(
+ 'landed_cost.dialog.label_select_transaction',
+ )}
popoverProps={{ minimal: true }}
/>
@@ -131,16 +133,17 @@ export default function AllocateLandedCostFormFields() {
>
{
+ onItemSelect={(entry) => {
+ const { id, unallocated_cost_amount: unallocatedAmount } =
+ entry;
const { items, allocation_method } = form.values;
+ form.setFieldValue('amount', unallocatedAmount);
form.setFieldValue('transaction_entry_id', id);
- form.setFieldValue('amount', unallocated_cost_amount);
-
form.setFieldValue(
'items',
allocateCostToEntries(
- unallocated_cost_amount,
+ unallocatedAmount,
allocation_method,
items,
),
@@ -150,7 +153,10 @@ export default function AllocateLandedCostFormFields() {
selectedItem={value}
selectedItemProp={'id'}
textProp={'name'}
- defaultText={intl.get('Select transaction entry')}
+ labelProp={'formatted_unallocated_cost_amount'}
+ defaultText={intl.get(
+ 'landed_cost.dialog.label_select_transaction_entry',
+ )}
popoverProps={{ minimal: true }}
/>
diff --git a/src/containers/Dialogs/AllocateLandedCostDialog/utils.js b/src/containers/Dialogs/AllocateLandedCostDialog/utils.js
index a19fff723..1cfd6775a 100644
--- a/src/containers/Dialogs/AllocateLandedCostDialog/utils.js
+++ b/src/containers/Dialogs/AllocateLandedCostDialog/utils.js
@@ -1,13 +1,25 @@
+import React from 'react';
import { sumBy, round } from 'lodash';
import * as R from 'ramda';
-import { defaultFastFieldShouldUpdate } from 'utils';
+import intl from 'react-intl-universal';
-/**
- * Retrieve the landed cost transaction by the given id.
- */
-export function getCostTransactionById(id, transactions) {
- return transactions.find((trans) => trans.id === id);
-}
+import { defaultFastFieldShouldUpdate } from 'utils';
+import { MoneyFieldCell } from 'components';
+
+export const defaultInitialItem = {
+ entry_id: '',
+ cost: '',
+};
+
+// Default form initial values.
+export const defaultInitialValues = {
+ transaction_type: 'Bill',
+ transaction_id: '',
+ transaction_entry_id: '',
+ amount: '',
+ allocation_method: 'quantity',
+ items: [defaultInitialItem],
+};
/**
* Retrieve transaction entries of the given transaction id.
@@ -17,10 +29,23 @@ export function getEntriesByTransactionId(transactions, id) {
return transaction ? transaction.entries : [];
}
+/**
+ *
+ * @param {*} transaction
+ * @param {*} transactionEntryId
+ * @returns
+ */
export function getTransactionEntryById(transaction, transactionEntryId) {
return transaction.entries.find((entry) => entry.id === transactionEntryId);
}
+/**
+ *
+ * @param {*} total
+ * @param {*} allocateType
+ * @param {*} entries
+ * @returns
+ */
export function allocateCostToEntries(total, allocateType, entries) {
return R.compose(
R.when(
@@ -43,12 +68,12 @@ export function allocateCostToEntries(total, allocateType, entries) {
export function allocateCostByValue(total, entries) {
const totalAmount = sumBy(entries, 'amount');
- const _entries = entries.map((entry) => ({
+ const entriesMapped = entries.map((entry) => ({
...entry,
percentageOfValue: entry.amount / totalAmount,
}));
- return _entries.map((entry) => ({
+ return entriesMapped.map((entry) => ({
...entry,
cost: round(entry.percentageOfValue * total, 2),
}));
@@ -74,6 +99,13 @@ export function allocateCostByQuantity(total, entries) {
}));
}
+/**
+ * Retrieve the landed cost transaction by the given id.
+ */
+export function getCostTransactionById(id, transactions) {
+ return transactions.find((trans) => trans.id === id);
+}
+
/**
* Detarmines the transactions selet field when should update.
*/
@@ -84,7 +116,55 @@ export function transactionsSelectShouldUpdate(newProps, oldProps) {
);
}
-
+/**
+ *
+ * @param {*} entries
+ * @returns
+ */
export function resetAllocatedCostEntries(entries) {
return entries.map((entry) => ({ ...entry, cost: 0 }));
-}
\ No newline at end of file
+}
+
+/**
+ * Retrieves allocate landed cost entries table columns.
+ */
+export const useAllocateLandedCostEntriesTableColumns = () => {
+ return React.useMemo(
+ () => [
+ {
+ Header: intl.get('item'),
+ accessor: 'item.name',
+ disableSortBy: true,
+ width: '150',
+ },
+ {
+ Header: intl.get('quantity'),
+ accessor: 'quantity',
+ disableSortBy: true,
+ width: '100',
+ },
+ {
+ Header: intl.get('rate'),
+ accessor: 'rate',
+ disableSortBy: true,
+ width: '100',
+ align: 'right',
+ },
+ {
+ Header: intl.get('amount'),
+ accessor: 'amount',
+ disableSortBy: true,
+ align: 'right',
+ width: '100',
+ },
+ {
+ Header: intl.get('cost'),
+ accessor: 'cost',
+ width: '150',
+ Cell: MoneyFieldCell,
+ disableSortBy: true,
+ },
+ ],
+ [],
+ );
+};
diff --git a/src/containers/Dialogs/CreditNoteNumberDialog/CreditNoteNumberDialogContent.js b/src/containers/Dialogs/CreditNoteNumberDialog/CreditNoteNumberDialogContent.js
new file mode 100644
index 000000000..ff1d56f16
--- /dev/null
+++ b/src/containers/Dialogs/CreditNoteNumberDialog/CreditNoteNumberDialogContent.js
@@ -0,0 +1,102 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { useSaveSettings } from 'hooks/query';
+
+import { CreditNoteNumberDialogProvider } from './CreditNoteNumberDialogProvider';
+import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withSettings from 'containers/Settings/withSettings';
+import withSettingsActions from 'containers/Settings/withSettingsActions';
+import { compose } from 'utils';
+import {
+ transformFormToSettings,
+ transformSettingsToForm,
+} from 'containers/JournalNumber/utils';
+
+/**
+ * credit note number dialog content
+ */
+function CreditNoteNumberDialogContent({
+ // #ownProps
+ initialValues,
+ onConfirm,
+
+ // #withSettings
+ nextNumber,
+ numberPrefix,
+ autoIncrement,
+
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { mutateAsync: saveSettings } = useSaveSettings();
+ const [referenceFormValues, setReferenceFormValues] = React.useState(null);
+
+ // Handle the submit form.
+ const handleSubmitForm = (values, { setSubmitting }) => {
+ // Handle the form success.
+ const handleSuccess = () => {
+ setSubmitting(false);
+ closeDialog('credit-number-form');
+ onConfirm(values);
+ };
+ // Handle the form errors.
+ const handleErrors = () => {
+ setSubmitting(false);
+ };
+ if (values.incrementMode === 'manual-transaction') {
+ handleSuccess();
+ return;
+ }
+ // Transformes the form values to settings to save it.
+ const options = transformFormToSettings(values, 'credit_note');
+
+ // Save the settings.
+ saveSettings({ options }).then(handleSuccess).catch(handleErrors);
+ };
+
+ // Handle the dialog close.
+ const handleClose = () => {
+ closeDialog('credit-number-form');
+ };
+ // Handle form change.
+ const handleChange = (values) => {
+ setReferenceFormValues(values);
+ };
+
+ // Description.
+ const description =
+ referenceFormValues?.incrementMode === 'auto'
+ ? intl.get('credit_note.auto_increment.auto')
+ : intl.get('credit_note.auto_increment.manually');
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withDialogActions,
+ withSettingsActions,
+ withSettings(({ creditNoteSettings }) => ({
+ autoIncrement: creditNoteSettings?.autoIncrement,
+ nextNumber: creditNoteSettings?.nextNumber,
+ numberPrefix: creditNoteSettings?.numberPrefix,
+ })),
+)(CreditNoteNumberDialogContent);
diff --git a/src/containers/Dialogs/CreditNoteNumberDialog/CreditNoteNumberDialogProvider.js b/src/containers/Dialogs/CreditNoteNumberDialog/CreditNoteNumberDialogProvider.js
new file mode 100644
index 000000000..94daf467f
--- /dev/null
+++ b/src/containers/Dialogs/CreditNoteNumberDialog/CreditNoteNumberDialogProvider.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import { DialogContent } from 'components';
+import { useSettingsCreditNotes } from 'hooks/query';
+
+const CreditNoteNumberDialogContext = React.createContext();
+
+/**
+ *Credit Note number dialog provider
+ */
+function CreditNoteNumberDialogProvider({ query, ...props }) {
+ const { isLoading: isSettingsLoading } = useSettingsCreditNotes();
+
+ // Provider payload.
+ const provider = {
+ isSettingsLoading,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useCreditNoteNumberDialogContext = () =>
+ React.useContext(CreditNoteNumberDialogContext);
+
+export { CreditNoteNumberDialogProvider, useCreditNoteNumberDialogContext };
diff --git a/src/containers/Dialogs/CreditNoteNumberDialog/index.js b/src/containers/Dialogs/CreditNoteNumberDialog/index.js
new file mode 100644
index 000000000..c1786c324
--- /dev/null
+++ b/src/containers/Dialogs/CreditNoteNumberDialog/index.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import { Dialog, DialogSuspense, FormattedMessage as T } from 'components';
+import withDialogRedux from 'components/DialogReduxConnect';
+import { compose, saveInvoke } from 'utils';
+
+const CreditNoteNumberDialogContent = React.lazy(() =>
+ import('./CreditNoteNumberDialogContent'),
+);
+
+/**
+ * Credit note number dialog.
+ */
+function CreditNoteNumberDialog({
+ dialogName,
+ payload: { initialFormValues },
+ isOpen,
+ onConfirm,
+}) {
+ const handleConfirm = (values) => {
+ saveInvoke(onConfirm, values);
+ };
+
+ return (
+ }
+ name={dialogName}
+ autoFocus={true}
+ canEscapeKeyClose={true}
+ isOpen={isOpen}
+ >
+
+
+
+
+ );
+}
+export default compose(withDialogRedux())(CreditNoteNumberDialog);
diff --git a/src/containers/Dialogs/InviteUserDialog/InviteUserFormContent.js b/src/containers/Dialogs/InviteUserDialog/InviteUserFormContent.js
index c66fe492f..a09bc38ed 100644
--- a/src/containers/Dialogs/InviteUserDialog/InviteUserFormContent.js
+++ b/src/containers/Dialogs/InviteUserDialog/InviteUserFormContent.js
@@ -24,7 +24,7 @@ function InviteUserFormContent({
const handleClose = () => {
closeDialog(dialogName);
};
- console.log(roles, 'XX');
+
return (
+ }
+ label={
+ <>
+
${item.reference.amount}
+
+ >
+ }
+ onClick={handleClick}
+ className={'universal-search__item--receipt'}
+ />
+ );
+}
+
+/**
+ * Transformes receipt resource item to search item.
+ */
+const transformVendorCreditsToSearch = (vendorCredit) => ({
+ id: vendorCredit.id,
+ text: vendorCredit.vendor.display_name,
+ label: vendorCredit.formatted_amount,
+ reference: vendorCredit,
+});
+
+/**
+ * Credit note universal search bind configuration.
+ */
+export const universalSearchVendorCreditBind = () => ({
+ resourceType: RESOURCES_TYPES.VENDOR_CREDIT,
+ optionItemLabel: intl.get('vendor_credit.label'),
+ selectItemAction: VendorCreditUniversalSearchSelect,
+ itemRenderer: VendorCreditUniversalSearchItem,
+ itemSelect: transformVendorCreditsToSearch,
+ permission: {
+ ability: VendorCreditAction.View,
+ subject: AbilitySubject.VendorCredit,
+ },
+});
diff --git a/src/containers/Purchases/CreditNotes/VendorCreditNotesAlerts.js b/src/containers/Purchases/CreditNotes/VendorCreditNotesAlerts.js
new file mode 100644
index 000000000..05bfbfef6
--- /dev/null
+++ b/src/containers/Purchases/CreditNotes/VendorCreditNotesAlerts.js
@@ -0,0 +1,39 @@
+import React from 'react';
+
+const VendorCreditDeleteAlert = React.lazy(() =>
+ import('../../Alerts/VendorCeditNotes/VendorCreditDeleteAlert'),
+);
+
+const RefundVendorCreditDeleteAlert = React.lazy(() =>
+ import('../../Alerts/VendorCeditNotes/RefundVendorCreditDeleteAlert'),
+);
+
+const OpenVendorCreditAlert = React.lazy(() =>
+ import('../../Alerts/VendorCeditNotes/VendorCreditOpenedAlert'),
+);
+
+const ReconcileVendorCreditDeleteAlert = React.lazy(() =>
+ import('../../Alerts/VendorCeditNotes/ReconcileVendorCreditDeleteAlert'),
+);
+
+/**
+ * Vendor Credit notes alerts.
+ */
+export default [
+ {
+ name: 'vendor-credit-delete',
+ component: VendorCreditDeleteAlert,
+ },
+ {
+ name: 'vendor-credit-open',
+ component: OpenVendorCreditAlert,
+ },
+ {
+ name: 'refund-vendor-delete',
+ component: RefundVendorCreditDeleteAlert,
+ },
+ {
+ name: 'reconcile-vendor-delete',
+ component: ReconcileVendorCreditDeleteAlert,
+ },
+];
diff --git a/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFloatingActions.js b/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFloatingActions.js
index 147c3c8c4..3fd8f0030 100644
--- a/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFloatingActions.js
+++ b/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFloatingActions.js
@@ -64,6 +64,7 @@ export default function PaymentMadeFloatingActions() {
intent={Intent.PRIMARY}
type="submit"
onClick={handleSubmitBtnClick}
+ style={{ minWidth: '85px' }}
text={paymentMadeId ?
:
}
/>
{
const getError = (errorType) => errors.find((e) => e.type === errorType);
diff --git a/src/containers/Purchases/PaymentMades/PaymentForm/utils.js b/src/containers/Purchases/PaymentMades/PaymentForm/utils.js
index 76c8fe7a0..d85a7931c 100644
--- a/src/containers/Purchases/PaymentMades/PaymentForm/utils.js
+++ b/src/containers/Purchases/PaymentMades/PaymentForm/utils.js
@@ -29,7 +29,7 @@ export const defaultPaymentMade = {
payment_date: moment(new Date()).format('YYYY-MM-DD'),
reference: '',
payment_number: '',
- // statement: '',
+ statement: '',
currency_code: '',
entries: [],
};
diff --git a/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMdesListProvider.js b/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMdesListProvider.js
index 4753c0aeb..b6b31506a 100644
--- a/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMdesListProvider.js
+++ b/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMdesListProvider.js
@@ -39,7 +39,7 @@ function PaymentMadesProvider({ query, ...props }) {
return (
diff --git a/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js b/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js
index ae5951478..d009e8a2e 100644
--- a/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js
+++ b/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js
@@ -46,6 +46,7 @@ export function ActionsMenu({
/>
+
+ }
+ label={
+ <>
+
${item.reference.amount}
+
+ >
+ }
+ onClick={handleClick}
+ className={'universal-search__item--receipt'}
+ />
+ );
+}
+
+/**
+ * Transformes receipt resource item to search item.
+ */
+const transformReceiptsToSearch = (creditNote) => ({
+ id: creditNote.id,
+ text: creditNote.customer.display_name,
+ label: creditNote.formatted_amount,
+ reference: creditNote,
+});
+
+/**
+ * Credit note universal search bind configuration.
+ */
+export const universalSearchCreditNoteBind = () => ({
+ resourceType: RESOURCES_TYPES.CREDIT_NOTE,
+ optionItemLabel: intl.get('credit_note.label'),
+ selectItemAction: CreditNoteUniversalSearchSelect,
+ itemRenderer: CreditNoteUniversalSearchItem,
+ itemSelect: transformReceiptsToSearch,
+ permission: {
+ ability: CreditNoteAction.View,
+ subject: AbilitySubject.CreditNote,
+ },
+});
diff --git a/src/containers/Sales/CreditNotes/CreditNotesAlerts.js b/src/containers/Sales/CreditNotes/CreditNotesAlerts.js
new file mode 100644
index 000000000..83b171df7
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesAlerts.js
@@ -0,0 +1,39 @@
+import React from 'react';
+
+const CreditNoteDeleteAlert = React.lazy(() =>
+ import('../../Alerts/CreditNotes/CreditNoteDeleteAlert'),
+);
+
+const RefundCreditNoteDeleteAlert = React.lazy(() =>
+ import('../../Alerts/CreditNotes/RefundCreditNoteDeleteAlert'),
+);
+
+const OpenCreditNoteAlert = React.lazy(() =>
+ import('../../Alerts/CreditNotes/CreditNoteOpenedAlert'),
+);
+
+const ReconcileCreditDeleteAlert = React.lazy(() =>
+ import('../../Alerts/CreditNotes/ReconcileCreditNoteDeleteAlert'),
+);
+
+/**
+ * Credit notes alerts.
+ */
+export default [
+ {
+ name: 'credit-note-delete',
+ component: CreditNoteDeleteAlert,
+ },
+ {
+ name: 'credit-note-open',
+ component: OpenCreditNoteAlert,
+ },
+ {
+ name: 'refund-credit-delete',
+ component: RefundCreditNoteDeleteAlert,
+ },
+ {
+ name: 'reconcile-credit-delete',
+ component: ReconcileCreditDeleteAlert,
+ },
+];
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesActionsBar.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesActionsBar.js
new file mode 100644
index 000000000..1504cb10f
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesActionsBar.js
@@ -0,0 +1,150 @@
+import React from 'react';
+import {
+ Button,
+ Classes,
+ NavbarDivider,
+ NavbarGroup,
+ Intent,
+ Alignment,
+} from '@blueprintjs/core';
+import { useHistory } from 'react-router-dom';
+import {
+ Icon,
+ Can,
+ FormattedMessage as T,
+ DashboardActionViewsList,
+ AdvancedFilterPopover,
+ DashboardFilterButton,
+ DashboardRowsHeightButton,
+} from 'components';
+import DashboardActionsBar from '../../../../components/Dashboard/DashboardActionsBar';
+
+import { useCreditNoteListContext } from './CreditNotesListProvider';
+import {
+ CreditNoteAction,
+ AbilitySubject,
+} from '../../../../common/abilityOption';
+import withCreditNotes from './withCreditNotes';
+import withCreditNotesActions from './withCreditNotesActions';
+import withSettings from '../../../Settings/withSettings';
+import withSettingsActions from '../../../Settings/withSettingsActions';
+
+import { compose } from 'utils';
+
+/**
+ * Credit note table actions bar.
+ */
+function CreditNotesActionsBar({
+ // #withCreditNotes
+ creditNoteFilterRoles,
+
+ // #withCreditNotesActions
+ setCreditNotesTableState,
+
+ // #withSettings
+ creditNoteTableSize,
+
+ // #withSettingsActions
+ addSetting,
+}) {
+ const history = useHistory();
+
+ // credit note list context.
+ const { CreditNotesView, fields, refresh } = useCreditNoteListContext();
+
+ // Handle view tab change.
+ const handleTabChange = (view) => {
+ setCreditNotesTableState({ viewSlug: view ? view.slug : null });
+ };
+
+ // Handle click a new Credit.
+ const handleClickNewCreateNote = () => {
+ history.push('/credit-notes/new');
+ };
+
+ // Handle click a refresh credit note.
+ const handleRefreshBtnClick = () => {
+ refresh();
+ };
+
+ // Handle table row size change.
+ const handleTableRowSizeChange = (size) => {
+ addSetting('creditNote', 'tableSize', size);
+ };
+
+ return (
+
+
+
+
+
+ }
+ text={}
+ onClick={handleClickNewCreateNote}
+ />
+
+ {
+ setCreditNotesTableState({ filterRoles: filterConditions });
+ },
+ }}
+ >
+
+
+
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+
+
+
+
+
+ }
+ onClick={handleRefreshBtnClick}
+ />
+
+
+ );
+}
+
+export default compose(
+ withCreditNotesActions,
+ withSettingsActions,
+ withCreditNotes(({ creditNoteTableState }) => ({
+ creditNoteFilterRoles: creditNoteTableState.filterRoles,
+ })),
+ withSettings(({ creditNoteSettings }) => ({
+ creditNoteTableSize: creditNoteSettings?.tableSize,
+ })),
+)(CreditNotesActionsBar);
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesDataTable.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesDataTable.js
new file mode 100644
index 000000000..a2a666858
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesDataTable.js
@@ -0,0 +1,157 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+
+import CreditNoteEmptyStatus from './CreditNotesEmptyStatus';
+import { DataTable, DashboardContentTable } from 'components';
+import { TABLES } from 'common/tables';
+import { useMemorizedColumnsWidths } from 'hooks';
+
+import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
+import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
+
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import withCreditNotesActions from './withCreditNotesActions';
+import withAlertsActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withSettings from '../../../Settings/withSettings';
+
+import { useCreditNoteTableColumns, ActionsMenu } from './components';
+import { useCreditNoteListContext } from './CreditNotesListProvider';
+
+import { compose } from 'utils';
+
+/**
+ * Credit note data table.
+ */
+function CreditNotesDataTable({
+ // #withCreditNotesActions
+ setCreditNotesTableState,
+
+ // #withAlertsActions
+ openAlert,
+
+ // #withDrawerActions
+ openDrawer,
+
+ // #withDialogAction
+ openDialog,
+
+ // #withSettings
+ creditNoteTableSize,
+}) {
+ const history = useHistory();
+
+ // Credit note list context.
+ const {
+ creditNotes,
+ pagination,
+ isEmptyStatus,
+ isCreditNotesFetching,
+ isCreditNotesLoading,
+ } = useCreditNoteListContext();
+
+ // Credit note table columns.
+ const columns = useCreditNoteTableColumns();
+
+ // Local storage memorizing columns widths.
+ const [initialColumnsWidths, , handleColumnResizing] =
+ useMemorizedColumnsWidths(TABLES.CREDIT_NOTES);
+
+ // Handles fetch data once the table state change.
+ const handleDataTableFetchData = React.useCallback(
+ ({ pageSize, pageIndex, sortBy }) => {
+ setCreditNotesTableState({
+ pageSize,
+ pageIndex,
+ sortBy,
+ });
+ },
+ [setCreditNotesTableState],
+ );
+
+ // Display create note empty status instead of the table.
+ if (isEmptyStatus) {
+ return
;
+ }
+
+ const handleViewDetailCreditNote = ({ id }) => {
+ openDrawer('credit-note-detail-drawer', { creditNoteId: id });
+ };
+
+ // Handle delete credit note.
+ const handleDeleteCreditNote = ({ id }) => {
+ openAlert('credit-note-delete', { creditNoteId: id });
+ };
+
+ // Handle edit credit note.
+ const hanldeEditCreditNote = (creditNote) => {
+ history.push(`/credit-notes/${creditNote.id}/edit`);
+ };
+
+ // Handle cell click.
+ const handleCellClick = (cell, event) => {
+ openDrawer('credit-note-detail-drawer', {
+ creditNoteId: cell.row.original.id,
+ });
+ };
+
+ const handleRefundCreditNote = ({ id }) => {
+ openDialog('refund-credit-note', { creditNoteId: id });
+ };
+
+ // Handle cancel/confirm crdit note open.
+ const handleOpenCreditNote = ({ id }) => {
+ openAlert('credit-note-open', { creditNoteId: id });
+ };
+
+ // Handle reconcile credit note.
+ const handleReconcileCreditNote = ({ id }) => {
+ openDialog('reconcile-credit-note', { creditNoteId: id });
+ };
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withDashboardActions,
+ withCreditNotesActions,
+ withDrawerActions,
+ withAlertsActions,
+ withDialogActions,
+ withSettings(({ creditNoteSettings }) => ({
+ creditNoteTableSize: creditNoteSettings?.tableSize,
+ })),
+)(CreditNotesDataTable);
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesEmptyStatus.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesEmptyStatus.js
new file mode 100644
index 000000000..5a3c7cd43
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesEmptyStatus.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import { Button, Intent } from '@blueprintjs/core';
+import { useHistory } from 'react-router-dom';
+import { EmptyStatus } from 'components';
+import { Can, FormattedMessage as T } from 'components';
+import {
+ CreditNoteAction,
+ AbilitySubject,
+} from '../../../../common/abilityOption';
+
+export default function CreditNotesEmptyStatus() {
+ const history = useHistory();
+ return (
+
}
+ description={
+
+
+
+ }
+ action={
+ <>
+
+
+
+
+
+ >
+ }
+ />
+ );
+}
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesList.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesList.js
new file mode 100644
index 000000000..43b054e16
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesList.js
@@ -0,0 +1,53 @@
+import React from 'react';
+
+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';
+import withCreditNotesActions from './withCreditNotesActions';
+
+import { CreditNotesListProvider } from './CreditNotesListProvider';
+import { transformTableStateToQuery, compose } from 'utils';
+
+function CreditNotesList({
+ // #withCreditNotes
+ creditNoteTableState,
+ creditNoteTableStateChanged,
+
+ // #withCreditNotesActions
+ resetCreditNotesTableState,
+}) {
+ // Resets the credit note table state once the page unmount.
+ React.useEffect(
+ () => () => {
+ resetCreditNotesTableState();
+ },
+ [resetCreditNotesTableState],
+ );
+
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withCreditNotesActions,
+ withCreditNotes(({ creditNoteTableState, creditNoteTableStateChanged }) => ({
+ creditNoteTableState,
+ creditNoteTableStateChanged,
+ })),
+)(CreditNotesList);
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesListProvider.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesListProvider.js
new file mode 100644
index 000000000..07a778892
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesListProvider.js
@@ -0,0 +1,75 @@
+import React from 'react';
+import { isEmpty } from 'lodash';
+
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+import {
+ useResourceViews,
+ useResourceMeta,
+ useCreditNotes,
+ useRefreshCreditNotes,
+} from 'hooks/query';
+
+import { getFieldsFromResourceMeta } from 'utils';
+
+const CreditNoteListContext = React.createContext();
+
+/**
+ * Credit note data provider.
+ */
+function CreditNotesListProvider({ query, tableStateChanged, ...props }) {
+ // Credit notes refresh action.
+ const { refresh } = useRefreshCreditNotes();
+
+ // Fetch create notes resource views and fields.
+ const { data: CreditNotesView, isLoading: isViewsLoading } =
+ useResourceViews('credit_notes');
+
+ // Fetch the accounts resource fields.
+ const {
+ data: resourceMeta,
+ isLoading: isResourceLoading,
+ isFetching: isResourceFetching,
+ } = useResourceMeta('credit_notes');
+
+ // Fetch credit note list.
+ const {
+ data: { creditNotes, pagination, filterMeta },
+ isFetching: isCreditNotesFetching,
+ isLoading: isCreditNotesLoading,
+ } = useCreditNotes(query, { keepPreviousData: true });
+
+ // Detarmines the datatable empty status.S
+ const isEmptyStatus = isEmpty(creditNotes) && !isCreditNotesLoading && !tableStateChanged;
+
+ // Provider payload.
+ const provider = {
+ creditNotes,
+ pagination,
+
+ CreditNotesView,
+ refresh,
+
+ resourceMeta,
+ fields: getFieldsFromResourceMeta(resourceMeta.fields),
+ isResourceLoading,
+ isResourceFetching,
+
+ isCreditNotesFetching,
+ isCreditNotesLoading,
+ isViewsLoading,
+ isEmptyStatus,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useCreditNoteListContext = () => React.useContext(CreditNoteListContext);
+
+export { CreditNotesListProvider, useCreditNoteListContext };
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesViewTabs.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesViewTabs.js
new file mode 100644
index 000000000..5ef16b4e9
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesViewTabs.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
+
+import { DashboardViewsTabs } from 'components';
+
+import withCreditNotes from './withCreditNotes';
+import withCreditNotesActions from './withCreditNotesActions';
+
+import { compose, transfromViewsToTabs } from 'utils';
+import { useCreditNoteListContext } from './CreditNotesListProvider';
+
+/**
+ * Credit Note views tabs.
+ */
+function CreditNotesViewTabs({
+ // #withCreditNotes
+ creditNoteCurrentView,
+
+ // #withCreditNotesActions
+ setCreditNotesTableState,
+}) {
+ // Credit note list context.
+ const { CreditNotesView } = useCreditNoteListContext();
+
+ const tabs = transfromViewsToTabs(CreditNotesView);
+
+ // Handle tab change.
+ const handleTabsChange = (viewSlug) => {
+ setCreditNotesTableState({ viewSlug });
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withCreditNotesActions,
+ withCreditNotes(({ creditNoteTableState }) => ({
+ creditNoteCurrentView: creditNoteTableState.viewSlug,
+ })),
+)(CreditNotesViewTabs);
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/components.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/components.js
new file mode 100644
index 000000000..eb171ae86
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/components.js
@@ -0,0 +1,183 @@
+import React from 'react';
+import { Intent, Tag, Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
+import intl from 'react-intl-universal';
+import clsx from 'classnames';
+
+import { CLASSES } from '../../../../common/classes';
+import {
+ FormatDateCell,
+ FormattedMessage as T,
+ Choose,
+ If,
+ Icon,
+ Can,
+} from 'components';
+import { safeCallback } from 'utils';
+import {
+ CreditNoteAction,
+ AbilitySubject,
+} from '../../../../common/abilityOption';
+
+export function ActionsMenu({
+ payload: { onEdit, onDelete, onRefund, onOpen, onReconcile, onViewDetails },
+ row: { original },
+}) {
+ return (
+
+ );
+}
+
+/**
+ * Status accessor.
+ */
+export function StatusAccessor(creditNote) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+/**
+ * Retrieve credit note table columns.
+ */
+export function useCreditNoteTableColumns() {
+ return React.useMemo(
+ () => [
+ {
+ id: 'credit_date',
+ Header: intl.get('credit_note.column.credit_date'),
+ accessor: 'formatted_credit_note_date',
+ Cell: FormatDateCell,
+ width: 110,
+ className: 'credit_date',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'customer',
+ Header: intl.get('customer_name'),
+ accessor: 'customer.display_name',
+ width: 180,
+ className: 'customer',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'credit_number',
+ Header: intl.get('credit_note.column.credit_note_no'),
+ accessor: 'credit_note_number',
+ width: 100,
+ className: 'credit_number',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'amount',
+ Header: intl.get('amount'),
+ accessor: 'formatted_amount',
+ width: 120,
+ align: 'right',
+ clickable: true,
+ textOverview: true,
+ className: clsx(CLASSES.FONT_BOLD),
+ },
+ {
+ id: 'balance',
+ Header: intl.get('balance'),
+ accessor: 'formatted_credits_remaining',
+ width: 120,
+ align: 'right',
+ clickable: true,
+ textOverview: true,
+ disableSortBy: true,
+ className: clsx(CLASSES.FONT_BOLD),
+ },
+ {
+ id: 'status',
+ Header: intl.get('status'),
+ accessor: StatusAccessor,
+ width: 160, // 160
+ className: 'status',
+ clickable: true,
+ },
+ {
+ id: 'reference_no',
+ Header: intl.get('reference_no'),
+ accessor: 'reference_no', // or note
+ width: 90,
+ className: 'reference_no',
+ clickable: true,
+ textOverview: true,
+ },
+ ],
+ [],
+ );
+}
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/utils.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/utils.js
new file mode 100644
index 000000000..9d94edad5
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/utils.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Intent } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+
+export const handleDeleteErrors = (errors) => {
+ if (
+ errors.find((error) => error.type === 'CREDIT_NOTE_HAS_APPLIED_INVOICES')
+ ) {
+ AppToaster.show({
+ message: intl.get(
+ 'credit_note.error.you_couldn_t_delete_credit_note_that_has_associated_invoice',
+ ),
+ intent: Intent.DANGER,
+ });
+ }
+ if (
+ errors.find(
+ (error) => error.type === 'CREDIT_NOTE_HAS_REFUNDS_TRANSACTIONS',
+ )
+ ) {
+ AppToaster.show({
+ message: intl.get(
+ 'credit_note.error.you_couldn_t_delete_credit_note_that_has_associated_refund',
+ ),
+ intent: Intent.DANGER,
+ });
+ }
+};
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotes.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotes.js
new file mode 100644
index 000000000..f9c8b0b9a
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotes.js
@@ -0,0 +1,19 @@
+import { connect } from 'react-redux';
+import {
+ getCreditNotesTableStateFactory,
+ isCreditNotesTableStateChangedFactory,
+} from '../../../../store/CreditNote/creditNote.selector';
+
+export default (mapState) => {
+ const getCreditNoteTableState = getCreditNotesTableStateFactory();
+ const isCreditNoteTableChanged = isCreditNotesTableStateChangedFactory();
+
+ const mapStateToProps = (state, props) => {
+ const mapped = {
+ creditNoteTableState: getCreditNoteTableState(state, props),
+ creditNoteTableStateChanged: isCreditNoteTableChanged(state, props),
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/src/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotesActions.js b/src/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotesActions.js
new file mode 100644
index 000000000..cedc9dbd4
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotesActions.js
@@ -0,0 +1,13 @@
+import { connect } from 'react-redux';
+import {
+ setCreditNoteTableState,
+ resetCreditNoteTableState,
+} from '../../../../store/CreditNote/creditNote.actions';
+
+const mapDipatchToProps = (dispatch) => ({
+ setCreditNotesTableState: (queries) =>
+ dispatch(setCreditNoteTableState(queries)),
+ resetCreditNotesTableState: () => dispatch(resetCreditNoteTableState()),
+});
+
+export default connect(null, mapDipatchToProps);
diff --git a/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js b/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js
index 248938c74..440ba9be7 100644
--- a/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js
+++ b/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.js
@@ -65,7 +65,6 @@ export default function EstimateFloatingActions() {
const handleCancelBtnClick = (event) => {
history.goBack();
-
};
const handleClearBtnClick = (event) => {
@@ -149,6 +148,7 @@ export default function EstimateFloatingActions() {
disabled={isSubmitting}
intent={Intent.PRIMARY}
onClick={handleSubmitDeliverBtnClick}
+ style={{ minWidth: '85px' }}
text={
}
/>
(
}
+ labelInfo={}
inline={true}
className={classNames(
CLASSES.FORM_GROUP_LIST_SELECT,
diff --git a/src/containers/Sales/Estimates/EstimatesLanding/EstimatesList.js b/src/containers/Sales/Estimates/EstimatesLanding/EstimatesList.js
index ac6561444..b32f1b318 100644
--- a/src/containers/Sales/Estimates/EstimatesLanding/EstimatesList.js
+++ b/src/containers/Sales/Estimates/EstimatesLanding/EstimatesList.js
@@ -43,7 +43,6 @@ function EstimatesList({
-
);
}
diff --git a/src/containers/Sales/Estimates/EstimatesLanding/components.js b/src/containers/Sales/Estimates/EstimatesLanding/components.js
index dd9d72131..65b941d71 100644
--- a/src/containers/Sales/Estimates/EstimatesLanding/components.js
+++ b/src/containers/Sales/Estimates/EstimatesLanding/components.js
@@ -24,25 +24,28 @@ import { safeCallback } from 'utils';
*/
export const statusAccessor = (row) => (
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
-
+
@@ -134,6 +137,7 @@ export function ActionsMenu({
/>
+
}
/>
{
+ history.push(`/credit-notes/new?from_invoice_id=${id}`, { invoiceId: id });
+ };
+
// handle quick payment receive.
const handleQuickPaymentReceive = ({ id }) => {
openDialog('quick-payment-receive', { invoiceId: id });
@@ -147,6 +152,7 @@ function InvoicesDataTable({
onQuick: handleQuickPaymentReceive,
onViewDetails: handleViewDetailInvoice,
onPrint: handlePrintInvoice,
+ onConvert: handleConvertToCreitNote,
}}
/>
diff --git a/src/containers/Sales/Invoices/InvoicesLanding/components.js b/src/containers/Sales/Invoices/InvoicesLanding/components.js
index 68e68ae89..fea2b1dff 100644
--- a/src/containers/Sales/Invoices/InvoicesLanding/components.js
+++ b/src/containers/Sales/Invoices/InvoicesLanding/components.js
@@ -27,53 +27,59 @@ import {
AbilitySubject,
} from '../../../../common/abilityOption';
+export function InvoiceStatus({ invoice }) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {intl.get('overdue_by', { overdue: invoice.overdue_days })}
+
+
+
+
+ {intl.get('due_in', { due: invoice.remaining_days })}
+
+
+
+
+
+
+ {intl.get('day_partially_paid', {
+ due: formattedAmount(invoice.due_amount, invoice.currency_code),
+ })}
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
export const statusAccessor = (row) => {
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {intl.get('overdue_by', { overdue: row.overdue_days })}
-
-
-
-
- {intl.get('due_in', { due: row.remaining_days })}
-
-
-
-
-
-
- {intl.get('day_partially_paid', {
- due: formattedAmount(row.due_amount, row.currency_code),
- })}
-
-
-
-
-
-
-
-
-
-
+
);
};
@@ -99,6 +105,18 @@ export const handleDeleteErrors = (errors) => {
intent: Intent.DANGER,
});
}
+ if (
+ errors.find(
+ (error) => error.type === 'SALE_INVOICE_HAS_APPLIED_TO_CREDIT_NOTES',
+ )
+ ) {
+ AppToaster.show({
+ message: intl.get(
+ 'invoices.error.you_couldn_t_delete_sale_invoice_that_has_reconciled',
+ ),
+ intent: Intent.DANGER,
+ });
+ }
};
export function ActionsMenu({
@@ -106,7 +124,7 @@ export function ActionsMenu({
onEdit,
onDeliver,
onDelete,
- onDrawer,
+ onConvert,
onQuick,
onViewDetails,
onPrint,
@@ -127,6 +145,11 @@ export function ActionsMenu({
text={intl.get('edit_invoice')}
onClick={safeCallback(onEdit, original)}
/>
+ }
+ text={intl.get('invoice.convert_to_credit_note')}
+ onClick={safeCallback(onConvert, original)}
+ />
+
: }
/>
({
@@ -194,7 +199,7 @@ export default compose(
paymentReceiveNextNumber: paymentReceiveSettings?.nextNumber,
paymentReceiveNumberPrefix: paymentReceiveSettings?.numberPrefix,
paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement,
- preferredDepositAccount: paymentReceiveSettings?.depositAccount,
+ preferredDepositAccount: paymentReceiveSettings?.preferredDepositAccount,
})),
withCurrentOrganization(),
)(PaymentReceiveForm);
diff --git a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js
index 743e97d32..b990c3438 100644
--- a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js
+++ b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js
@@ -224,6 +224,7 @@ function PaymentReceiveHeaderFields({
}
inline={true}
+ labelInfo={}
className={('form-group--payment_receive_no', CLASSES.FILL)}
intent={inputIntent({ error, touched })}
helperText={}
diff --git a/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiptsListProvider.js b/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiptsListProvider.js
index 8a8c0ecf1..c1f77977a 100644
--- a/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiptsListProvider.js
+++ b/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiptsListProvider.js
@@ -1,4 +1,6 @@
import React, { createContext, useContext } from 'react';
+import { isEmpty } from 'lodash';
+
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import {
useResourceViews,
@@ -12,12 +14,10 @@ const PaymentReceivesListContext = createContext();
/**
* Payment receives list data provider.
*/
-function PaymentReceivesListProvider({ query, ...props }) {
+function PaymentReceivesListProvider({ query, tableStateChanged, ...props }) {
// Fetch payment receives resource views and fields.
- const {
- data: paymentReceivesViews,
- isFetching: isViewsLoading,
- } = useResourceViews('payment_receives');
+ const { data: paymentReceivesViews, isFetching: isViewsLoading } =
+ useResourceViews('payment_receives');
// Fetch the payment receives resource fields.
const {
@@ -35,11 +35,7 @@ function PaymentReceivesListProvider({ query, ...props }) {
// Detarmines the datatable empty status.
const isEmptyStatus =
- isTableEmptyStatus({
- data: paymentReceives,
- pagination,
- filterMeta,
- }) && !isPaymentReceivesLoading;
+ isEmpty(paymentReceives) && !isPaymentReceivesLoading && !tableStateChanged;
// Provider payload.
const state = {
diff --git a/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js b/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js
index de95d270a..c679f95e6 100644
--- a/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js
+++ b/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js
@@ -41,6 +41,7 @@ export function ActionsMenu({
/>
+
}
/>
+
);
diff --git a/src/containers/Sales/Receipts/ReceiptsLanding/components.js b/src/containers/Sales/Receipts/ReceiptsLanding/components.js
index 8a063e69d..5f7a09207 100644
--- a/src/containers/Sales/Receipts/ReceiptsLanding/components.js
+++ b/src/containers/Sales/Receipts/ReceiptsLanding/components.js
@@ -21,6 +21,10 @@ import {
AbilitySubject,
} from '../../../../common/abilityOption';
+/**
+ * Receipts table row actions menu.
+ * @returns {React.JSX}
+ */
export function ActionsMenu({
payload: { onEdit, onDelete, onClose, onDrawer, onViewDetails, onPrint },
row: { original: receipt },
@@ -56,6 +60,7 @@ export function ActionsMenu({
/>
+
-
+
-
+
diff --git a/src/containers/Settings/withSettings.js b/src/containers/Settings/withSettings.js
index 77ec97cc8..867e56dc7 100644
--- a/src/containers/Settings/withSettings.js
+++ b/src/containers/Settings/withSettings.js
@@ -19,6 +19,8 @@ export default (mapState) => {
cashflowSettings: state.settings.data.cashflowAccounts,
cashflowTransactionsSettings: state.settings.data.cashflowTransactions,
cashflowSetting: state.settings.data.cashflow,
+ creditNoteSettings: state.settings.data.creditNote,
+ vendorsCreditNoteSetting: state.settings.data.vendorCredit,
};
return mapState ? mapState(mapped, state, props) : mapped;
};
diff --git a/src/containers/TransactionsLocking/TransactionsLockingAlerts.js b/src/containers/TransactionsLocking/TransactionsLockingAlerts.js
new file mode 100644
index 000000000..c4e9554aa
--- /dev/null
+++ b/src/containers/TransactionsLocking/TransactionsLockingAlerts.js
@@ -0,0 +1,15 @@
+import React from 'react';
+
+const cancelUnlockingPartialAlert = React.lazy(() =>
+ import('../Alerts/TransactionLocking/cancelUnlockingPartialAlert'),
+);
+
+/**
+ * Transactions alerts.
+ */
+export default [
+ {
+ name: 'cancel-unlocking-partail',
+ component: cancelUnlockingPartialAlert,
+ },
+];
diff --git a/src/containers/TransactionsLocking/TransactionsLockingBody.js b/src/containers/TransactionsLocking/TransactionsLockingBody.js
new file mode 100644
index 000000000..2190907fd
--- /dev/null
+++ b/src/containers/TransactionsLocking/TransactionsLockingBody.js
@@ -0,0 +1,74 @@
+import React from 'react';
+import * as R from 'ramda';
+
+import {
+ TransactionsLockingList,
+ TransactionsLockingFull,
+ TransactionLockingSkeletonList,
+} from './components';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withAlertsActions from 'containers/Alert/withAlertActions';
+
+import { useTransactionsLockingContext } from './TransactionsLockingProvider';
+
+/**
+ * Transactions locking body.
+ * @returns {JSX}
+ */
+function TransactionsLockingBodyJsx({
+ // #withDialogActions
+ openDialog,
+
+ // #withAlertsActions
+ openAlert,
+}) {
+ const { isTransactionLockingLoading, transactionLockingType } =
+ useTransactionsLockingContext();
+
+ // Handle locking transactions.
+ const handleLockingTransactions = (module, {}, isEnabled) => {
+ openDialog('locking-transactions', {
+ isEnabled: isEnabled,
+ module: module,
+ });
+ };
+ // Handle unlocking transactions
+ const handleUnlockTransactions = (module) => {
+ openDialog('unlocking-transactions', { module: module });
+ };
+ // Handle unlocking transactions
+ const handleUnlockingPartial = (module) => {
+ openDialog('unlocking-partial-transactions', { module: module });
+ };
+ // Handle cancel partial unlocking.
+ const handleCancelUnlockingPartail = (module) => {
+ openAlert('cancel-unlocking-partail', { module: module });
+ };
+
+ return !isTransactionLockingLoading ? (
+ transactionLockingType === 'partial' ? (
+
+ ) : (
+
+ )
+ ) : (
+
+ );
+}
+
+export const TransactionsLockingBody = R.compose(
+ withAlertsActions,
+ withDialogActions,
+)(TransactionsLockingBodyJsx);
diff --git a/src/containers/TransactionsLocking/TransactionsLockingHeader.js b/src/containers/TransactionsLocking/TransactionsLockingHeader.js
new file mode 100644
index 000000000..877d81072
--- /dev/null
+++ b/src/containers/TransactionsLocking/TransactionsLockingHeader.js
@@ -0,0 +1,106 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Intent } from '@blueprintjs/core';
+import styled from 'styled-components';
+
+import { useTransactionsLockingContext } from './TransactionsLockingProvider';
+import {
+ ButtonLink,
+ AppToaster,
+ Join,
+ FormattedMessage as T,
+ Alert,
+ AlertDesc,
+} from 'components';
+import {
+ validateMoveToFullLocking,
+ validateMoveToPartialLocking,
+} from './utils';
+
+/**
+ * Transactions locking header.
+ * @returns
+ */
+export function TransactionsLockingHeader() {
+ const {
+ transactionsLocking,
+ transactionLockingType,
+ setTransactionLockingType,
+ } = useTransactionsLockingContext();
+
+ // Handle all lock link click.
+ const handleAllLockClick = () => {
+ const activeModules = validateMoveToFullLocking(
+ transactionsLocking.modules,
+ );
+ const modulesStrong = activeModules.map((module) => (
+ {module.formatted_module}
+ ));
+ if (activeModules.length > 0) {
+ AppToaster.show({
+ message: (
+
+ You should unlock modules
+ first, than you can lock all transactions at once.
+
+ ),
+ intent: Intent.DANGER,
+ });
+ } else {
+ setTransactionLockingType('all');
+ }
+ };
+
+ const handleUndividualLockClick = () => {
+ const isAllLockingActive = validateMoveToPartialLocking(
+ transactionsLocking.all,
+ );
+
+ if (isAllLockingActive) {
+ AppToaster.show({
+ message: intl.get(
+ 'transactions_locking.you_should_unlock_all_transactions_at_once_before',
+ ),
+ intent: Intent.DANGER,
+ });
+ } else {
+ setTransactionLockingType('partial');
+ }
+ };
+
+ return transactionLockingType !== 'all' ? (
+ }
+ intent={Intent.PRIMARY}
+ >
+
+
+
+
+
+
+
+ ) : (
+ }
+ intent={Intent.PRIMARY}
+ >
+
+
+
+
+
+
+
+ );
+}
+
+const LockAllAlert = styled(Alert)`
+ margin-bottom: 0;
+ margin-top: 20px;
+ background: transparent;
+
+ ${AlertDesc} {
+ color: #1f3255;
+ }
+`;
diff --git a/src/containers/TransactionsLocking/TransactionsLockingList.js b/src/containers/TransactionsLocking/TransactionsLockingList.js
index 6163b8daf..045e50bf4 100644
--- a/src/containers/TransactionsLocking/TransactionsLockingList.js
+++ b/src/containers/TransactionsLocking/TransactionsLockingList.js
@@ -1,86 +1,42 @@
import React from 'react';
-import { Link } from 'react-router-dom';
import styled from 'styled-components';
-import clsx from 'classnames';
+
+import { Paragraph, FormattedMessage as T } from 'components';
import { TransactionsLockingProvider } from './TransactionsLockingProvider';
-import { TransactionLockingContent } from './components';
-import withDialogActions from 'containers/Dialog/withDialogActions';
-
-import { compose } from 'utils';
-
-const DataTest = [
- {
- name: 'sales',
- description:
- 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do',
- },
- {
- name: 'purchases',
- description:
- 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do',
- },
- {
- name: 'financial',
- description:
- 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do',
- },
-];
-
-function Paragraph({ className, children }) {
- return {children}
;
-}
+import { TransactionsLockingHeader } from './TransactionsLockingHeader';
+import { TransactionsLockingBody } from './TransactionsLockingBody';
/**
* Transactions locking list.
*/
-function TransactionsLockingList({
- // #withDialogActions
- openDialog,
-}) {
- // Handle switch transactions locking.
- const handleSwitchTransactionsLocking = () => {
- openDialog('transactions-locking', {});
- };
-
+export default function TransactionsLockingListPage() {
return (
- Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
- Lock All Transactions At Once. {' '}
- {''}Lock All Transactions At Once →
+
- {DataTest.map(({ name, description }) => (
-
- ))}
+
);
}
-export default compose(withDialogActions)(TransactionsLockingList);
const TransactionsLocking = styled.div`
display: flex;
flex-direction: column;
- padding: 32px;
- max-width: 700px;
+ padding: 32px 40px;
+ min-width: 800px;
+ max-width: 900px;
+ width: 75%;
`;
const TransactionsLockingParagraph = styled(Paragraph)`
- margin-bottom: 30px;
-`;
-
-const TransLockingTitle = styled.h2`
- margin-bottom: 12px;
+ margin-bottom: 25px;
`;
const TransLockingDesc = styled.p``;
diff --git a/src/containers/TransactionsLocking/TransactionsLockingPage.js b/src/containers/TransactionsLocking/TransactionsLockingPage.js
new file mode 100644
index 000000000..0ea88c231
--- /dev/null
+++ b/src/containers/TransactionsLocking/TransactionsLockingPage.js
@@ -0,0 +1,12 @@
+import React from 'react';
+
+import { TransactionsLockingProvider } from './TransactionsLockingProvider';
+import TransactionsLockingList from './TransactionsLockingList';
+
+export default function TransactionsLockingPage() {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/TransactionsLocking/TransactionsLockingProvider.js b/src/containers/TransactionsLocking/TransactionsLockingProvider.js
index 33f1b855c..f7ec72f5c 100644
--- a/src/containers/TransactionsLocking/TransactionsLockingProvider.js
+++ b/src/containers/TransactionsLocking/TransactionsLockingProvider.js
@@ -1,5 +1,7 @@
import React from 'react';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
+import { useTransactionsLocking } from 'hooks/query';
+import { useWatchImmediate } from '../../hooks/utils/useWatch';
const TransactionsLockingContext = React.createContext();
@@ -7,13 +9,36 @@ const TransactionsLockingContext = React.createContext();
* Transactions locking data provider.
*/
function TransactionsLockingProvider({ ...props }) {
+ // Fetch transaction locking modules list.
+ const {
+ data: transactionsLocking,
+ isFetching: isTransactionLockingFetching,
+ isLoading: isTransactionLockingLoading,
+ } = useTransactionsLocking();
+
+ // Transactions locking type.
+ const [transactionLockingType, setTransactionLockingType] =
+ React.useState('partial');
+
+ // Locking type controlled from response.
+ useWatchImmediate(() => {
+ if (transactionsLocking.locking_type) {
+ setTransactionLockingType(transactionsLocking.locking_type);
+ }
+ }, transactionsLocking.locking_type);
+
// Provider
- const provider = {};
+ const provider = {
+ transactionsLocking,
+ isTransactionLockingFetching,
+ isTransactionLockingLoading,
+
+ transactionLockingType,
+ setTransactionLockingType,
+ };
return (
-
+
);
diff --git a/src/containers/TransactionsLocking/components.js b/src/containers/TransactionsLocking/components.js
index bd6825f41..d0285ce48 100644
--- a/src/containers/TransactionsLocking/components.js
+++ b/src/containers/TransactionsLocking/components.js
@@ -1,57 +1,351 @@
import React from 'react';
import styled from 'styled-components';
-import { Switch, FormGroup, Position } from '@blueprintjs/core';
-import { Hint, Icon, FormattedMessage as T } from 'components';
+import intl from 'react-intl-universal';
+import {
+ Button,
+ Position,
+ MenuItem,
+ Menu,
+ Intent,
+ Divider,
+ Classes,
+} from '@blueprintjs/core';
+import { Popover2 } from '@blueprintjs/popover2';
-export const TransactionLockingContent = ({ name, description, onSwitch }) => (
-
-
-
-
-
+import { Hint, Icon, If, FormattedMessage as T } from 'components';
+import { useTransactionsLockingContext } from './TransactionsLockingProvider';
+import { safeInvoke } from 'utils';
-
-
- {' '}
-
-
- {description}
-
-
-
+ );
+}
+
+/**
+ * Transactions locking items modules list.
+ * @returns {React.JSX}
+ */
+export function TransactionsLockingList({ ...rest }) {
+ const {
+ transactionsLocking: { modules },
+ } = useTransactionsLockingContext();
+
+ return modules.map((module) => (
+
+ ));
+}
+
+/**
+ * Transactions locking full module item.
+ * @returns {React.JSX}
+ */
+export function TransactionsLockingFull({ ...rest }) {
+ const {
+ transactionsLocking: { all },
+ } = useTransactionsLockingContext();
+
+ return ;
+}
+
+/**
+ * Transactions locking skeleton list.
+ * @returns {React.JSX}
+ */
+export function TransactionLockingSkeletonList() {
+ return (
+ <>
+
+
+
+ >
+ );
+}
+
+/**
+ * Transactions locking skeleton item.
+ * @returns {React.JSX}
+ */
+export const TransactionLockingItemSkeleton = ({}) => {
+ return (
+
+
+
+
+
+
+
+
+ XXXX
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit.
+
+
+
+
+ );
+};
+
+const TransactionsLockingItemContext = React.createContext();
+
+const useTransactionsLockingItemContext = () =>
+ React.useContext(TransactionsLockingItemContext);
+
+/**
+ * Transactions locking item.
+ * @returns {React.JSX}
+ */
+export const TransactionLockingContent = (props) => {
+ const {
+ name,
+ description,
+ module,
+
+ isEnabled,
+ lockToDate,
+ lockReason,
+
+ // Unlock props.
+ isPartialUnlock,
+ unlockToDate,
+ unlockFromDate,
+ unlockReason,
+
+ onLock,
+ onCancelLock,
+ onEditLock,
+ onUnlockPartial,
+ onCancelUnlockPartial,
+ } = props;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+/**
+ * Transactions locking item content.
+ */
+function TransactionsLockingItemContent() {
+ const {
+ name,
+ description,
+
+ isEnabled,
+ lockToDate,
+ lockReason,
+
+ // Unlock props.
+ isPartialUnlock,
+ unlockToDate,
+ unlockFromDate,
+ unlockReason,
+ } = useTransactionsLockingItemContext();
+
+ return (
+
+
+ {name}
+
+
+
+
+
+
+
+
+
+
+
+
+ {intl.formatHTMLMessage(
+ { id: 'transactions_locking.of_the_module_locked_to' },
+ {
+ value: lockToDate,
+ },
+ )}
+
+
+
+
+ {intl.formatHTMLMessage(
+ { id: 'transactions_locking.lock_reason' },
+ { value: lockReason },
+ )}
+
+
+
+
+
+
+
+
+ {intl.formatHTMLMessage(
+ { id: 'transactions_locking.partial_unlocked_from' },
+ {
+ fromDate: unlockFromDate,
+ toDate: unlockToDate,
+ },
+ )}
+
+
+
+
+ {intl.formatHTMLMessage(
+ { id: 'transactions_locking.unlock_reason' },
+ { value: unlockReason },
+ )}
+
+
+
+
+
+ );
+}
+
+/**
+ * Transactions locking item actions.
+ */
+function TransactionsLockingItemActions() {
+ const {
+ module,
+ isEnabled,
+
+ // Unlock props.
+ isPartialUnlock,
+
+ onLock,
+ onCancelLock,
+ onEditLock,
+ onUnlockPartial,
+ onCancelUnlockPartial,
+ } = useTransactionsLockingItemContext();
+
+ const handleLockClick = (event) => {
+ safeInvoke(onLock, module, event);
+ };
+ const handleEditBtn = (event) => {
+ safeInvoke(onEditLock, module, isEnabled, event);
+ };
+ const handleUnlockPartial = (event) => {
+ safeInvoke(onUnlockPartial, module, event);
+ };
+
+ const handleUnlockFull = (event) => {
+ safeInvoke(onCancelLock, module, event);
+ };
+ const handleCancelPartialUnlock = (event) => {
+ safeInvoke(onCancelUnlockPartial, module, event);
+ };
+
+ return (
+
+
+
-
-
-
-);
+ intent={Intent.PRIMARY}
+ onClick={handleLockClick}
+ >
+
+
+
+
+
+
+
+
+ }
+ onClick={handleUnlockFull}
+ />
+
+
+ }
+ onClick={handleUnlockPartial}
+ />
+
+
+ }
+ onClick={handleCancelPartialUnlock}
+ />
+
+
+ }
+ placement={'bottom-start'}
+ minimal={true}
+ >
+
+
+
+
+ );
+}
const TransactionLockingWrapp = styled.div`
display: flex;
align-items: center;
border-radius: 6px;
- border: 1px solid #d1dee2;
- padding: 14px 18px;
+ border: 1px solid #c4d2d7;
+ padding: 16px 18px;
margin-bottom: 25px;
background: #fff;
+ box-shadow: 0 4px 20px -5px rgb(0 8 36 / 5%);
- div.block {
- flex: 1 1 0;
- margin-left: 20px;
- width: 100%;
- }
+ ${(props) =>
+ props.isEnabled &&
+ `
+ border-color: #fc8483;
+
+ ${TransLockingIcon} {
+ color: #ef6d6d;
+ }
+ `}
`;
-const TransactionsLockingcontent = styled.div`
+const TransLockingInner = styled.div`
display: flex;
align-items: center;
flex: 1 1 0;
@@ -65,15 +359,62 @@ const TransLockingItemTitle = styled.h1`
`;
const TransLockingItemDesc = styled.p`
margin-bottom: 0;
- opacity: 0.8;
+ opacity: 0.9;
`;
const TransLockingIcon = styled.div`
border: 1px solid #d2dde2;
- height: 50px;
- width: 50px;
+ height: 45px;
+ width: 45px;
text-align: center;
- line-height: 50px;
- border-radius: 5px;
- color: #8190ac;
+ line-height: 45px;
+ border-radius: 8px;
+ color: #93a1ba;
+
+ .bp3-icon {
+ position: relative;
+ top: 1px;
+ }
+`;
+
+export const TransLockingActions = styled.div`
+ display: flex;
+
+ .bp3-divider {
+ margin: 2px;
+ }
+`;
+
+export const TransLockingContent = styled.div`
+ flex: 1 1 0;
+ margin-left: 20px;
+ width: 100%;
+ padding-right: 10px;
+`;
+
+export const TransLockingReason = styled.div`
+ font-size: 13px;
+
+ strong {
+ color: #777;
+ }
+`;
+
+const TransUnlockWrap = styled.div`
+ padding-top: 10px;
+ border-top: 1px solid #ddd;
+ margin-top: 10px;
+
+ ${TransLockingReason} {
+ margin-top: 8px;
+ }
+ ${TransLockingItemDesc} {
+ font-size: 13px;
+ }
+`;
+
+const TransLockWrap = styled.div`
+ ${TransLockingReason} {
+ margin-top: 10px;
+ }
`;
diff --git a/src/containers/TransactionsLocking/utils.js b/src/containers/TransactionsLocking/utils.js
new file mode 100644
index 000000000..f523d65c6
--- /dev/null
+++ b/src/containers/TransactionsLocking/utils.js
@@ -0,0 +1,30 @@
+export const validateMoveToPartialLocking = (all) => {
+ return all.is_enabled;
+};
+
+export const validateMoveToFullLocking = (modules) => {
+ return modules.filter((module) => module.is_enabled);
+};
+
+export const transformItem = (item) => {
+ return {
+ name: item.formatted_module,
+ module: item.module,
+ description: item.description,
+ isEnabled: item.is_enabled,
+ isPartialUnlock: item.is_partial_unlock,
+ lockToDate: item.formatted_lock_to_date,
+ lockReason: item.lock_reason,
+ unlockFromDate: item.formatted_unlock_from_date,
+ unlockToDate: item.formatted_unlock_to_date,
+ unlockReason: item.unlock_reason,
+ partialUnlockReason: item.partial_unlock_reason,
+ };
+};
+
+export const transformList = (res) => {
+ return {
+ all: transformItem(res.all),
+ modules: res.modules.map((module) => transformItem(module)),
+ };
+};
diff --git a/src/containers/UniversalSearch/DashboardUniversalSearchBinds.js b/src/containers/UniversalSearch/DashboardUniversalSearchBinds.js
index ef28e4dd1..2de45627f 100644
--- a/src/containers/UniversalSearch/DashboardUniversalSearchBinds.js
+++ b/src/containers/UniversalSearch/DashboardUniversalSearchBinds.js
@@ -9,6 +9,8 @@ import { universalSearchCustomerBind } from '../Customers/CustomersUniversalSear
import { universalSearchJournalBind } from '../Accounting/ManualJournalUniversalSearch';
import { universalSearchAccountBind } from '../Accounts/AccountUniversalSearch';
import { universalSearchVendorBind } from '../Vendors/VendorsUniversalSearch';
+import { universalSearchCreditNoteBind } from '../Sales/CreditNotes/CreditNoteUniversalSearch';
+import { universalSearchVendorCreditBind } from '../Purchases/CreditNotes/VendorCreditIUniversalSearchBind';
// Universal search binds.
export const universalSearchBinds = [
@@ -23,4 +25,6 @@ export const universalSearchBinds = [
universalSearchCustomerBind,
universalSearchVendorBind,
universalSearchJournalBind,
+ universalSearchCreditNoteBind,
+ universalSearchVendorCreditBind,
];
diff --git a/src/containers/Vendors/VendorsLanding/VendorsListProvider.js b/src/containers/Vendors/VendorsLanding/VendorsListProvider.js
index 8b5be1896..5997120cb 100644
--- a/src/containers/Vendors/VendorsLanding/VendorsListProvider.js
+++ b/src/containers/Vendors/VendorsLanding/VendorsListProvider.js
@@ -53,7 +53,7 @@ function VendorsListProvider({ tableState, tableStateChanged, ...props }) {
return (
diff --git a/src/containers/Vendors/VendorsLanding/components.js b/src/containers/Vendors/VendorsLanding/components.js
index 76bd69217..19c0cf8b8 100644
--- a/src/containers/Vendors/VendorsLanding/components.js
+++ b/src/containers/Vendors/VendorsLanding/components.js
@@ -67,6 +67,7 @@ export function ActionsMenu({
+
}
text={intl.get('delete_vendor')}
diff --git a/src/hooks/query/GenericResource/index.js b/src/hooks/query/GenericResource/index.js
index 27580ce9f..353d9e436 100644
--- a/src/hooks/query/GenericResource/index.js
+++ b/src/hooks/query/GenericResource/index.js
@@ -26,7 +26,7 @@ export function useResourceData(type, query, props) {
/**
* Retrieve the resource url by the given resource type.
- * @param {string} type
+ * @param {string} type
* @returns {string}
*/
function getResourceUrlFromType(type) {
@@ -42,6 +42,8 @@ function getResourceUrlFromType(type) {
[RESOURCES_TYPES.VENDOR]: '/vendors',
[RESOURCES_TYPES.MANUAL_JOURNAL]: '/manual-journals',
[RESOURCES_TYPES.ACCOUNT]: '/accounts',
+ [RESOURCES_TYPES.CREDIT_NOTE]: '/sales/credit_notes',
+ [RESOURCES_TYPES.VENDOR_CREDIT]: '/purchases/vendor-credit',
};
return config[type] || '';
}
@@ -81,7 +83,6 @@ const transformVendors = (response) => ({
items: response.data.vendors,
});
-
const transformPaymentMades = (response) => ({
items: response.data.bill_payments,
});
@@ -104,7 +105,15 @@ const transformsEstimates = (response) => ({
const transformAccounts = (response) => ({
items: response.data.accounts,
-})
+});
+
+const transformCreditNotes = (response) => ({
+ items: response.data.credit_notes,
+});
+
+const transformVendorCredits = (response) => ({
+ items: response.data.vendor_credits,
+});
/**
* Detarmines the transformer based on the given resource type.
@@ -122,7 +131,9 @@ const transformResourceData = (type) => (response) => {
[RESOURCES_TYPES.VENDOR]: transformVendors,
[RESOURCES_TYPES.BILL]: transformBills,
[RESOURCES_TYPES.MANUAL_JOURNAL]: transformManualJournals,
- [RESOURCES_TYPES.ACCOUNT]: transformAccounts
+ [RESOURCES_TYPES.ACCOUNT]: transformAccounts,
+ [RESOURCES_TYPES.CREDIT_NOTE]: transformCreditNotes,
+ [RESOURCES_TYPES.VENDOR_CREDIT]: transformVendorCredits,
};
return {
...pairs[type](response),
diff --git a/src/hooks/query/bills.js b/src/hooks/query/bills.js
index 2ee4b366e..24806a3b6 100644
--- a/src/hooks/query/bills.js
+++ b/src/hooks/query/bills.js
@@ -20,12 +20,19 @@ const commonInvalidateQueries = (queryClient) => {
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
- // Invalidate financial reports.
- queryClient.invalidateQueries(t.FINANCIAL_REPORT);
-
// Invalidate landed cost.
queryClient.invalidateQueries(t.LANDED_COST);
queryClient.invalidateQueries(t.LANDED_COST_TRANSACTION);
+
+ // Invalidate reconcile.
+ queryClient.invalidateQueries(t.RECONCILE_VENDOR_CREDIT);
+ queryClient.invalidateQueries(t.RECONCILE_VENDOR_CREDITS);
+
+ // Invalidate financial reports.
+ queryClient.invalidateQueries(t.FINANCIAL_REPORT);
+
+ // Invalidate items associated bills transactions.
+ queryClient.invalidateQueries(t.ITEMS_ASSOCIATED_WITH_BILLS);
};
/**
@@ -182,3 +189,18 @@ export function useRefreshBills() {
},
};
}
+
+export function useBillPaymentTransactions(id, props) {
+ return useRequestQuery(
+ [t.BILLS_PAYMENT_TRANSACTIONS, id],
+ {
+ method: 'get',
+ url: `purchases/bills/${id}/payment-transactions`,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/creditNote.js b/src/hooks/query/creditNote.js
new file mode 100644
index 000000000..6e06ce622
--- /dev/null
+++ b/src/hooks/query/creditNote.js
@@ -0,0 +1,343 @@
+import { useQueryClient, useMutation } from 'react-query';
+import { useRequestQuery } from '../useQueryRequest';
+import { transformPagination } from 'utils';
+import useApiRequest from '../useRequest';
+import t from './types';
+
+const commonInvalidateQueries = (queryClient) => {
+ // Invalidate credit note.
+ queryClient.invalidateQueries(t.CREDIT_NOTES);
+ queryClient.invalidateQueries(t.CREDIT_NOTE);
+
+ // Invalidate items.
+ queryClient.invalidateQueries(t.ITEMS);
+ queryClient.invalidateQueries(t.ITEM);
+
+ // Invalidate customers.
+ queryClient.invalidateQueries([t.CUSTOMER]);
+ queryClient.invalidateQueries(t.CUSTOMERS);
+
+ // Invalidate accounts.
+ queryClient.invalidateQueries(t.ACCOUNTS);
+ queryClient.invalidateQueries(t.ACCOUNT);
+
+ // Invalidate settings.
+ queryClient.invalidateQueries([t.SETTING, t.SETTING_CREDIT_NOTES]);
+
+ // Invalidate refund credit
+ queryClient.invalidateQueries(t.REFUND_CREDIT_NOTE);
+ queryClient.invalidateQueries(t.REFUND_CREDIT_NOTE_TRANSACTION);
+
+ // Invalidate reconcile.
+ queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTE);
+ queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTES);
+
+ // Invalidate invoices.
+ queryClient.invalidateQueries(t.SALE_INVOICES);
+ queryClient.invalidateQueries(t.SALE_INVOICE);
+
+ // Invalidate cashflow accounts.
+ queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
+
+ // Invalidate financial reports.
+ queryClient.invalidateQueries(t.FINANCIAL_REPORT);
+};
+
+/**
+ * Create a new credit note.
+ */
+export function useCreateCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.post('sales/credit_notes', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Edit the given credit note.
+ */
+export function useEditCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) => apiRequest.post(`sales/credit_notes/${id}`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate credit note query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Delete the given credit note.
+ */
+export function useDeleteCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.delete(`sales/credit_notes/${id}`), {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ });
+}
+
+const transformCreditNotes = (res) => ({
+ creditNotes: res.data.credit_notes,
+ pagination: transformPagination(res.data.pagination),
+ filterMeta: res.data.filter_meta,
+});
+
+/**
+ * Retrieve credit notes list with pagination meta.
+ */
+export function useCreditNotes(query, props) {
+ return useRequestQuery(
+ [t.CREDIT_NOTES, query],
+ { method: 'get', url: 'sales/credit_notes', params: query },
+ {
+ select: transformCreditNotes,
+ defaultData: {
+ creditNotes: [],
+ pagination: {
+ page: 1,
+ pageSize: 20,
+ total: 0,
+ },
+ filterMeta: {},
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve credit note detail of the given id.
+ * @param {number} id
+ *
+ */
+export function useCreditNote(id, props, requestProps) {
+ return useRequestQuery(
+ [t.CREDIT_NOTE, id],
+ { method: 'get', url: `sales/credit_notes/${id}`, ...requestProps },
+ {
+ select: (res) => res.data.credit_note,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
+
+export function useRefreshCreditNotes() {
+ const queryClient = useQueryClient();
+
+ return {
+ refresh: () => {
+ queryClient.invalidateQueries(t.CREDIT_NOTES);
+ },
+ };
+}
+
+/**
+ * Create Round creidt note
+ */
+export function useCreateRefundCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) =>
+ apiRequest.post(`sales/credit_notes/${id}/refund`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate credit note query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Delete the given refund credit note.
+ */
+export function useDeleteRefundCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.delete(`sales/credit_notes/refunds/${id}`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve refund credit note detail of the given id.
+ * @param {number} id
+ *
+ */
+export function useRefundCreditNote(id, props, requestProps) {
+ return useRequestQuery(
+ [t.REFUND_CREDIT_NOTE, id],
+ { method: 'get', url: `sales/credit_notes/${id}/refund`, ...requestProps },
+ {
+ select: (res) => res.data.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
+
+/**
+ * Mark the given credit note as opened.
+ */
+export function useOpenCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.post(`sales/credit_notes/${id}/open`), {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate specific
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ });
+}
+
+/**
+ * Retrieve reconcile credit note of the given id.
+ * @param {number} id
+ *
+ */
+export function useReconcileCreditNote(id, props, requestProps) {
+ return useRequestQuery(
+ [t.RECONCILE_CREDIT_NOTE, id],
+ {
+ method: 'get',
+ url: `sales/credit_notes/${id}/apply-to-invoices`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+/**
+ * Create Reconcile credit note.
+ */
+export function useCreateReconcileCreditNote(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) =>
+ apiRequest.post(`sales/credit_notes/${id}/apply-to-invoices`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate credit note query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve reconcile credit notes.
+ */
+export function useReconcileCreditNotes(id, props, requestProps) {
+ return useRequestQuery(
+ [t.RECONCILE_CREDIT_NOTES, id],
+ {
+ method: 'get',
+ url: `sales/credit_notes/${id}/applied-invoices`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
+
+/**
+ * Delete the given reconcile credit note.
+ */
+export function useDeleteReconcileCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.delete(`sales/credit_notes/applied-to-invoices/${id}`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve refund credit transaction detail.
+ * @param {number} id
+ *
+ */
+export function useRefundCreditTransaction(id, props, requestProps) {
+ return useRequestQuery(
+ [t.REFUND_CREDIT_NOTE_TRANSACTION, id],
+ { method: 'get', url: `sales/credit_notes/refunds/${id}`, ...requestProps },
+ {
+ select: (res) => res.data.refund_credit,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/estimates.js b/src/hooks/query/estimates.js
index b73eae6ce..63ac3e53a 100644
--- a/src/hooks/query/estimates.js
+++ b/src/hooks/query/estimates.js
@@ -9,6 +9,9 @@ import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate estimates.
queryClient.invalidateQueries(t.SALE_ESTIMATES);
+
+ // Invalidate
+ queryClient.invalidateQueries(t.ITEM_ASSOCIATED_WITH_ESTIMATES);
};
/**
@@ -191,7 +194,7 @@ export function useRefreshEstimates() {
}
/**
- *
+ *
*/
export function useCreateNotifyEstimateBySMS(props) {
const queryClient = useQueryClient();
@@ -214,11 +217,11 @@ export function useCreateNotifyEstimateBySMS(props) {
}
/**
- *
- * @param {*} estimateId
- * @param {*} props
- * @param {*} requestProps
- * @returns
+ *
+ * @param {*} estimateId
+ * @param {*} props
+ * @param {*} requestProps
+ * @returns
*/
export function useEstimateSMSDetail(estimateId, props, requestProps) {
return useRequestQuery(
diff --git a/src/hooks/query/index.js b/src/hooks/query/index.js
index e73c09307..629f4f1b4 100644
--- a/src/hooks/query/index.js
+++ b/src/hooks/query/index.js
@@ -28,5 +28,8 @@ export * from './UniversalSearch/UniversalSearch';
export * from './GenericResource';
export * from './jobs';
export * from './misc';
-export * from './cashflowAccounts'
-export * from './roles'
+export * from './cashflowAccounts';
+export * from './roles';
+export * from './creditNote';
+export * from './vendorCredit';
+export * from './transactionsLocking';
diff --git a/src/hooks/query/invoices.js b/src/hooks/query/invoices.js
index aabe2fa07..1223210a9 100644
--- a/src/hooks/query/invoices.js
+++ b/src/hooks/query/invoices.js
@@ -27,6 +27,13 @@ const commonInvalidateQueries = (queryClient) => {
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
+
+ // Invalidate reconcile.
+ queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTE);
+ queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTES);
+
+ // Invalidate
+ queryClient.invalidateQueries(t.ITEM_ASSOCIATED_WITH_INVOICES);
};
/**
@@ -269,3 +276,18 @@ export function useInvoiceSMSDetail(invoiceId, query, props) {
},
);
}
+
+export function useInvoicePaymentTransactions(invoiceId, props) {
+ return useRequestQuery(
+ [t.SALE_INVOICE_PAYMENT_TRANSACTIONS, invoiceId],
+ {
+ method: 'get',
+ url: `sales/invoices/${invoiceId}/payment-transactions`,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/items.js b/src/hooks/query/items.js
index aa5c60559..78fc18533 100644
--- a/src/hooks/query/items.js
+++ b/src/hooks/query/items.js
@@ -172,3 +172,62 @@ export function useItem(id, props) {
},
);
}
+
+export function useItemAssociatedInvoiceTransactions(id, props) {
+ return useRequestQuery(
+ [t.ITEM_ASSOCIATED_WITH_INVOICES, id],
+ {
+ method: 'get',
+ url: `items/${id}/transactions/invoices`,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+export function useItemAssociatedEstimateTransactions(id, props) {
+ return useRequestQuery(
+ [t.ITEM_ASSOCIATED_WITH_ESTIMATES, id],
+ {
+ method: 'get',
+ url: `items/${id}/transactions/estimates`,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+export function useItemAssociatedReceiptTransactions(id, props) {
+ return useRequestQuery(
+ [t.ITEM_ASSOCIATED_WITH_RECEIPTS, id],
+ {
+ method: 'get',
+ url: `items/${id}/transactions/receipts`,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+export function useItemAssociatedBillTransactions(id, props) {
+ return useRequestQuery(
+ [t.ITEMS_ASSOCIATED_WITH_BILLS, id],
+ {
+ method: 'get',
+ url: `items/${id}/transactions/bills`,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/paymentMades.js b/src/hooks/query/paymentMades.js
index f4589b480..9cfad50d8 100644
--- a/src/hooks/query/paymentMades.js
+++ b/src/hooks/query/paymentMades.js
@@ -30,6 +30,9 @@ const commonInvalidateQueries = (client) => {
// Invalidate the cashflow transactions.
client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
+
+ // Invalidate bills payment transactions.
+ client.invalidateQueries(t.BILLS_PAYMENT_TRANSACTIONS);
};
/**
diff --git a/src/hooks/query/paymentReceives.js b/src/hooks/query/paymentReceives.js
index 06e7b39cb..e4bb74be9 100644
--- a/src/hooks/query/paymentReceives.js
+++ b/src/hooks/query/paymentReceives.js
@@ -28,6 +28,16 @@ const commonInvalidateQueries = (client) => {
// Invalidate the cashflow transactions.
client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
+
+ client.invalidateQueries(t.CREDIT_NOTE);
+ client.invalidateQueries(t.CREDIT_NOTES);
+
+ // Invalidate reconcile.
+ client.invalidateQueries(t.RECONCILE_CREDIT_NOTE);
+ client.invalidateQueries(t.RECONCILE_CREDIT_NOTES);
+
+ // Invalidate invoices payment transactions.
+ client.invalidateQueries(t.SALE_INVOICE_PAYMENT_TRANSACTIONS);
};
// Transform payment receives.
diff --git a/src/hooks/query/receipts.js b/src/hooks/query/receipts.js
index a9b0c705b..c2cbeaa22 100644
--- a/src/hooks/query/receipts.js
+++ b/src/hooks/query/receipts.js
@@ -24,6 +24,9 @@ const commonInvalidateQueries = (queryClient) => {
queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
+ // Invalidate
+ queryClient.invalidateQueries(t.ITEM_ASSOCIATED_WITH_RECEIPTS);
+
// Invalidate the settings.
queryClient.invalidateQueries([t.SETTING, t.SETTING_RECEIPTS]);
};
diff --git a/src/hooks/query/settings.js b/src/hooks/query/settings.js
index b7c70b335..bc28b9e57 100644
--- a/src/hooks/query/settings.js
+++ b/src/hooks/query/settings.js
@@ -95,7 +95,7 @@ export function useSettingsReceipts(props) {
export function useSettingsManualJournals(props) {
return useSettingsQuery(
[t.SETTING, t.SETTING_MANUAL_JOURNALS],
- { group: 'sale_receipts' },
+ { group: 'manual_journals' },
props,
);
}
@@ -123,6 +123,27 @@ export function useSettingCashFlow(props) {
);
}
+/**
+ * Retrieve credit notes settings.
+ */
+export function useSettingsCreditNotes(props) {
+ return useSettingsQuery(
+ [t.SETTING, t.SETTING_CREDIT_NOTES],
+ { group: 'credit_note' },
+ props,
+ );
+}
+/**
+ * Retrieve vendor credit settings.
+ */
+export function useSettingsVendorCredits(props) {
+ return useSettingsQuery(
+ [t.SETTING, t.SETTING_VENDOR_CREDITS],
+ { group: 'vendor_credit' },
+ props,
+ );
+}
+
/**
* Retrieve SMS Notifications settings.
*/
diff --git a/src/hooks/query/transactionsLocking.js b/src/hooks/query/transactionsLocking.js
new file mode 100644
index 000000000..8de5016d0
--- /dev/null
+++ b/src/hooks/query/transactionsLocking.js
@@ -0,0 +1,115 @@
+import { useQueryClient, useMutation } from 'react-query';
+import { useRequestQuery } from '../useQueryRequest';
+import { transformPagination } from 'utils';
+import useApiRequest from '../useRequest';
+import { useRequestPdf } from '../utils';
+import t from './types';
+
+// Common invalidate queries.
+const commonInvalidateQueries = (queryClient) => {
+ // Invalidate.
+ queryClient.invalidateQueries(t.TRANSACTION_LOCKING);
+ queryClient.invalidateQueries(t.TRANSACTIONS_LOCKING);
+};
+
+/**
+ * Create a locking transactions.
+ */
+export function useCreateLockingTransactoin(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.put('transactions-locking/lock', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Create cancle locking transactions
+ */
+export function useCancelLockingTransaction(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.put('transactions-locking/cancel-lock', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Create a unlocking partial transactions.
+ */
+export function useCreateUnlockingPartialTransactions(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+ return useMutation(
+ (values) => apiRequest.put('transactions-locking/unlock-partial', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Create cancle unlocking partial transactions.
+ */
+export function useCancelUnlockingPartialTransactions(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+ return useMutation(
+ (values) =>
+ apiRequest.put('transactions-locking/cancel-unlock-partial', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrive the transactions locking.
+ */
+export function useTransactionsLocking(query, props) {
+ return useRequestQuery(
+ [t.TRANSACTIONS_LOCKING, query],
+ { method: 'get', url: 'transactions-locking', params: query },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+export function useEditTransactionsLocking(query, props) {
+ return useRequestQuery(
+ [t.TRANSACTION_LOCKING, query],
+ { method: 'get', url: `transactions-locking/${query}` },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index edec96183..d98f99db8 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -30,6 +30,7 @@ const BILLS = {
BILLS: 'BILLS',
BILL: 'BILL',
BILLS_DUE: 'BILLS_DUE',
+ BILLS_PAYMENT_TRANSACTIONS: 'BILLS_PAYMENT_TRANSACTIONS',
};
const VENDORS = {
@@ -46,6 +47,10 @@ const ITEMS = {
ITEMS: 'ITEMS',
ITEM: 'ITEM',
ITEMS_CATEGORIES: 'ITEMS_CATEGORIES',
+ ITEM_ASSOCIATED_WITH_INVOICES: 'ITEM_ASSOCIATED_WITH_INVOICES',
+ ITEM_ASSOCIATED_WITH_ESTIMATES: 'ITEM_ASSOCIATED_WITH_ESTIMATES',
+ ITEM_ASSOCIATED_WITH_RECEIPTS: 'ITEM_ASSOCIATED_WITH_RECEIPTS',
+ ITEMS_ASSOCIATED_WITH_BILLS: 'ITEMS_ASSOCIATED_WITH_BILLS',
};
const SALE_ESTIMATES = {
@@ -95,6 +100,7 @@ const SALE_INVOICES = {
NOTIFY_SALE_INVOICE_BY_SMS: 'NOTIFY_SALE_INVOICE_BY_SMS',
BAD_DEBT: 'BAD_DEBT',
CANCEL_BAD_DEBT: 'CANCEL_BAD_DEBT',
+ SALE_INVOICE_PAYMENT_TRANSACTIONS: 'SALE_INVOICE_PAYMENT_TRANSACTIONS',
};
const USERS = {
@@ -108,6 +114,24 @@ const ROLES = {
ROLES_PERMISSIONS_SCHEMA: 'ROLES_PERMISSIONS_SCHEMA',
};
+const CREDIT_NOTES = {
+ CREDIT_NOTE: 'CREDIT_NOTE',
+ CREDIT_NOTES: 'CREDIT_NOTES',
+ REFUND_CREDIT_NOTE: 'REFUND_CREDIT_NOTE',
+ REFUND_CREDIT_NOTE_TRANSACTION: 'REFUND_CREDIT_NOTE_TRANSACTION',
+ RECONCILE_CREDIT_NOTE: 'RECONCILE_CREDIT_NOTE',
+ RECONCILE_CREDIT_NOTES: 'RECONCILE_CREDIT_NOTES',
+};
+
+const VENDOR_CREDIT_NOTES = {
+ VENDOR_CREDITS: 'VENDOR_CREDITS',
+ VENDOR_CREDIT: 'VENDOR_CREDIT',
+ REFUND_VENDOR_CREDIT: 'REFUND_VENDOR_CREDIT',
+ REFUND_VENDOR_CREDIT_TRANSACTION: 'REFUND_VENDOR_CREDIT_TRANSACTION',
+ RECONCILE_VENDOR_CREDIT: 'RECONCILE_VENDOR_CREDIT',
+ RECONCILE_VENDOR_CREDITS: 'RECONCILE_VENDOR_CREDITS',
+};
+
const SETTING = {
SETTING: 'SETTING',
SETTING_INVOICES: 'SETTING_INVOICES',
@@ -120,6 +144,8 @@ const SETTING = {
SETTING_SMS_NOTIFICATION: 'SETTING_SMS_NOTIFICATION',
SETTING_SMS_NOTIFICATIONS: 'SETTING_SMS_NOTIFICATIONS',
SETTING_EDIT_SMS_NOTIFICATION: 'SETTING_EDIT_SMS_NOTIFICATION',
+ SETTING_CREDIT_NOTES: 'SETTING_CREDIT_NOTES',
+ SETTING_VENDOR_CREDITS: 'SETTING_VENDOR_CREDITS',
};
const ORGANIZATIONS = {
@@ -160,6 +186,11 @@ const CASH_FLOW_ACCOUNTS = {
'CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY',
};
+const TARNSACTIONS_LOCKING = {
+ TRANSACTION_LOCKING: 'TRANSACTION_LOCKING',
+ TRANSACTIONS_LOCKING: 'TRANSACTIONS_LOCKING',
+};
+
export default {
...ACCOUNTS,
...BILLS,
@@ -184,4 +215,7 @@ export default {
...CONTACTS,
...CASH_FLOW_ACCOUNTS,
...ROLES,
+ ...CREDIT_NOTES,
+ ...VENDOR_CREDIT_NOTES,
+ ...TARNSACTIONS_LOCKING,
};
diff --git a/src/hooks/query/vendorCredit.js b/src/hooks/query/vendorCredit.js
new file mode 100644
index 000000000..927456d94
--- /dev/null
+++ b/src/hooks/query/vendorCredit.js
@@ -0,0 +1,360 @@
+import { useQueryClient, useMutation } from 'react-query';
+import { useRequestQuery } from '../useQueryRequest';
+import { transformPagination } from 'utils';
+import useApiRequest from '../useRequest';
+import t from './types';
+
+const commonInvalidateQueries = (queryClient) => {
+ // Invalidate vendor credit.
+ queryClient.invalidateQueries(t.VENDOR_CREDITS);
+ queryClient.invalidateQueries(t.VENDOR_CREDIT);
+
+ // Invalidate items.
+ queryClient.invalidateQueries(t.ITEMS);
+ queryClient.invalidateQueries(t.ITEM);
+
+ // Invalidate vendors.
+ queryClient.invalidateQueries([t.VENDORS]);
+ queryClient.invalidateQueries(t.VENDOR);
+
+ // Invalidate accounts.
+ queryClient.invalidateQueries(t.ACCOUNTS);
+ queryClient.invalidateQueries(t.ACCOUNT);
+
+ // Invalidate settings.
+ queryClient.invalidateQueries([t.SETTING, t.SETTING_VENDOR_CREDITS]);
+
+ // Invalidate refund vendor credit
+ queryClient.invalidateQueries(t.REFUND_VENDOR_CREDIT);
+ queryClient.invalidateQueries(t.REFUND_VENDOR_CREDIT_TRANSACTION);
+
+ // Invalidate reconcile vendor credit.
+ queryClient.invalidateQueries(t.RECONCILE_VENDOR_CREDIT);
+ queryClient.invalidateQueries(t.RECONCILE_VENDOR_CREDITS);
+
+ // Invalidate bills.
+ queryClient.invalidateQueries(t.BILL);
+ queryClient.invalidateQueries(t.BILLS);
+
+ // Invalidate cashflow accounts.
+ queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
+
+ // Invalidate financial reports.
+ queryClient.invalidateQueries(t.FINANCIAL_REPORT);
+};
+
+/**
+ * Create a new vendor credit.
+ */
+export function useCreateVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.post('purchases/vendor-credit', values),
+ {
+ onSuccess: (res, values) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Edit the given vendor credit.
+ */
+export function useEditVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) => apiRequest.post(`purchases/vendor-credit/${id}`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.VENDOR_CREDIT, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Delete the given vendor credit.
+ */
+export function useDeleteVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.delete(`purchases/vendor-credit/${id}`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.VENDOR_CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+const transformVendorCreditsResponse = (response) => ({
+ vendorCredits: response.data.vendor_credits,
+ pagination: transformPagination(response.data.pagination),
+ filterMeta: response.data.filter_meta,
+});
+
+/**
+ * Retrieve vendor credit notes list with pagination meta.
+ */
+export function useVendorCredits(query, props) {
+ return useRequestQuery(
+ [t.VENDOR_CREDITS, query],
+ {
+ method: 'get',
+ url: 'purchases/vendor-credit',
+ params: query,
+ },
+ {
+ select: transformVendorCreditsResponse,
+ defaultData: {
+ vendorCredits: [],
+ pagination: {
+ page: 1,
+ page_size: 12,
+ total: 0,
+ },
+ filterMeta: {},
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve vendor credit detail of the given id.
+ * @param {number} id
+ *
+ */
+export function useVendorCredit(id, props, requestProps) {
+ return useRequestQuery(
+ [t.VENDOR_CREDIT, id],
+ { method: 'get', url: `purchases/vendor-credit/${id}`, ...requestProps },
+ {
+ select: (res) => res.data.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
+
+export function useRefreshVendorCredits() {
+ const queryClient = useQueryClient();
+
+ return {
+ refresh: () => {
+ queryClient.invalidateQueries(t.VENDOR_CREDITS);
+ },
+ };
+}
+
+/**
+ * Create Round vendor creidt
+ */
+export function useCreateRefundVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) =>
+ apiRequest.post(`purchases/vendor-credit/${id}/refund`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate credit note query.
+ queryClient.invalidateQueries([t.VENDOR_CREDIT, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Delete the given refund vendor credit.
+ */
+export function useDeleteRefundVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.delete(`purchases/vendor-credit/refunds/${id}`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve refund credit note detail of the given id.
+ * @param {number} id
+ *
+ */
+export function useRefundVendorCredit(id, props, requestProps) {
+ return useRequestQuery(
+ [t.REFUND_VENDOR_CREDIT, id],
+ {
+ method: 'get',
+ url: `purchases/vendor-credit/${id}/refund`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
+
+/**
+ * Mark the given vendor credit as opened.
+ */
+export function useOpenVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.post(`purchases/vendor-credit/${id}/open`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate specific.
+ queryClient.invalidateQueries([t.VENDOR_CREDIT, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Create Reconcile vendor credit.
+ */
+export function useCreateReconcileVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ ([id, values]) =>
+ apiRequest.post(`purchases/vendor-credit/${id}/apply-to-bills`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate credit note query.
+ queryClient.invalidateQueries([t.VENDOR_CREDIT, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve reconcile vendor credit of the given id.
+ * @param {number} id
+ *
+ */
+export function useReconcileVendorCredit(id, props, requestProps) {
+ return useRequestQuery(
+ [t.RECONCILE_VENDOR_CREDIT, id],
+ {
+ method: 'get',
+ url: `purchases/vendor-credit/${id}/apply-to-bills`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve reconcile credit notes.
+ */
+export function useReconcileVendorCredits(id, props, requestProps) {
+ return useRequestQuery(
+ [t.RECONCILE_VENDOR_CREDITS, id],
+ {
+ method: 'get',
+ url: `purchases/vendor-credit/${id}/applied-bills`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
+/**
+ * Delete the given reconcile vendor credit.
+ */
+export function useDeleteReconcileVendorCredit(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.delete(`purchases/vendor-credit/applied-to-bills/${id}`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate vendor credit query.
+ queryClient.invalidateQueries([t.VENDOR_CREDIT, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve refund vendor transaction detail.
+ * @param {number} id
+ *
+ */
+export function useRefundVendorCreditTransaction(id, props, requestProps) {
+ return useRequestQuery(
+ [t.REFUND_VENDOR_CREDIT_TRANSACTION, id],
+ {
+ method: 'get',
+ url: `purchases/vendor-credit/refunds/${id}`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.refund_credit,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/useRequest.js b/src/hooks/useRequest.js
index f27edbd4e..aae07bb13 100644
--- a/src/hooks/useRequest.js
+++ b/src/hooks/useRequest.js
@@ -12,7 +12,7 @@ export default function useApiRequest() {
const setGlobalErrors = useSetGlobalErrors();
const { setLogout } = useAuthActions();
const currentLocale = getCookie('locale');
-
+
// Authentication token.
const token = useAuthToken();
@@ -47,7 +47,7 @@ export default function useApiRequest() {
instance.interceptors.response.use(
(response) => response,
(error) => {
- const { status } = error.response;
+ const { status, data } = error.response;
if (status >= 500) {
setGlobalErrors({ something_wrong: true });
@@ -57,7 +57,19 @@ export default function useApiRequest() {
setLogout();
}
if (status === 403) {
- setGlobalErrors({ access_denied: true })
+ setGlobalErrors({ access_denied: true });
+ }
+ if (status === 400) {
+ const lockedError = data.errors.find(
+ (error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
+ );
+ if (lockedError) {
+ setGlobalErrors({ transactionsLocked: { ...lockedError.data } });
+ }
+ if (data.errors.find(e => e.type === 'USER_INACTIVE')) {
+ setGlobalErrors({ userInactive: true });
+ setLogout();
+ }
}
return Promise.reject(error);
},
@@ -65,27 +77,30 @@ export default function useApiRequest() {
return instance;
}, [token, organizationId, setGlobalErrors, setLogout]);
- return React.useMemo(() => ({
- http,
+ return React.useMemo(
+ () => ({
+ http,
- get(resource, params) {
- return http.get(`/api/${resource}`, params);
- },
+ get(resource, params) {
+ return http.get(`/api/${resource}`, params);
+ },
- post(resource, params, config) {
- return http.post(`/api/${resource}`, params, config);
- },
+ post(resource, params, config) {
+ return http.post(`/api/${resource}`, params, config);
+ },
- update(resource, slug, params) {
- return http.put(`/api/${resource}/${slug}`, params);
- },
+ update(resource, slug, params) {
+ return http.put(`/api/${resource}/${slug}`, params);
+ },
- put(resource, params) {
- return http.put(`/api/${resource}`, params);
- },
+ put(resource, params) {
+ return http.put(`/api/${resource}`, params);
+ },
- delete(resource, params) {
- return http.delete(`/api/${resource}`, params);
- },
- }), [http]);
+ delete(resource, params) {
+ return http.delete(`/api/${resource}`, params);
+ },
+ }),
+ [http],
+ );
}
diff --git a/src/hooks/utils/index.js b/src/hooks/utils/index.js
index 5d189d42e..ba26d0fa2 100644
--- a/src/hooks/utils/index.js
+++ b/src/hooks/utils/index.js
@@ -6,4 +6,6 @@ export * from './useWhen';
export * from './useRequestPdf';
export * from './useAsync';
export * from './useIntersectionObserver';
-export * from './useAbilityContext';
\ No newline at end of file
+export * from './useAbilityContext';
+export * from './useCustomCompareEffect';
+export * from './useDeepCompareEffect';
diff --git a/src/hooks/utils/useCustomCompareEffect.ts b/src/hooks/utils/useCustomCompareEffect.ts
new file mode 100644
index 000000000..c67e6488a
--- /dev/null
+++ b/src/hooks/utils/useCustomCompareEffect.ts
@@ -0,0 +1,44 @@
+import { DependencyList, EffectCallback, useEffect, useRef } from 'react';
+
+const isPrimitive = (val: any) => val !== Object(val);
+
+type DepsEqualFnType = (
+ prevDeps: TDeps,
+ nextDeps: TDeps,
+) => boolean;
+
+const useCustomCompareEffect = (
+ effect: EffectCallback,
+ deps: TDeps,
+ depsEqual: DepsEqualFnType,
+) => {
+ if (process.env.NODE_ENV !== 'production') {
+ if (!(deps instanceof Array) || !deps.length) {
+ console.warn(
+ '`useCustomCompareEffect` should not be used with no dependencies. Use React.useEffect instead.',
+ );
+ }
+
+ if (deps.every(isPrimitive)) {
+ console.warn(
+ '`useCustomCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.',
+ );
+ }
+
+ if (typeof depsEqual !== 'function') {
+ console.warn(
+ '`useCustomCompareEffect` should be used with depsEqual callback for comparing deps list',
+ );
+ }
+ }
+
+ const ref = useRef(undefined);
+
+ if (!ref.current || !depsEqual(deps, ref.current)) {
+ ref.current = deps;
+ }
+
+ useEffect(effect, ref.current);
+};
+
+export { useCustomCompareEffect };
diff --git a/src/hooks/utils/useDeepCompareEffect.ts b/src/hooks/utils/useDeepCompareEffect.ts
new file mode 100644
index 000000000..8504cc09f
--- /dev/null
+++ b/src/hooks/utils/useDeepCompareEffect.ts
@@ -0,0 +1,24 @@
+import { DependencyList, EffectCallback } from 'react';
+import isDeepEqualReact from 'fast-deep-equal/react';
+import { useCustomCompareEffect } from './useCustomCompareEffect';
+
+const isPrimitive = (val: any) => val !== Object(val);
+
+const useDeepCompareEffect = (effect: EffectCallback, deps: DependencyList) => {
+ if (process.env.NODE_ENV !== 'production') {
+ if (!(deps instanceof Array) || !deps.length) {
+ console.warn(
+ '`useDeepCompareEffect` should not be used with no dependencies. Use React.useEffect instead.',
+ );
+ }
+
+ if (deps.every(isPrimitive)) {
+ console.warn(
+ '`useDeepCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.',
+ );
+ }
+ }
+ useCustomCompareEffect(effect, deps, isDeepEqualReact);
+};
+
+export { useDeepCompareEffect };
diff --git a/src/lang/ar/index.json b/src/lang/ar/index.json
index dde1374c1..97c82f290 100644
--- a/src/lang/ar/index.json
+++ b/src/lang/ar/index.json
@@ -11,7 +11,7 @@
"field_name_must_be_number": "field_name_must_be_number",
"name": "اسم",
"quick_find": "البحث السريع",
- "reference": "المرجعي #",
+ "reference": "رقم المرجعي ",
"date": "تاريخ",
"description": "الوصف",
"from_date": "من التاريخ",
@@ -370,7 +370,7 @@
"payment_account_": "حساب الدفع",
"expense_category": "تصنيف المصاريف",
"total_currency": "الإجمالي ({currency})",
- "amount_currency": "العملة كمية})",
+ "amount_currency": "كمية ({currency})",
"publish_expense": "نشر المصروف",
"edit_expense": "تعديل المصروف",
"delete_expense": "حذف المصروف",
@@ -512,7 +512,7 @@
"invoice_date": "تاريخ الفاتورة",
"due_date": "تاريخ الاستحقاق",
"invoice_date_": "تاريخ الفاتورة",
- "invoice_no": "فاتورة #",
+ "invoice_no": " رقم فاتورة",
"invoice_no__": "رقم الفاتورة",
"invoice_no_": "رقم الفاتورة",
"due_date_": "تاريخ الاستحقاق",
@@ -532,7 +532,7 @@
"once_delete_this_invoice_you_will_able_to_restore_it": "بمجرد حذف هذه الفاتورة ، لن تتمكن من استعادتها لاحقًا. هل أنت متأكد أنك تريد حذف هذه الفاتورة؟",
"receipts_list": "قائمة الإيصالات",
"receipts": "الإيصالات",
- "receipt": "إيصال #",
+ "receipt": "رقم إيصال ",
"receipt_date_": "تاريخ استلام",
"receipt_date": "تاريخ استلام",
"deposit_account_": "حساب إيداع",
@@ -664,7 +664,7 @@
"bill_number_exists": "رقم الفاتورة موجود",
"ok": "نعم!",
"quantity_cannot_be_zero_or_empty": "لا يمكن أن تكون الكمية صفراً أو فارغة.",
- "customer_email": "البريد إلكتروني الزبون",
+ "customer_email": "البريد إلكتروني ",
"customer_phone_number": "رقم هاتف الزبون",
"opening_balance_at": "الرصيد الافتتاحي عند",
"opening_balance": "الرصيد الافتتاحي",
@@ -689,7 +689,7 @@
"customer_has_sales_invoices": "لا يمكن حذف الزبون لديه فواتير المبيعات مرتبطة.",
"account_name_is_already_used": "اسم الحساب مستخدم بالفعل.",
"vendors": "الموردين",
- "vendor_email": "البريد إلكتروني المورد",
+ "vendor_email": "البريد إلكتروني",
"new_vendor": "مورد جديد",
"edit_vendor": "تعديل المورد",
"delete_vendor": "حذف المورد",
@@ -714,32 +714,33 @@
"email_is_already_used": "البريد الإلكتروني مستخدم بالفعل.",
"the_item_categories_has_been_deleted_successfully": "تم حذف تصنيفات المنتجات بنجاح.",
"receivable_accounts_should_assign_with_customers": "حسابات القبض مع العملاء.",
- "delivered": "تم التوصيل",
+ "delivered": "تم التسليم",
"save_and_deliver": "حفظ وتسليم",
"deliver_and_new": "تسليم وجديد",
"deliver_continue_editing": "تسليم (متابعة التعديل)",
"due_in": "موعد التسليم {due} يوم.",
"day_partially_paid": "مدفوعة جزئياً ، {due} مستحق.",
"overdue_by": "تأخرت بحلول {overdue} يوم.",
- "paid": "مدفوع",
+ "paid": "تم الدفع",
+ "due": "مستحقه",
"your_account_has_been_locked": "تم قفل حسابك بسبب محاولات تسجيل الدخول الفاشلة المتكررة. يرجى الانتظار بضع دقائق قبل المحاولة مرة أخرى.",
"the_invoice_has_been_delivered_successfully": "تم تسليم الفاتورة بنجاح.",
"are_sure_to_deliver_this_invoice": "هل أنت متأكد أنك تريد تسليم هذه الفاتورة؟",
"mark_as_delivered": "وضع علامة \"تم التسليم\"",
"deliver": "ايصال",
"mark_as_closed": "وضع علامة مغلق",
- "mark_as_opened": "وضع علامة مفتوح",
+ "mark_as_open": "وضع علامة مفتوح",
"save_close": "حفظ وإغلاق",
"save_open": "حفظ وفتح",
"close_and_new": "قريب وجديد",
"close_continue_editing": "إغلاق (متابعة التعديل)",
"the_receipt_has_been_closed_successfully": "تم إغلاق الإيصال بنجاح.",
"are_sure_to_close_this_receipt": "هل أنت متأكد أنك تريد إغلاق هذا الإيصال؟",
- "closed": "مغلق",
+ "closed": "مغلقة ",
"open_and_new": "مفتوح وجديد",
"open_continue_editing": "فتح (متابعة التعديل)",
"the_bill_has_been_opened_successfully": "تم فتح الفاتورة بنجاح.",
- "open": "فتح",
+ "open": "مفتوحة ",
"are_sure_to_open_this_bill": "هل أنت متأكد أنك تريد فتح هذه الفاتورة؟",
"opened": "مفتوح",
"the_estimate_has_been_delivered_successfully": "تم تسليم العرض بنجاح.",
@@ -784,6 +785,8 @@
"the_adjustment_transaction_has_been_created_successfully": "تم إضافة معاملة تسوية المخزون علي الصنف بنجاح.",
"the_adjustment_transaction_has_been_deleted_successfully": "تم حذف معاملة تسوية المخزون بنجاح.",
"once_delete_this_inventory_a_adjustment_you_will_able_to_restore_it": "بمجرد حذف هذا المخزون تعديلًا ، لن تتمكن من استعادته لاحقًا. هل أنت متأكد أنك تريد حذف هذه الفاتورة؟",
+ "inventory_adjustment.publish.success_message": "تم نشر معاملة تسوية المخزون بنجاح. ",
+ "inventory_adjustment.publish.alert_message": "هل أنت متأكد أنك تريد نشر معاملة تسوية المخزون؟",
"select_adjustment_account": "حدد حساب التسوية",
"qty": "الكمية الحالية",
"money_format": "شكل القيم المالية",
@@ -1142,7 +1145,6 @@
"Getting started": "Getting started",
"Congratulations": "Congratulations",
"payment_has_been_done_successfully": "Payment has been done successfully.",
- "manual_journal_number": "Manual journal {number}",
"conditions_and_terms": "Conditions and terms",
"allocate_landed_coast": "تحميل تكلفة اضافية",
"transaction_date": "تاريخ المعاملة",
@@ -1221,6 +1223,7 @@
"payment_receive.details.payment_number": "رقم العملية",
"payment_receive.details.total": "إجمالي",
"payment_receive.details.subtotal": "المجموع",
+ "payment_receive.details.statement": "بيان",
"estimate.details.estimate_number": "رقم العرض",
"estimate.details.subtotal": "المجموع",
"estimate.details.total": "إجمالي",
@@ -1228,11 +1231,14 @@
"estimate.details.due_amount": "مبلغ المستحق",
"estimate.details.note": "ملاحظة",
"estimate.details.created_at": "أنشئت في",
+ "estimate.details.terms_conditions": "الشروط والأحكام",
"receipt.details.receipt_number": "رقم إيصال",
"receipt.details.subtotal": "المجموع",
"receipt.details.total": "إجمالي",
"receipt.details.payment_amount": "مبلغ المدفوع",
"receipt.details.due_amount": "مبلغ المستحق",
+ "receipt.details.receipt_message": "رسالة إيصال",
+ "receipt.details.statement": "بيان",
"receipt.details.created_at": "أنشئت في",
"bill.details.bill_number": "رقم الفاتورة",
"bill.details.created_at": "أنشئت في",
@@ -1240,11 +1246,15 @@
"bill.details.subtotal": "المجموع",
"bill.details.payment_amount": "مبلغ المدفوع",
"bill.details.due_amount": "مبلغ المستحق",
+ "bill.drawer.title": "تفاصيل فاتورة الشراء {number}",
"invoice.details.created_at": "أنشئت في",
"invoice.details.total": "إجمالي",
"invoice.details.subtotal": "المجموع",
"invoice.details.due_amount": "مبلغ المستحق",
"invoice.details.payment_amount": "مبلغ المدفوع",
+ "invoice.details.invoice_no": "رقم الفاتورة",
+ "invoice.details.invoice_message": " رسالة الفاتورة ",
+ "invoice_details.drawer.title": "تفاصيل الفاتورة البيع ({invoiceNumber}) ",
"expense.details.subtotal": "المجموع",
"expense.details.total": "إجمالي",
"manual_journal.details.subtotal": "المجموع",
@@ -1417,7 +1427,7 @@
"cash_flow_transaction.money_out": "سحب من حساب {value}",
"cash_flow_transaction.other_income_account": " حساب الإيرادات الأخرى ",
"cash_flow_transaction.other_expense_account": "حساب مصاريف اخري",
- "save_and_publish": "احفظ وانشر",
+ "save_and_publish": "حفظ ونشر",
"cash_flow_transaction.label_transfer_from_account": "تحويل من الحساب ",
"cash_flow_transaction.label_transfer_to_account": "تحويل إلى الحساب ",
"cash_flow_transaction.label_current_account": "حساب الحالي",
@@ -1436,8 +1446,8 @@
"cash_flow_transaction.switch_item": " {value} معاملة علي حساب",
"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.bad_debt": "دين معدوم",
+ "bad_debt.dialog.cancel_bad_debt": "إلغاء الدين المعدوم",
"bad_debt.dialog.header_note": "يمكن للبائع تحميل مبلغ الفاتورة على حساب مصروفات الديون المعدومة عندما يكون من المؤكد أن الفاتورة لن يتم دفعها.",
"bad_debt.dialog.success_message": "تم شطب فاتورة البيع المقدمة بنجاح.",
"bad_debt.cancel_alert.success_message": "تم إلغاء شطب فاتورة البيع المقدمة بنجاح.",
@@ -1482,21 +1492,266 @@
"sms_notification.payment_details.type": "شكر علي عملية الدفع",
"sms_notification.receipt_details.type": "تفاصيل إيصال البيع",
"personal": "المحمول",
- "list.create":"إضافة {value}",
- "roles.label":"دور المستخدمين",
- "roles.column.name":"اسم الدور",
- "roles.column.description":"الوصف",
- "roles.edit_roles":" تعديل دور المستخدم",
- "roles.delete_roles":"حذف دور المستخدم",
- "roles.label.role_name":"دور المستخدم",
- "roles.error.role_is_predefined":"دور المستخدم معرَّف مسبقًا ، ولا يمكنك حذف دور المستخدمين المحددة مسبقًا ",
- "roles.error.you_cannot_change_your_own_role":"لا يمكنك تغيير دور المستخدم الخاص بك.",
- "roles.label.role_name_":"اسم دور المستخدم ",
- "roles.permission_schema.success_message":"تم اضافة دور المستخدم بنجاح.",
- "roles.permission_schema.upload_message":"تم تحديث دور المستخدم بنجاح.",
- "roles.permission_schema.delete.alert_message":"تم حذف دور المستخدم بنجاح. ",
- "roles.permission_schema.once_delete_this_role_you_will_able_to_restore_it":"بمجرد حذف دور المستخدم ، لن تتمكن من استعادتها لاحقًا. هل أنت متأكد أنك تريد حذف هذا الدور؟",
- "users.column.role_name":"دور المستخدم",
- "roles.error.you_cannot_edit_predefined_roles":"لا يمكنك تعديل أدوار المستخدم المحددة مسبقا.",
- "roles.error.you_cannot_delete_predefined_roles":"لا يمكنك حذف أدوار المستخدم المحددة مسبقا"
+ "list.create": "إضافة {value}",
+ "roles.label": "دور المستخدمين",
+ "roles.column.name": "اسم الدور",
+ "roles.column.description": "الوصف",
+ "roles.edit_roles": " تعديل دور المستخدم",
+ "roles.delete_roles": "حذف دور المستخدم",
+ "roles.label.role_name": "اسم الدور",
+ "roles.error.role_is_predefined": "دور المستخدم معرَّف مسبقًا ، ولا يمكنك حذف دور المستخدمين المحددة مسبقًا ",
+ "roles.error.you_cannot_change_your_own_role": "لا يمكنك تغيير دور المستخدم الخاص بك.",
+ "roles.label.role_name_": "اسم دور المستخدم ",
+ "roles.permission_schema.success_message": "تم اضافة دور المستخدم بنجاح.",
+ "roles.permission_schema.upload_message": "تم تحديث دور المستخدم بنجاح.",
+ "roles.permission_schema.delete.alert_message": "تم حذف دور المستخدم بنجاح. ",
+ "roles.permission_schema.once_delete_this_role_you_will_able_to_restore_it": "بمجرد حذف دور المستخدم ، لن تتمكن من استعادته لاحقًا. هل أنت متأكد أنك تريد حذف هذا الدور؟",
+ "users.column.role_name": "دور المستخدم",
+ "roles.error.you_cannot_edit_predefined_roles": "لا يمكنك تعديل أدوار المستخدم المحددة مسبقا.",
+ "roles.error.you_cannot_delete_predefined_roles": "لا يمكنك حذف أدوار المستخدم المحددة مسبقا",
+ "roles.error.you_cannot_delete_role_that_associated_to_users": "لا يمكن حذف دور المستخدم لأنه لديه مستخدمين مرتبطة به.",
+ "payment_transactions": "معاملات الدفع",
+ "sidebar_credit_note": "إشعارات الدائن",
+ "credit_note.label_create_note_list": "قائمة إشعارات الدائن",
+ "credit_note.label.new_credit_note": "إشعار دائن جديد",
+ "credit_note.label.edit_credit_note": "تعديل إشعار دائن ",
+ "credit_note.label_credit_note": " رقم إشعار الدائن",
+ "credit_note.action.refund_credit_note": " استرجاع الأموال",
+ "credit_note.action.reconcile_with_invoices": "تسوية فواتير المبيعات ",
+ "credit_note.action.make_as_open": "وضع علامة مفتوح",
+ "credit_note.action.delete_credit_note": " حذف إشعار الدائن ",
+ "credit_note.action.edit_credit_note": "تعديل إشعار دائن",
+ "credit_note.column.credit_note_no": "إشعار الدائن #",
+ "credit_note.column.credit_date": "تاريخ دائن",
+ "credit_note.empty_status.title": "خفض أرصدة الزبائن عن طريقة إنشاء إشعار دائن",
+ "credit_note.empty_status.description": "إشعار دائن وهو مستند تجاري يعطى للزبون عند إرجاع البضائع ، مع امكانية اضافة عملية استرجاع اموال او إضافته إلي فواتير البيع التي لم تدفع.",
+ "credit_note.label_credit_note_date": "تاريخ إشعار الدائن",
+ "credit_note.label_amount_to_credit": "قيمة الدائنة",
+ "credit_note.label_credit_note_details": "تفاصيل إشعار الدائن",
+ "credit_note.label_customer_note": "ملاحظة الزبون",
+ "credit_note.once_delete_this_credit_note": " بمجرد حذف إشعار الدائن ، لن تتمكن من استعادته لاحقًا. هل أنت متأكد أنك تريد حذف هذا إشعار",
+ "credit_note.alert.delete_message": "تم حذف إشعار الدائن بنجاح",
+ "credit_note.label": "إشعارات الدائن",
+ "credit_note.success_message": "تم إنشاء إشعار الدائن بنجاح.",
+ "credit_note.edit_success_message": "تم تعديل إشعار الدائن بنجاح.",
+ "credit_note_number_settings": "إعدادات رقم إشعار الدائن",
+ "credit_note.auto_increment.auto": "يتم تعيين أرقام إشعارات الدائن على وضع الزيادة التلقائي. هل أنت متأكد من تغيير هذا الإعداد؟",
+ "credit_note.auto_increment.manually": "يتم تعيين أرقام إشعارات الدائن على وضع الزيادة التلقائي. هل أنت متأكد من تغيير هذا الإعداد؟",
+ "setting_your_auto_generated_credit_note_number": "تعيين رقم إشعار الدائن الذي تم إنشاؤه تلقائيًا",
+ "credit_note.drawer.label_credit_note_no": "رقم الإشعار",
+ "credit_note.drawer.label_credit_note_date": "تاريخ الإشعار",
+ "credit_note.drawer.label_credits_remaining": "الرصيد المتبقي ",
+ "credit_note.drawer.label_created_at": "أنشئت في",
+ "credit_note.drawer.label_total": "إجمالي",
+ "credit_note.drawer.label_subtotal": "المجموع",
+ "credit_note.drawer.label_refund_transactions": "معاملات استرجاع الأموال ",
+ "credit_note.drawer.label_invoices_reconciled": "تسوية فواتير المبيعات",
+ "sidebar_vendor_credits": "إشعارات المدين",
+ "vendor_credits.lable_vendor_credit_list": "قائمة إشعارات المدين",
+ "vendor_credits.label.new_vendor_credit": "إشعار مدين جديد",
+ "vendor_credits.label.edit_vendor_credit": "تعديل إشعار مدين",
+ "vendor_credits.label.amount_to_credit": "قيمة الدائنة",
+ "vendor_credits_note.label_credit_note_details": "تفاصيل إشعار المدين",
+ "vendor_credits.column.vendor_credit_no": "رقم إشعار المدين ",
+ "vendor_credits.status_open": "مفتوحة ",
+ "vendor_credits.status_closed": "مغلقة",
+ "vendor_credits.action.edit_vendor_credit": "تعديل إشعار مدين",
+ "vendor_credits.action.refund_vendor_credit": "استرجاع الأموال",
+ "vendor_credits.action.delete_vendor_credit": "حذف إشعار المدين",
+ "vendor_credits.action.mark_as_open": "وضع علامة مفتوح",
+ "vendor_credits.action.reconcile_with_bills": "تسوية فواتير الشراء ",
+ "vendor_credits.success_message": "تم إنشاء إشعار المدين بنجاح.",
+ "vendor_credits.edit_success_message": "تم تعديل إشعار المدين بنجاح.",
+ "vendor_credits.alert.delete_message": "تم حذف إشعار المدين بنجاح",
+ "vendor_credits.note.once_delete_this_vendor_credit_note": " بمجرد حذف إشعار المدين ، لن تتمكن من استعادته لاحقًا. هل أنت متأكد أنك تريد حذف هذا إشعار ",
+ "vendor_credits.empty_status.title": "خفض أرصدة الموردين عن طريق إنشاء إشعار مدين",
+ "vendor_credits.empty_status.description": "إشعار المدين هو المستند الذي يرسل إلى المورد و يجعله مديناً للمنشأة ، فهو إثبات من قبل المنشأة أن لها حق يجب أخذه من المورد.",
+ "vendor_credit_number_settings": "إعدادات رقم إشعار المدين",
+ "vendor_credit.auto_increment.auto": "يتم تعيين أرقام إشعارات المدين على وضع الزيادة التلقائي. هل أنت متأكد من تغيير هذا الإعداد؟",
+ "vendor_credit.auto_increment.manually": "يتم تعيين أرقام إشعارات المدين على وضع الزيادة التلقائي. هل أنت متأكد من تغيير هذا الإعداد؟",
+ "setting_your_auto_generated_vendor_credit_number": "تعيين رقم إشعار المدين الذي تم إنشاؤه تلقائيًا",
+ "vendor_credit.label": "إشعارات المدين",
+ "vendor_credit.drawer_vendor_credit_detail": "تفاصيل إشعار المدين ({vendorNumber})",
+ "vendor_credit.drawer.label_vendor_credit_no": "رقم الإشعار",
+ "vendor_credit.drawer.label_vendor_credit_date": "تاريخ الإشعار",
+ "vendor_credit.drawer.label_credits_remaining": "الرصيد المتبقي",
+ "vendor_credit.drawer.label_created_at": "أنشئت في",
+ "vendor_credit.drawer.label_total": "إجمالي",
+ "vendor_credit.drawer.label_subtotal": "المجموع",
+ "vendor_credit.drawer.label_refund_transactions": "معاملات استرجاع الأموال ",
+ "vendor_credit.drawer.label_bills_reconciled": "تسوية فواتير الشراء",
+ "refund": "استرجاع",
+ "landed_cost.dialog.label_select_transaction": "حدد المعاملة ",
+ "landed_cost.dialog.label_select_transaction_entry": "حدد سطر المعاملة ",
+ "refund_credit_note.dialog.label": "استرجاع اموال",
+ "refund_credit_note.dialog.success_message": "تم انشاء معاملة استرجاع الاموال لإشعار الدائن بنجاح.",
+ "refund_credit_note.dialog.refund_date": "تاريخ الاسترجاع",
+ "refund_credit_note.dialog.amount": "القيمة",
+ "refund_credit_note.dialog.description": "الوصف",
+ "refund_credit_note.dialog.from_account": "حساب السحب",
+ "refund_vendor_credit.dialog.label": "استرجاع اموال",
+ "refund_vendor_credit.dialog.success_message": "تم انشاء معاملة استرجاع الاموال لإشعار المدين بنجاح.",
+ "refund_vendor_credit.dialog.refund_date": "تاريخ الاسترجاع",
+ "refund_vendor_credit.dialog.amount": "القيمة",
+ "refund_vendor_credit.dialog.description": "الوصف",
+ "refund_vendor_credit.dialog.deposit_to_account": "حساب الإيداع",
+ "refund_credit_transactions.column.amount_refunded": "قيمة",
+ "refund_credit_transactions.column.withdrawal_account": "حساب السحب",
+ "refund_credit_transactions.alert.delete_message": "تم حذف معاملة استرجاع الاموال لإشعار الدائن بنجاح.",
+ "refund_credit_transactions.once_your_delete_this_refund_credit_note": "بمجرد حذف معاملة استرجاع الاموال ، لن تتمكن من استعادتها لاحقًا. هل أنت متأكد أنك تريد حذف هذه المعاملة؟",
+ "refund_vendor_credit.column.amount": "القيمة",
+ "refund_vendor_credit.column.withdrawal_account": "حساب السحب",
+ "refund_vendor_credit_transactions.alert.delete_message": "تم حذف معاملة استرجاع الاموال لإشعار المدين بنجاح.",
+ "refund_vendor_credit_transactions.once_your_delete_this_refund_vendor_credit": "بمجرد حذف معاملة استرجاع الاموال ، لن تتمكن من استعادتها لاحقًا. هل أنت متأكد أنك تريد حذف هذه المعاملة؟",
+ "credit_note_opened.alert.success_message": "تم فتح إشعار الدائن بنجاح.",
+ "credit_note_opened.are_sure_to_open_this_credit": "هل أنت متأكد أنك تريد فتح هذا إشعار الدائن؟",
+ "reconcile_credit_note.label": "تسوية إشعار الدائن بالفواتير الشراء",
+ "reconcile_credit_note.dialog.total_amount_to_credit": "المبلغ الإجمالي",
+ "reconcile_credit_note.dialog.credits_balance": "رصيد الإشعار:",
+ "reconcile_credit_note.dialog.remaining_credits": "قيمة المتبقية من الإشعار",
+ "reconcile_credit_note.column.remaining_amount": "المبلغ المتبقي",
+ "reconcile_credit_note.column.amount_to_credit": " قيمة التسوية",
+ "reconcile_credit_note.success_message": "تم تطبيق معاملة تسوية إشعار الدائن على الفواتير المقدمة بنجاح. ",
+ "reconcile_credit_note.alert.there_is_no_open_sale_invoices": "لا توجد فواتير بيع مفتوحة مع نفس الزبون إشعار الدائن.",
+ "reconcile_credit_note.alert.success_message": "تم حذف معاملة تسوية إشعار الدائن بنجاح.",
+ "reconcile_credit_note.once_you_delete_this_reconcile_credit_note": "بمجرد حذف معاملة تسوية إشعار الدائن ، لن تتمكن من استعادتها لاحقًا. هل أنت متأكد أنك تريد حذف هذه المعاملة؟",
+ "reconcile_vendor_credit.dialog.label": " تسوية إشعار المدين بالفواتير البيع",
+ "reconcile_vendor_credit.dialog.success_message": "تم تطبيق معاملة تسوية إشعار المدين على الفواتير المقدمة بنجاح",
+ "reconcile_vendor_credit.alert.there_is_no_open_bills": "لا توجد فواتير شراء مفتوحة مع نفس المورد إشعار المدين.",
+ "reconcile_vendor_credit.dialog.total_amount_to_credit": "المبلغ الإجمالي",
+ "reconcile_vendor_note.dialog.credits_balance": "رصيد الإشعار:",
+ "reconcile_vendor_credit.dialog.remaining_credits": "قيمة المتبقية من الإشعار",
+ "reconcile_vendor_credit.column.bill_number": "رقم الفاتورة",
+ "reconcile_vendor_credit.column.remaining_amount": "المبلغ المتبقي",
+ "reconcile_vendor_credit.column.amount_to_credit": " قيمة التسوية",
+ "reconcile_vendor_credit.alert.success_message": "تم حذف معاملة تسوية إشعار المدين بنجاح.",
+ "reconcile_vendor_credit.alert.once_you_delete_this_reconcile_vendor_credit": "بمجرد حذف معاملة تسوية إشعار الدائن ، لن تتمكن من استعادتها لاحقًا. هل أنت متأكد أنك تريد حذف هذه المعاملة؟",
+ "credit_note.error.you_couldn_t_delete_credit_note_that_has_associated_refund": "لا يمكن حذف إشعار الدائن لديها معاملات استرجاع الأموال مرتبطة بيها",
+ "credit_note.error.you_couldn_t_delete_credit_note_that_has_associated_invoice": "لا يمكن حذف إشعار الدائن لديها معاملات تسوية الفواتير مرتبطة بيها.",
+ "invoices.error.you_couldn_t_delete_sale_invoice_that_has_reconciled": "لا يمكنك حذف فاتورة بيع تمت تسويتها مع معاملة إشعار الدائن.",
+ "vendor_credit.error.you_couldn_t_delete_vendor_credit_has_reconciled": "لا يمكن حذف إشعار المدين لديها معاملات تسوية الفواتير مرتبطة بيها.",
+ "vendor_credit.error.you_couldn_t_delete_vendor_credit_that_has_associated_refund": "لا يمكن حذف إشعار المدين لديها معاملات استرجاع الأموال مرتبطة بيها.",
+ "bills.error.you_couldn_t_delete_bill_has_reconciled_with_vendor_credit": "لا يمكنك حذف فاتورة شراء تمت تسويتها مع معاملة إشعار المدين.",
+ "vendor_credit_opened.alert.success_message": "تم فتح المدين بنجاح.",
+ "vendor_credit_opened.are_sure_to_open_this_credit": "هل أنت متأكد أنك تريد فتح هذا إشعار؟",
+ "sidebar.transactions_locaking": "قفل المعاملات",
+ "locking_transactions.dialog.label": "قفل المعاملات ",
+ "locking_transactions.dialog.locking_date": "تاريخ القفل ",
+ "locking_transactions.dialog.reason": "سبب القفل ",
+ "locking_transactions.dialog.success_message": "تم إرسال قفل جميع المعاملات بنجاح.",
+ "unlocking_transactions.dialog.label": "إلغاء قفل المعاملات",
+ "unlocking_transactions.dialog.reason": "سبب إلغاء القفل",
+ "unlocking_transactions.dialog.success_message": "تم إلغاء قفل المعاملات بنجاح.",
+ "unlocking_partial_transactions.dialog.label": "إلغاء قفل المعاملات الجزئية ",
+ "unlocking_partial_transactions.dialog.from_date": "إلغاء قفل من التاريخ",
+ "unlocking_partial_transactions.dialog.to_date": "حتى تاريخ",
+ "unlocking_partial_transactions.dialog.reason": "سبب إلغاء القفل",
+ "unlocking_partial_transactions.dialog.success_message": "تم إلغاء قفل المعاملات بشكل جزئي بنجاح. ",
+ "unlocking_full_transactions.dialog.label": "إلغاء قفل المعاملات بالكامل ",
+ "unlocking_full_transactions.dialog.reason": "سبب إلغاء القفل",
+ "unlocking_partial_transactions.alert.cancel_message": "تم إلغاء فتح المعاملات الجزئي بنجاح.",
+ "unlocking_partial_transactions.alert.message": "هل أنت متأكد تريد إلغاء قفل الجزئي لهذه الوحدة؟ ",
+ "yes": "نعم",
+ "transactions_locking.lock_all_transactions_at_once": "قفل جميع المعاملات دفعة واحدة ←",
+ "transactions_locking.lock_modules_individually": "قفل الوحدات بشكل فردي ←",
+ "transactions_locking_lock_all_transactions_at_once": "قفل جميع المعاملات دفعة واحدة.",
+ "transactions_locking.lock": "قفل",
+ "transactions_locking.unlock": "الغاء القفل",
+ "transactions_locking.full_unlock": "إلغاء القفل الكامل",
+ "transactions_locking.paetial_unlock": "إلغاء القفل الجزئي",
+ "transactions_locking.cancel_partial_unlock": "Cancel Partial Unlock",
+ "transactions_locking.of_the_module_locked_to": "تم قفل معاملات الوحدة حتى {value}.",
+ "transactions_locking.lock_reason": "سبب القفل : {value}.",
+ "transactions_locking.partial_unlocked_from": "غير مقفلة جزئيًا من {fromDate} إلى {toDate}.",
+ "transactions_locking.unlock_reason": " سبب إلغاءالقفل: {value}.",
+ "transactions_locking.callout.lock_individual.desc": "يمكنك قفل أو إلغاء قفل المعاملات لكل وحدة على حدا بدلاً من قفل المعاملات لجميع المعاملات مرة واحدة.",
+ "transactions_locking.callout.lock_all_at_once.desc": "يمكن قفل او إلغاء قفل المعاملات لكل الوحدات مرة واحدة بدلاً من قفلها لكل وحدة بشكل جزئي.",
+ "transactions_locking.long_description": "يمكنك قفل المعاملات المالية حتى لا يتمكن المستخدمون من تعديل أو حذف أو إضافة معاملات جديدة خلال الفترة الماضية ، ولكن لا يزال لدي المستخدمين إمكانية إضافة عمليات مالية فواتير الشراء أو البيع كمسودة لن يؤثر إضافتها على نتائج التقارير المالية. عادةً ما يحدد تاريخ القفل بعد ما يتم من تدقيق من المعاملات في نهاية الشهر أو السنة.",
+ "transactions_locking.you_should_unlock_all_transactions_at_once_before": ".يجب عليك إلغاء قفل جميع المعاملات مرة واحدة ، بدلاً من قفل المعاملات كل وحدة جزئيًا",
+ "transactions_locking.lock_individual_modules": "قفل الوحدات بشكل منفرد ",
+ "invoice_transactions.column.withdrawal_account": "حساب السحب",
+ "invoice_transactions.action.delete_transaction": "حذف المعاملة ",
+ "invoice_transactions.action.edit_transaction": " تعديل المعاملة",
+ "bill_transactions.column.deposit_account": "حساب إيداع",
+ "transactions_locking.lock_item.no_lock": "لا توجد معاملات مقفلة في هذه الوحدة.",
+ "overview": "نظرة عامة",
+ "transactions": "معاملات ",
+ "item.drawer_transactions_by": " عرض معاملات:",
+ "item.drawer_quantity_sold": "الكمية المباعة",
+ "journal_entries.amount_displayed_base_currency": "يتم عرض المبلغ بالعملة الأساسية الخاصة بك ",
+ "inventory_adjustment.column.product": "المنتج",
+ "invoice.convert_to_credit_note": "تحويل إلى إشعار دائن",
+ "bill.convert_to_credit_note": "تحويل إلى إشعار مدين",
+ "bill.allocate_landed_coast": "تحميل تكلفة اضافية",
+ "overdue": "متأخرّة",
+ "invite_user.label.role_name": "دور المستخدم",
+ "permissions.column.view": "عرض",
+ "permissions.column.full_access": "تحكم كامل",
+ "permissions.column.delete": "حذف",
+ "permissions.column.edit": "تعديل",
+ "permissions.column.create": "اضافة",
+ "permissions.column.written_off_invoice": "شطب فاتورة",
+ "permissions.column.refund_credit_note": "استرجاع الأموال",
+ "permissions.column.refund_vendor_credit": "استرجاع الأموال",
+ "permissions.column.transactions_locking": "قفل المعاملات",
+ "permissions.items_inventory": "منتجات والمخزون",
+ "permissions.inventory_adjustment": "تسويات المخزون",
+ "permissions.items": "المنتجات",
+ "permissions.contacts": "جهات الاتصال",
+ "permissions.customers": "العملاء",
+ "permissions.vendors": "الموردين",
+ "permissions.sales": "المبيعات",
+ "permissions.sale_invoice": "الفواتير ",
+ "permissions.sale_estimate": "العروض",
+ "permissions.sale_receipt": "الإيصالات",
+ "permissions.credit_note": "إشعارات الدائن",
+ "permissions.payment_receive": "سندات الزبائن",
+ "permissions.purchases": "المشتريات",
+ "permissions.bills": "فواتير الشراء",
+ "permissions.vendor_credits": "إشعارات المدين",
+ "permissions.payment_made": "سندات الموردين",
+ "permissions.financial_accounting": "الأمور المالية",
+ "permissions.manual_journals": "القيود اليدوية",
+ "permissions.chart_of_accounts": "شجرة الحسابات",
+ "permissions.expenses": "المصاريف",
+ "permissions.reports": "التقارير",
+ "permissions.financial_reports": "تقارير مالية",
+ "permissions.balance_sheet": "الميزانية العمومية",
+ "permissions.profit_loss_sheet": "قائمة الدخل",
+ "permissions.trial_balance_sheet": "ميزان المراجعة",
+ "permissions.cash_flow_sheet": "قائمة التدفقات النقدية",
+ "permissions.journal_sheet": "دفتر اليومية العامة",
+ "permissions.general_ledger": "دفتر الأستاذ العام",
+ "permissions.a_r_aging_summary_report": "ملخص اعمار الديون للذمم المدينة",
+ "permissions.a_p_aging_summary_report": "ملخص اعمار الديون للذمم الدائنة",
+ "permissions.purchases_by_items": "المشتريات حسب المنتجات",
+ "permissions.sales_by_items": "المبيعات حسب المنتجات",
+ "permissions.customers_transactions": "معاملات الزبائن",
+ "permissions.vendors_transactions": "معاملات الموردين",
+ "permissions.customers_summary_balance": "ملخص رصيد الزبائن",
+ "permissions.vendors_summary_balance": "ملخص رصيد الموردين",
+ "permissions.inventory_valuation_summary": "ملخص تقييم المخزون ",
+ "permissions.inventory_items_details": "تفاصيل منتج المخزون",
+ "permissions.cashflow_account_transactions": "معاملات حسابات التدفقات النقدية",
+ "permissions.more_permissions": "عرض المزيد ",
+ "estimate.status.expired": "منتهية الصلاحية",
+ "refund_credit.drawer.title": " تفاصيل استرجاع الأموال لإشعار الدائن ",
+ "refund_credit.drawer.label.amount": "القيمة",
+ "refund_credit.drawer.label.credit_note_no": "رقم الإشعار",
+ "refund_credit.drawer.label.withdrawal_account": "حساب السحب",
+ "refund_credit.drawer.label.reference_no": "رقم المرجع",
+ "refund_credit.drawer.label.description": "الوصف",
+ "refund_vendor_credit.drawer.title": " تفاصيل استرجاع الأموال لإشعار المدين ",
+ "refund_vendor_credit.drawer.label.amount": "القيمة",
+ "refund_vendor_credit.drawer.label.vendor_credit_no": "رقم الإشعار",
+ "refund_vendor_credit.drawer.label.deposit_account": "حساب إيداع",
+ "refund_vendor_credit.drawer.label.reference_no": "رقم المرجع",
+ "refund_vendor_credit.drawer.label.description": "الوصف",
+ "estimate.drawer.title": "تفاصيل العرض ({number})",
+ "receipt.drawer.title": "تفاصيل الإيصال ({number})",
+ "credit_note.drawer.title": "تفاصيل إشعار الدائن ({number})",
+ "payment_receive.drawer.title": "تفاصيل سند الزبون ({number})",
+ "payment_made.drawer.title": "تفاصيل سند المورد {number}",
+ "manual_journal.drawer.title": "تفاصيل قيد يدوي ({number})",
+ "expense.drawer.title": " تفاصيل المصروف"
}
\ No newline at end of file
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 8613f21bf..14a6cca5b 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -519,6 +519,7 @@
"delete_invoice": "Delete Invoice",
"new_invoice": "New Invoice",
"invoice_list": "Invoice List",
+ "invoice_reference_no": "Reference #",
"the_invoice_has_been_edited_successfully": "The invoice #{number} has been edited successfully.",
"the_invoice_has_been_created_successfully": "The invoice #{number} has been created successfully.",
"the_invoice_has_been_deleted_successfully": "The invoice has been deleted successfully.",
@@ -708,13 +709,13 @@
"day_partially_paid": "Partially paid, {due} due.",
"overdue_by": "Overdue by {overdue} day.",
"paid": "Paid",
+ "due": "Due",
"your_account_has_been_locked": "Your account has been locked due to repeated failed login attempts. Please wait a few minutes before trying again.",
"the_invoice_has_been_delivered_successfully": "The invoice has been delivered successfully.",
"are_sure_to_deliver_this_invoice": "Are you sure you want to deliver this invoice?",
"mark_as_delivered": "Mark as delivered",
"deliver": "Deliver",
"mark_as_closed": "Mark as closed",
- "mark_as_opened": "Mark as opened",
"save_close": "Save & Close",
"save_open": "Save & Open",
"close_and_new": "Close and new",
@@ -758,6 +759,7 @@
"inventory_adjustments": "Inventory adjustments",
"make_adjustment": "Make an adjustment",
"adjustment_type": "Adjustment type",
+ "mark_as_open": "Make as Open",
"decrement": "Decrement",
"new_quantity": "New quantity",
"reason": "Reason",
@@ -910,7 +912,7 @@
"drag_drop_files_here_or_click_here": "Drag/Drop files here or click here.",
"enter_an_item": "Enter an item...",
"due_amount": "Due Amount",
- "invoice_details": "Invoice details",
+ "invoice_details.drawer.title": "Invoice details ({invoiceNumber})",
"setting_your_auto_generated_estimate_number": "Setting your auto-generated estimate number",
"setting_your_auto_generated_journal_number": "Setting your auto-generated journal number",
"setting_your_auto_generated_invoice_number": "Setting your auto-generated invoice number",
@@ -1114,7 +1116,6 @@
"Initializing": "Initializing",
"Getting started": "Getting started",
"Congratulations": "Congratulations",
- "manual_journal_number": "Manual journal {number}",
"conditions_and_terms": "Conditions and terms",
"allocate_landed_coast": "Allocate landed cost",
"transaction_date": "Transaction date",
@@ -1142,10 +1143,10 @@
"Select transaction": "Select transaction",
"Select transaction entry": "Select transaction entry",
"From transaction": "From transaction",
- "Landed": "Landed",
+ "landed": "Landed",
"This options allows you to be able to add additional cost eg. freight then allocate cost to the items in your bills.": "This options allows you to be able to add additional cost eg. freight then allocate cost to the items in your bills.",
"Once your delete this located landed cost, you won't be able to restore it later, Are your sure you want to delete this transaction?": "Once your delete this located landed cost, you won't be able to restore it later, Are your sure you want to delete this transaction?",
- "journal_entries": "Journal entries",
+ "journal_entries": "Journal Entries",
"contact": "Contact",
"invoice_details": "Invoice details",
"receipt_details": "Receipt details",
@@ -1195,6 +1196,7 @@
"payment_receive.details.payment_number": "Payment #",
"payment_receive.details.total": "TOTAL",
"payment_receive.details.subtotal": "Subtotal",
+ "payment_receive.details.statement": "Statement",
"estimate.details.estimate_number": "Estimate #",
"estimate.details.subtotal": "Subtotal",
"estimate.details.total": "TOTAL",
@@ -1202,23 +1204,31 @@
"estimate.details.due_amount": "Due amount",
"estimate.details.note": "Note",
"estimate.details.created_at": "Created at",
+ "estimate.details.terms_conditions": "Terms & Conditions",
"receipt.details.receipt_number": "Receipt #",
"receipt.details.subtotal": "Subtotal",
"receipt.details.total": "TOTAL",
"receipt.details.payment_amount": "Payment amount",
"receipt.details.due_amount": "Due amount",
"receipt.details.created_at": "Created at",
+ "receipt.details.receipt_message": "Receipt Message",
+ "receipt.details.statement": "Statement",
"invoice.details.created_at": "Created at",
"invoice.details.total": "TOTAL",
"invoice.details.subtotal": "Subtotal",
"invoice.details.due_amount": "Due amount",
"invoice.details.payment_amount": "Payment amount",
+ "invoice.details.invoice_message": "Invoice Message",
+ "invoice.details.invoice_no": "Invoice #",
+ "bill.drawer.title": "Bill details {number}",
+ "bill.details.reference": "Reference #",
"bill.details.bill_number": "Bill #",
"bill.details.created_at": "Created at",
"bill.details.total": "TOTAL",
"bill.details.subtotal": "Subtotal",
"bill.details.payment_amount": "Payment amount",
"bill.details.due_amount": "Due amount",
+ "bill.drawer.bill_details": "Bill details ({billNumber})",
"expense.details.subtotal": "Subtotal",
"expense.details.total": "Total",
"manual_journal.details.subtotal": "Subtotal",
@@ -1469,23 +1479,259 @@
"sms_notification.payment_details.type": "Payment receive thank you.",
"sms_notification.receipt_details.type": "Sale receipt details",
"personal": "Personal",
- "list.create":"Create {value}",
- "roles.label":"Roles",
- "roles.column.name":"Name",
- "roles.column.description":"Description",
- "roles.edit_roles":"Edit Roles",
- "roles.delete_roles":"Delete Roles",
- "roles.label.role_name":"Role Name",
- "roles.label.role_name_":"Role name",
- "roles.error.role_is_predefined":"Role is predefined, you cannot delete predefined roles.",
- "roles.error.you_cannot_change_your_own_role":"You cannot change your own role.",
- "sidebar.transactions_locaking":"Transactions Locaking",
- "transactions_locking.dialog.label":"Transactions locking",
- "roles.permission_schema.success_message":"The role has been created successfully.",
- "roles.permission_schema.upload_message":"The given role has been updated successfully.",
- "roles.permission_schema.delete.alert_message":"The given role has been deleted successfully.",
- "roles.permission_schema.once_delete_this_role_you_will_able_to_restore_it":"Once you delete this role, you won't be able to restore it later. Are you sure you want to delete this role?",
- "users.column.role_name":"Role Name",
- "roles.error.you_cannot_edit_predefined_roles":"You cannot edit predefined roles.",
- "roles.error.you_cannot_delete_predefined_roles":"You cannot delete predefined roles."
+ "list.create": "Create {value}",
+ "roles.label": "Roles",
+ "roles.column.name": "Name",
+ "roles.column.description": "Description",
+ "roles.edit_roles": "Edit Roles",
+ "roles.delete_roles": "Delete Roles",
+ "roles.label.role_name": "Role Name",
+ "roles.label.role_name_": "Role name",
+ "roles.error.role_is_predefined": "Role is predefined, you cannot delete predefined roles.",
+ "roles.error.you_cannot_change_your_own_role": "You cannot change your own role.",
+ "roles.permission_schema.success_message": "The role has been created successfully.",
+ "roles.permission_schema.upload_message": "The given role has been updated successfully.",
+ "roles.permission_schema.delete.alert_message": "The given role has been deleted successfully.",
+ "roles.permission_schema.once_delete_this_role_you_will_able_to_restore_it": "Once you delete this role, you won't be able to restore it later. Are you sure you want to delete this role?",
+ "users.column.role_name": "Role Name",
+ "roles.error.you_cannot_edit_predefined_roles": "You cannot edit predefined roles.",
+ "roles.error.you_cannot_delete_predefined_roles": "You cannot delete predefined roles.",
+ "roles.error.the_submit_role_has_invalid_permissions": "The submit role has invalid permissions.",
+ "roles.error.you_cannot_delete_role_that_associated_to_users": "You cannot delete role that associated to users",
+ "sidebar_credit_note": "Credit Notes",
+ "credit_note.label_create_note_list": "Credit Notes List",
+ "credit_note.label.new_credit_note": "New Credit Note",
+ "credit_note.label.edit_credit_note": "Edit Credit Note",
+ "credit_note.action.edit_credit_note": "Edit Credit Note",
+ "credit_note.action.refund_credit_note": "Refund Credit note",
+ "credit_note.action.reconcile_with_invoices": "Reconcile with Invoices",
+ "credit_note.action.make_as_open": "Mark as Open",
+ "credit_note.action.delete_credit_note": "Delete Credit Note",
+ "credit_note.column.credit_note_no": "Credit Note #",
+ "credit_note.column.credit_date": "Credit Date",
+ "credit_note.empty_status.title": "Reduce customers balance by create credit note",
+ "credit_note.empty_status.description": "A credit note is a commercial document given to the customer when the goods are returned, with the possibility of adding a refund or applied to unpaid sales invoices.",
+ "credit_note.label_credit_note_date": "Credit Note date",
+ "credit_note.label_credit_note": "Credit Note #",
+ "credit_note.label_amount_to_credit": "Amount to credit",
+ "credit_note.label_credit_note_details": "Credit Note details",
+ "credit_note.label_customer_note": "Customer note",
+ "credit_note.once_delete_this_credit_note": "Once you delete this credit note, you won't be able to restore it later. Are you sure you want to delete this credit note?",
+ "credit_note.alert.delete_message": "The credit note has been deleted successfully",
+ "credit_note.success_message": "The credit note has been created successfully.",
+ "credit_note.edit_success_message": "The credit note has been edited successfully.",
+ "credit_note.label": "Credit notes",
+ "credit_note_number_settings": "Credit Note Number Settings",
+ "credit_note.auto_increment.auto": "Your credit note numbers are set on auto-increment mode. Are you sure changing this setting?",
+ "credit_note.auto_increment.manually": "Your credit note numbers are set on manual mode. Are you sure chaning this settings?",
+ "setting_your_auto_generated_credit_note_number": "Setting your auto-generated credit note number",
+ "credit_note.drawer.label_credit_note_no": "Credit Note #",
+ "credit_note.drawer.label_credit_note_date": "Credit Date",
+ "credit_note.drawer.label_credits_remaining": "Credits Remaining",
+ "credit_note.drawer.label_created_at": "Created at",
+ "credit_note.drawer.label_total": "TOTAL",
+ "credit_note.drawer.label_subtotal": "Subtotal",
+ "credit_note.drawer.label_refund_transactions": "Refund Transactions",
+ "credit_note.drawer.label_invoices_reconciled": "Invoices Reconciled",
+ "sidebar_vendor_credits": "Vendor Credits",
+ "vendor_credits.lable_vendor_credit_list": "Vendor Credits List",
+ "vendor_credits.label.new_vendor_credit": "New Vendor Credit",
+ "vendor_credits.label.edit_vendor_credit": "Edit Vendor Credit",
+ "vendor_credits.label.amount_to_credit": "Amount to credit",
+ "vendor_credits.column.vendor_credit_no": "Vendor Credit #",
+ "vendor_credits.action.new_vendor_credit": "New Vendor Credit",
+ "vendor_credits.action.edit_vendor_credit": "Edit Vendor Credit",
+ "vendor_credits.action.refund_vendor_credit": "Refund Vendor Credit",
+ "vendor_credits.action.delete_vendor_credit": "Delete Vendor Credit",
+ "vendor_credits.empty_status.title": "Reduce vendors balance by create vendor credit",
+ "vendor_credits.empty_status.description": "Vendor credit is the commercial document that is sent to the vendor and makes him owe to our organization. It is proof by the facility that it has a right to be taken from the vendor.",
+ "vendor_credits.action.mark_as_open": "Make as Open",
+ "vendor_credits.action.reconcile_with_bills": "Reconcile with Bills",
+ "vendor_credits.success_message": "The vendor credit has been created successfully",
+ "vendor_credits.edit_success_message": "The vendor credit has been edited successfully.",
+ "vendor_credits.alert.delete_message": "The given vendor credit has been deleted successfully.",
+ "vendor_credits.note.once_delete_this_vendor_credit_note": "Once you delete this vendor credit , you won't be able to restore it later. Are you sure you want to delete this vendor credit ?",
+ "vendor_credit_number_settings": "Vendor Credit Number Settings",
+ "vendor_credit.auto_increment.auto": "Your vendor credit numbers are set on auto-increment mode. Are you sure changing this setting?",
+ "vendor_credit.auto_increment.manually": "Your vendor credit numbers are set on manual mode. Are you sure chaning this settings?",
+ "setting_your_auto_generated_vendor_credit_number": "Setting your auto-generated vendor credit number",
+ "vendor_credit.label": "Vendor credits",
+ "vendor_credit.drawer_vendor_credit_detail": "Vendor Credit details",
+ "vendor_credit.drawer.label_vendor_credit_no": "Vendor Credit #",
+ "vendor_credit.drawer.label_vendor_credit_date": "Vendor Credit Date",
+ "vendor_credit.drawer.label_credits_remaining": "Credits Remaining",
+ "vendor_credit.drawer.label_created_at": "Created at",
+ "vendor_credit.drawer.label_total": "TOTAL",
+ "vendor_credit.drawer.label_subtotal": "Subtotal",
+ "vendor_credit.drawer.label_refund_transactions": "Refund Transactions",
+ "vendor_credit.drawer.label_bills_reconciled": "Bills Reconciled",
+ "refund": "Refund",
+ "landed_cost.dialog.label_select_transaction": "Select transaction",
+ "landed_cost.dialog.label_select_transaction_entry": "Select transaction entry",
+ "refund_credit_note.dialog.label": "Refund Credit Note",
+ "refund_credit_note.dialog.success_message": "The customer credit note refund has been created successfully.",
+ "refund_credit_note.dialog.refund_date": "Refund date",
+ "refund_credit_note.dialog.amount": "Amount",
+ "refund_credit_note.dialog.description": "Description",
+ "refund_credit_note.dialog.from_account": "From account",
+ "refund_vendor_credit.dialog.label": "Refund Vendor Credit",
+ "refund_vendor_credit.dialog.success_message": "The vendor credit refund has been created successfully.",
+ "refund_vendor_credit.dialog.refund_date": "Refund date",
+ "refund_vendor_credit.dialog.amount": "Amount",
+ "refund_vendor_credit.dialog.description": "Description",
+ "refund_vendor_credit.dialog.deposit_to_account": "Deposit to account",
+ "refund_credit_transactions.column.amount_refunded": "Amount refunded",
+ "refund_credit_transactions.column.withdrawal_account": "Withdrawal account",
+ "refund_credit_transactions.alert.delete_message": "The credit note refund has been deleted successfully.",
+ "refund_credit_transactions.once_your_delete_this_refund_credit_note": "Once your delete this refund credit note, you won't be able to restore it later, Are your sure you want to delete this transaction?",
+ "refund_vendor_credit.column.amount": "Amount refunded",
+ "refund_vendor_credit.column.withdrawal_account": "Withdrawal account",
+ "refund_vendor_credit_transactions.alert.delete_message": "The vendor credit refund has been deleted successfully.",
+ "refund_vendor_credit_transactions.once_your_delete_this_refund_vendor_credit": "Once your delete this refund vendor credit note, you won't be able to restore it later, Are your sure you want to delete this transaction?",
+ "credit_note_opened.alert.success_message": "The credit note has been opened successfully",
+ "credit_note_opened.are_sure_to_open_this_credit": "Are you sure you want to open this credit note?",
+ "vendor_credit_opened.alert.success_message": "The vendor credit has been opened successfully",
+ "vendor_credit_opened.are_sure_to_open_this_credit": "Are you sure you want to open this vendor credit?",
+ "reconcile_credit_note.label": "Reconcile credit note with invoices",
+ "reconcile_credit_note.dialog.total_amount_to_credit": "Total amount to credit",
+ "reconcile_credit_note.dialog.credits_balance": "Credits balance:",
+ "reconcile_credit_note.dialog.remaining_credits": "Remaining credits",
+ "reconcile_credit_note.column.remaining_amount": "Remaining amount",
+ "reconcile_credit_note.column.amount_to_credit": "Amount to credit",
+ "reconcile_credit_note.success_message": "The credit note has been applied the given invoices successfully.",
+ "reconcile_credit_note.alert.there_is_no_open_sale_invoices": "There is no open sale invoices associated to credit note customer.",
+ "reconcile_credit_note.alert.success_message": "The applied credit to invoices has been deleted successfully.",
+ "reconcile_credit_note.once_you_delete_this_reconcile_credit_note": "Once you delete this reconcile credit note, you won't be able to restore it later. Are you sure you want to delete this reconcile credit note?",
+ "credit_note.error.you_couldn_t_delete_credit_note_that_has_associated_refund": "You couldn't delete credit note that has associated refund transactions.",
+ "credit_note.error.you_couldn_t_delete_credit_note_that_has_associated_invoice": "You couldn't delete credit note that has associated invoice reconcile transactions.",
+ "invoices.error.you_couldn_t_delete_sale_invoice_that_has_reconciled": "You couldn't delete sale invoice that has reconciled with credit note transaction.",
+ "reconcile_vendor_credit.dialog.label": "Reconcile Credit Note with Bills",
+ "reconcile_vendor_credit.dialog.success_message": "The vendor credit has been applied to the given bills successfully",
+ "reconcile_vendor_credit.alert.there_is_no_open_bills": "There is no open bills associated to credit note vendor.",
+ "reconcile_vendor_credit.dialog.total_amount_to_credit": "Total amount to credit",
+ "reconcile_vendor_note.dialog.credits_balance": "Credits balance:",
+ "reconcile_vendor_credit.dialog.remaining_credits": "Remaining amount",
+ "reconcile_vendor_credit.column.bill_number": "Bill #",
+ "reconcile_vendor_credit.column.remaining_amount": "Remaining amount",
+ "reconcile_vendor_credit.column.amount_to_credit": "Amount to credit",
+ "vendor_credit.error.you_couldn_t_delete_vendor_credit_has_reconciled": "You couldn't delete vendor credit has reconciled with bills transactions.",
+ "vendor_credit.error.you_couldn_t_delete_vendor_credit_that_has_associated_refund": "You couldn't delete vendor credit that has associated refund transactions.",
+ "bills.error.you_couldn_t_delete_bill_has_reconciled_with_vendor_credit": "You couldn't delete bill has reconciled with vendor credit transaction.",
+ "reconcile_vendor_credit.alert.success_message": "The applied vendor credit to bill has been deleted successfully",
+ "reconcile_vendor_credit.alert.once_you_delete_this_reconcile_vendor_credit": "Once you delete this reconcile vendor credit note, you won't be able to restore it later. Are you sure you want to delete this reconcile vendor credit note?",
+ "sidebar.transactions_locaking": "Transactions Locking",
+ "locking_transactions.dialog.label": "Locking transactions",
+ "locking_transactions.dialog.locking_date": "Locking date",
+ "locking_transactions.dialog.reason": "Locking reason",
+ "locking_transactions.dialog.success_message": "All transactions locking has been submit successfully.",
+ "unlocking_transactions.dialog.label": "Transactions unlocking",
+ "unlocking_transactions.dialog.reason": "Unlocking reason",
+ "unlocking_transactions.dialog.success_message": "Transactions locking has been canceled successfully.",
+ "unlocking_partial_transactions.dialog.label": "Partial unlocking transactions",
+ "unlocking_partial_transactions.dialog.from_date": "Unlocking from date",
+ "unlocking_partial_transactions.dialog.to_date": "To date",
+ "unlocking_partial_transactions.dialog.reason": "Unlocking reason",
+ "unlocking_partial_transactions.dialog.success_message": "Transactions locking haas been unlocked partially successfully.",
+ "unlocking_full_transactions.dialog.label": "Full unlocking transactions",
+ "unlocking_full_transactions.dialog.reason": "Unlocking reason",
+ "unlocking_partial_transactions.alert.cancel_message": "Partial transaction unlocking has been canceled successfully.",
+ "unlocking_partial_transactions.alert.message": "Are you sure you want to cancel partial unlock of this module?",
+ "yes": "Yes",
+ "transactions_locking.lock_all_transactions_at_once": "Lock All Transactions At Once →",
+ "transactions_locking.lock_modules_individually": "Lock Modules Individually →",
+ "transactions_locking_lock_all_transactions_at_once": "Lock All Transactions At Once.",
+ "transactions_locking.lock": "Lock",
+ "transactions_locking.unlock": "Unlock",
+ "transactions_locking.full_unlock": "Full Unlock",
+ "transactions_locking.paetial_unlock": "Partial Unlock",
+ "transactions_locking.cancel_partial_unlock": "Cancel Partial Unlock",
+ "transactions_locking.of_the_module_locked_to": "Transactions of the module locked to {value}.",
+ "transactions_locking.lock_reason": "Lock Reason: {value}.",
+ "transactions_locking.partial_unlocked_from": "Partial unlocked from {fromDate} to {toDate}.",
+ "transactions_locking.unlock_reason": "Unlock Reason: {value}.",
+ "transactions_locking.callout.lock_individual.desc": "You have the ability to lock transactions of all modules at once instead of locking transactions each module partially.",
+ "transactions_locking.callout.lock_all_at_once.desc": "You have the ability to lock or unlock transactions of each module individually instead of locking all transactions at once.",
+ "transactions_locking.long_description": "Transactions locking has the ability to lock all organization transactions so users can’t edit, delete or create new transactions during the past period, but still have the ability to create draft invoices or bills and that won’t affect financial reports. typically set a lock date when your financial records are being prepared for the year.",
+ "transactions_locking.you_should_unlock_all_transactions_at_once_before": "You should unlock all transactions at once before, than lock transactions partially on each module.",
+ "transactions_locking.lock_individual_modules": "Lock Individual Modules",
+ "payment_transactions": "Payment transactions",
+ "invoice_transactions.column.withdrawal_account": "Deposit account",
+ "invoice_transactions.action.delete_transaction": "Delete Transaction",
+ "invoice_transactions.action.edit_transaction": "Edit Transaction",
+ "bill_transactions.column.deposit_account": "Withdrawal account",
+ "transactions_locking.lock_item.no_lock": "There are no locked transactions in this module.",
+ "overview": "Overview",
+ "transactions": "Transactions",
+ "item.drawer_transactions_by": "Transactions by:",
+ "item.drawer_quantity_sold": "Quantity Sold",
+ "role_name": "Role name",
+ "journal_entries.amount_displayed_base_currency": "Amount is displayed in your base currency",
+ "inventory_adjustment.column.product": "Product",
+ "invoice.convert_to_credit_note": "Convert to Credit Note",
+ "bill.convert_to_credit_note": "Convert to Vendor Credit",
+ "bill.allocate_landed_coast": "Allocate Landed Cost",
+ "overdue": "Overdue",
+ "permissions.column.view": "View",
+ "permissions.column.full_access": "Full Access",
+ "permissions.column.delete": "Delete",
+ "permissions.column.edit": "Edit",
+ "permissions.column.create": "Create",
+ "permissions.column.written_off_invoice": "Written-off invoice",
+ "permissions.column.refund_credit_note": "Refund credit note",
+ "permissions.column.refund_vendor_credit": "Refund vendor credit",
+ "permissions.column.transactions_locking": "Transactions locking",
+ "permissions.items_inventory": "Items & Inventory",
+ "permissions.inventory_adjustment": "Inventory Adjustment",
+ "permissions.items": "Items",
+ "permissions.caontacts": "Contacts",
+ "permissions.customers": "Customers",
+ "permissions.vendors": "Vendors",
+ "permissions.sales": "Sales",
+ "permissions.sale_invoice": "Sale Invoice",
+ "permissions.sale_estimate": "Sale Estimate",
+ "permissions.sale_receipt": "Sale Receipt",
+ "permissions.credit_note": "Credit note",
+ "permissions.payment_receive": "Payment Receive",
+ "permissions.purchases": "Purchases",
+ "permissions.bills": "Bills",
+ "permissions.vendor_credit": "Vendor Credits",
+ "permissions.payment_made": "Payment Made",
+ "permissions.financial_accounting": "Financial Accounting",
+ "permissions.manual_journals": "Manual Journals",
+ "permissions.chart_of_accounts": "Chart of Accounts",
+ "permissions.expenses": "Expenses",
+ "permissions.reports": "Financial Reports",
+ "permissions.financial_reports": "Financial reprots",
+ "permissions.balance_sheet": "Balance sheet",
+ "permissions.profit_loss_sheet": "Profit & Loss sheet",
+ "permissions.trial_balance_sheet": "Trial Balance sheet",
+ "permissions.cash_flow_sheet": "Cash flow sheet",
+ "permissions.journal_sheet": "Journal sheet",
+ "permissions.general_ledger": "General ledger",
+ "permissions.a_r_aging_summary_report": "A/R Aging Summary report",
+ "permissions.a_p_aging_summary_report": "A/P Aging Summary report",
+ "permissions.purchases_by_items": "Purchases by items",
+ "permissions.sales_by_items": "Sales by items",
+ "permissions.customers_transactions": "Customers transactions",
+ "permissions.vendors_transactions": "Vendors transactions",
+ "permissions.customers_summary_balance": "Customers summary balance",
+ "permissions.vendors_summary_balance": "Vendors summary balance",
+ "permissions.inventory_valuation_summary": "Inventory valuation summary",
+ "permissions.inventory_items_details": "Inventory valuation summary",
+ "permissions.cashflow_account_transactions": "Cashflow account transactions",
+ "permissions.more_permissions": "More Permissions",
+ "estimate.status.expired": "Expired",
+ "refund_credit.drawer.title": "Refund credit note",
+ "refund_credit.drawer.label.amount": "Amount",
+ "refund_credit.drawer.label.credit_note_no": "Credit note number",
+ "refund_credit.drawer.label.withdrawal_account": "Withdrawal account",
+ "refund_credit.drawer.label.reference_no": "Reference number",
+ "refund_credit.drawer.label.description": "Description",
+ "estimate.drawer.title": "Estimate details ({number})",
+ "receipt.drawer.title": "Receipt details ({number})",
+ "credit_note.drawer.title": "Credit Note details ({number})",
+ "payment_receive.drawer.title": "Payment receive details ({number})",
+ "payment_made.drawer.title": "Payment made details {number}",
+ "manual_journal.drawer.title": "Manual journal details ({number})",
+ "expense.drawer.title": "Expense details"
}
\ No newline at end of file
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index dd9764664..491b32238 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -369,7 +369,6 @@ export const getDashboardRoutes = () => [
pageTitle: intl.get('new_expense'),
sidebarExpand: false,
backLink: true,
- defaultSearchResource: RESOURCES_TYPES.EXPENSE,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
{
@@ -381,7 +380,6 @@ export const getDashboardRoutes = () => [
pageTitle: intl.get('edit_expense'),
sidebarExpand: false,
backLink: true,
- defaultSearchResource: RESOURCES_TYPES.EXPENSE,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
{
@@ -392,7 +390,6 @@ export const getDashboardRoutes = () => [
breadcrumb: intl.get('expenses_list'),
pageTitle: intl.get('expenses_list'),
hotkey: 'shift+x',
- defaultSearchResource: RESOURCES_TYPES.EXPENSE,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
@@ -630,6 +627,65 @@ export const getDashboardRoutes = () => [
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
+ // Sales Credit notes.
+ {
+ path: `/credit-notes/:id/edit`,
+ component: lazy(() =>
+ import(
+ '../containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormPage'
+ ),
+ ),
+ name: 'credit-note-edit',
+ breadcrumb: intl.get('edit'),
+ pageTitle: intl.get('credit_note.label.edit_credit_note'),
+ backLink: true,
+ sidebarExpand: false,
+ defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+ {
+ path: `/credit-notes/new/?from_invoice_id=/:id`,
+ component: lazy(() =>
+ import(
+ '../containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormPage'
+ ),
+ ),
+ name: 'credit-note-new',
+ breadcrumb: intl.get('credit_note.label.new_credit_note'),
+ backLink: true,
+ sidebarExpand: false,
+ pageTitle: intl.get('credit_note.label.new_credit_note'),
+ defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+ {
+ path: '/credit-notes/new',
+ component: lazy(() =>
+ import(
+ '../containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormPage'
+ ),
+ ),
+ name: 'credit-note-new',
+ breadcrumb: intl.get('credit_note.label.new_credit_note'),
+ backLink: true,
+ sidebarExpand: false,
+ pageTitle: intl.get('credit_note.label.new_credit_note'),
+ defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+ {
+ path: '/credit-notes',
+ component: lazy(() =>
+ import(
+ '../containers/Sales/CreditNotes/CreditNotesLanding/CreditNotesList'
+ ),
+ ),
+ breadcrumb: intl.get('credit_note.label_create_note_list'),
+ pageTitle: intl.get('credit_note.label_create_note_list'),
+ defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+
// Payment receives
{
path: `/payment-receives/:id/edit`,
@@ -713,6 +769,64 @@ export const getDashboardRoutes = () => [
defaultSearchResource: RESOURCES_TYPES.BILL,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
+ // Purchases Credit note.
+ {
+ path: `/vendor-credits/:id/edit`,
+ component: lazy(() =>
+ import(
+ 'containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormPage'
+ ),
+ ),
+ name: 'vendor-credits-edit',
+ breadcrumb: intl.get('edit'),
+ pageTitle: intl.get('vendor_credits.label.edit_vendor_credit'),
+ backLink: true,
+ sidebarExpand: false,
+ defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+ {
+ path: '/vendor-credits/new/?from_bill_id=/:id',
+ component: lazy(() =>
+ import(
+ 'containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormPage'
+ ),
+ ),
+ name: 'vendor-credits-new',
+ backLink: true,
+ sidebarExpand: false,
+ breadcrumb: intl.get('vendor_credits.label.new_vendor_credit'),
+ pageTitle: intl.get('vendor_credits.label.new_vendor_credit'),
+ defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+ {
+ path: '/vendor-credits/new',
+ component: lazy(() =>
+ import(
+ 'containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormPage'
+ ),
+ ),
+ name: 'vendor-credits-new',
+ backLink: true,
+ sidebarExpand: false,
+ breadcrumb: intl.get('vendor_credits.label.new_vendor_credit'),
+ pageTitle: intl.get('vendor_credits.label.new_vendor_credit'),
+ defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
+ {
+ path: '/vendor-credits',
+ component: lazy(() =>
+ import(
+ '../containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNotesList'
+ ),
+ ),
+ breadcrumb: intl.get('vendor_credits.lable_vendor_credit_list'),
+ pageTitle: intl.get('vendor_credits.lable_vendor_credit_list'),
+ defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
+ subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
+ },
// Subscription billing.
{
@@ -788,7 +902,7 @@ export const getDashboardRoutes = () => [
{
path: `/transactions-locking`,
component: lazy(() =>
- import('../containers/TransactionsLocking/TransactionsLockingList'),
+ import('../containers/TransactionsLocking/TransactionsLockingPage'),
),
pageTitle: intl.get('sidebar.transactions_locaking'),
},
diff --git a/src/store/CreditNote/creditNote.actions.js b/src/store/CreditNote/creditNote.actions.js
new file mode 100644
index 000000000..2592bfe54
--- /dev/null
+++ b/src/store/CreditNote/creditNote.actions.js
@@ -0,0 +1,16 @@
+import t from 'store/types';
+
+export const setCreditNoteTableState = (queries) => {
+ return {
+ type: t.CREDIT_NOTES_TABLE_STATE_SET,
+ payload: { queries },
+ };
+};
+
+export const resetCreditNoteTableState = () => {
+ return {
+ type: t.CREDIT_NOTES_TABLE_STATE_RESET,
+ };
+};
+
+export const setSelectedRowsItems = () => {};
diff --git a/src/store/CreditNote/creditNote.reducer.js b/src/store/CreditNote/creditNote.reducer.js
new file mode 100644
index 000000000..8a543fabc
--- /dev/null
+++ b/src/store/CreditNote/creditNote.reducer.js
@@ -0,0 +1,34 @@
+import { createReducer } from '@reduxjs/toolkit';
+import { persistReducer, purgeStoredState } from 'redux-persist';
+import storage from 'redux-persist/lib/storage';
+import { createTableStateReducers } from 'store/tableState.reducer';
+import t from 'store/types';
+
+export const defaultTableQuery = {
+ pageSize: 20,
+ pageIndex: 0,
+ filterRoles: [],
+ viewSlug: null,
+};
+
+const initialState = {
+ tableState: defaultTableQuery,
+};
+
+const STORAGE_KEY = 'bigcapital:credit_notes';
+
+const CONFIG = {
+ key: STORAGE_KEY,
+ whitelist: [],
+ storage,
+};
+
+const reducerInstance = createReducer(initialState, {
+ ...createTableStateReducers('CREDIT_NOTES', defaultTableQuery),
+
+ [t.RESET]: () => {
+ purgeStoredState(CONFIG);
+ },
+});
+
+export default persistReducer(CONFIG, reducerInstance);
diff --git a/src/store/CreditNote/creditNote.selector.js b/src/store/CreditNote/creditNote.selector.js
new file mode 100644
index 000000000..77f761260
--- /dev/null
+++ b/src/store/CreditNote/creditNote.selector.js
@@ -0,0 +1,29 @@
+import { isEqual } from 'lodash';
+import { paginationLocationQuery } from 'store/selectors';
+import { createDeepEqualSelector } from 'utils';
+import { defaultTableQuery } from './creditNote.reducer';
+
+const creditsTableStateSelector = (state) => state.creditNotes.tableState;
+
+/**
+ * Retrieve credit notes table state.
+ */
+export const getCreditNotesTableStateFactory = () =>
+ createDeepEqualSelector(
+ paginationLocationQuery,
+ creditsTableStateSelector,
+ (locationQuery, tableState) => {
+ return {
+ ...locationQuery,
+ ...tableState,
+ };
+ },
+ );
+
+/**
+ * Retrieve credit notes table state.
+ */
+export const isCreditNotesTableStateChangedFactory = () =>
+ createDeepEqualSelector(creditsTableStateSelector, (tableState) => {
+ return !isEqual(tableState, defaultTableQuery);
+ });
diff --git a/src/store/CreditNote/creditNote.type.js b/src/store/CreditNote/creditNote.type.js
new file mode 100644
index 000000000..85585381a
--- /dev/null
+++ b/src/store/CreditNote/creditNote.type.js
@@ -0,0 +1,4 @@
+export default {
+ CREDIT_NOTES_TABLE_STATE_SET: 'CREDIT_NOTES/TABLE_STATE_SET',
+ CREDIT_NOTES_TABLE_STATE_RESET: 'CREDIT_NOTE/TABLE_STATE_RESET',
+};
diff --git a/src/store/VendorCredit/VendorCredit.reducer.js b/src/store/VendorCredit/VendorCredit.reducer.js
new file mode 100644
index 000000000..ac35b0e2b
--- /dev/null
+++ b/src/store/VendorCredit/VendorCredit.reducer.js
@@ -0,0 +1,34 @@
+import { createReducer } from '@reduxjs/toolkit';
+import { persistReducer, purgeStoredState } from 'redux-persist';
+import storage from 'redux-persist/lib/storage';
+import { createTableStateReducers } from 'store/tableState.reducer';
+import t from 'store/types';
+
+export const defaultTableQuery = {
+ pageSize: 20,
+ pageIndex: 0,
+ filterRoles: [],
+ viewSlug: null,
+};
+
+const initialState = {
+ tableState: defaultTableQuery,
+};
+
+const STORAGE_KEY = 'bigcapital:vendor_credits';
+
+const CONFIG = {
+ key: STORAGE_KEY,
+ whitelist: [],
+ storage,
+};
+
+const reducerInstance = createReducer(initialState, {
+ ...createTableStateReducers('VENDOR_CREDITS', defaultTableQuery),
+
+ [t.RESET]: () => {
+ purgeStoredState(CONFIG);
+ },
+});
+
+export default persistReducer(CONFIG, reducerInstance);
diff --git a/src/store/VendorCredit/vendorCredit.actions.js b/src/store/VendorCredit/vendorCredit.actions.js
new file mode 100644
index 000000000..423d9df76
--- /dev/null
+++ b/src/store/VendorCredit/vendorCredit.actions.js
@@ -0,0 +1,16 @@
+import t from 'store/types';
+
+export const setVendorCreditTableState = (queries) => {
+ return {
+ type: t.VENDOR_CREDITS_TABLE_STATE_SET,
+ payload: { queries },
+ };
+};
+
+export const resetVendorCreditTableState = () => {
+ return {
+ type: t.VENDOR_CREDITS_NOTES_TABLE_STATE_RESET,
+ };
+};
+
+export const setSelectedRowsItems = () => {};
diff --git a/src/store/VendorCredit/vendorCredit.selector.js b/src/store/VendorCredit/vendorCredit.selector.js
new file mode 100644
index 000000000..e66ffdd77
--- /dev/null
+++ b/src/store/VendorCredit/vendorCredit.selector.js
@@ -0,0 +1,31 @@
+import { isEqual } from 'lodash';
+import { paginationLocationQuery } from 'store/selectors';
+import { createDeepEqualSelector } from 'utils';
+import { defaultTableQuery } from './VendorCredit.reducer';
+
+const vendorCreditsTableStateSelector = (state) => {
+ return state.vendorCredit.tableState;
+};
+
+/**
+ * Retrieve vendor credit table state.
+ */
+export const getVendorCreditTableStateFactory = () =>
+ createDeepEqualSelector(
+ paginationLocationQuery,
+ vendorCreditsTableStateSelector,
+ (locationQuery, tableState) => {
+ return {
+ ...locationQuery,
+ ...tableState,
+ };
+ },
+ );
+
+/**
+ * Retrieve vendor credit table state.
+ */
+export const isVendorCreditTableStateChangedFactory = () =>
+ createDeepEqualSelector(vendorCreditsTableStateSelector, (tableState) => {
+ return !isEqual(tableState, defaultTableQuery);
+ });
diff --git a/src/store/VendorCredit/vendorCredit.type.js b/src/store/VendorCredit/vendorCredit.type.js
new file mode 100644
index 000000000..b68fcad28
--- /dev/null
+++ b/src/store/VendorCredit/vendorCredit.type.js
@@ -0,0 +1,4 @@
+export default {
+ VENDOR_CREDITS_TABLE_STATE_SET: 'VENDOR_CREDITS/TABLE_STATE_SET',
+ VENDOR_CREDITS_NOTES_TABLE_STATE_RESET: 'VENDOR_CREDITS/TABLE_STATE_RESET',
+};
diff --git a/src/store/reducers.js b/src/store/reducers.js
index db31ab4db..ad28a32e6 100644
--- a/src/store/reducers.js
+++ b/src/store/reducers.js
@@ -32,6 +32,8 @@ import organizations from './organizations/organizations.reducers';
import subscriptions from './subscription/subscription.reducer';
import inventoryAdjustments from './inventoryAdjustments/inventoryAdjustment.reducer';
import plans from './plans/plans.reducer';
+import creditNotes from './CreditNote/creditNote.reducer';
+import vendorCredit from './VendorCredit/VendorCredit.reducer';
const appReducer = combineReducers({
authentication,
@@ -63,7 +65,9 @@ const appReducer = combineReducers({
paymentReceives,
paymentMades,
inventoryAdjustments,
- plans
+ plans,
+ creditNotes,
+ vendorCredit,
});
// Reset the state of a redux store
@@ -71,7 +75,7 @@ const rootReducer = (state, action) => {
if (action.type === types.RESET) {
state = undefined;
}
- return appReducer(state, action)
-}
+ return appReducer(state, action);
+};
-export default rootReducer;
\ No newline at end of file
+export default rootReducer;
diff --git a/src/store/settings/settings.reducer.js b/src/store/settings/settings.reducer.js
index 28ceaa9e8..853ab0589 100644
--- a/src/store/settings/settings.reducer.js
+++ b/src/store/settings/settings.reducer.js
@@ -52,6 +52,12 @@ const initialState = {
cashflowTransactions: {
tableSize: 'medium',
},
+ creditNote: {
+ tableSize: 'medium',
+ },
+ vendorCredit: {
+ tableSize: 'medium',
+ },
},
};
diff --git a/src/store/types.js b/src/store/types.js
index b79f0d1ba..3e509142f 100644
--- a/src/store/types.js
+++ b/src/store/types.js
@@ -28,6 +28,8 @@ import paymentMades from './PaymentMades/paymentMades.type';
import organizations from './organizations/organizations.types';
import subscription from './subscription/subscription.types';
import inventoryAdjustments from './inventoryAdjustments/inventoryAdjustment.type';
+import creditNote from './CreditNote/creditNote.type';
+import vendorCredit from './VendorCredit/vendorCredit.type';
import plans from './plans/plans.types';
export default {
@@ -61,5 +63,7 @@ export default {
...organizations,
...subscription,
...inventoryAdjustments,
- ...plans
+ ...plans,
+ ...creditNote,
+ ...vendorCredit
};
diff --git a/src/style/App.scss b/src/style/App.scss
index cc5d3e2e1..55b604c00 100644
--- a/src/style/App.scss
+++ b/src/style/App.scss
@@ -11,6 +11,7 @@
// Objects
@import 'objects/form';
+@import 'objects/switch';
@import 'objects/typography';
@import 'objects/buttons';
@import 'objects/Bigcapital';
@@ -21,7 +22,6 @@
@import 'components/resizer';
@import 'components/CloudSpinner';
@import 'components/Alert';
-@import 'components/Card';
@import 'components/Toast';
@import 'components/PageForm';
@import 'components/Tooltip';
diff --git a/src/style/components/Card.scss b/src/style/components/Card.scss
deleted file mode 100644
index 5662ab350..000000000
--- a/src/style/components/Card.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-
-.card{
- background: #fff;
- border: 1px solid #d2dce2;
-}
\ No newline at end of file
diff --git a/src/style/components/DataTable/DataTable.scss b/src/style/components/DataTable/DataTable.scss
index 1eb7c15f9..1258e6160 100644
--- a/src/style/components/DataTable/DataTable.scss
+++ b/src/style/components/DataTable/DataTable.scss
@@ -120,7 +120,6 @@
}
.bp3-control.bp3-checkbox .bp3-control-indicator {
- border: 1px solid #c2c2c2;
cursor: auto;
&,
@@ -359,12 +358,10 @@
.ReactVirtualized__Grid {
will-change: auto !important;
}
-
-
-
}
-.table-constrant {
+.table-constrant,
+.table--constrant {
.table {
.thead .th {
background: transparent;
@@ -379,9 +376,5 @@
padding: 0.5rem 0.5rem;
border-bottom: 0;
}
-
- .tbody .tr:last-child .td {
- border-bottom: 1px solid #d2dce2;
- }
}
}
\ No newline at end of file
diff --git a/src/style/components/Details.scss b/src/style/components/Details.scss
index 6b62d9fd7..fd28128cb 100644
--- a/src/style/components/Details.scss
+++ b/src/style/components/Details.scss
@@ -10,7 +10,7 @@
flex-grow: 1;
&__content{
- margin: 5px 0;
+ margin: 2px 0;
}
}
}
@@ -23,12 +23,16 @@
flex-direction: row;
&:not(:first-of-type){
- margin-top: 16px;
+ margin-top: 12px;
}
&__label{
padding-right: 10px;
}
+
+ &__content{
+ width: 100%;
+ }
}
}
diff --git a/src/style/components/Drawers/AccountDrawer.scss b/src/style/components/Drawers/AccountDrawer.scss
index 7b120cff0..aaaff51ed 100644
--- a/src/style/components/Drawers/AccountDrawer.scss
+++ b/src/style/components/Drawers/AccountDrawer.scss
@@ -1,8 +1,7 @@
.account-drawer {
- background-color: #fbfbfb;
-
+
.card-header{
margin: 15px;
padding: 22px 15px;
@@ -35,34 +34,4 @@
}
}
}
-
- &__table {
- margin: 18px;
- background: #fff;
- border: 1px solid #d2dce2;
-
- .table {
- .thead {
- .tr .th {
- padding: 0.7rem 0.8rem;
- font-weight: 500;
- }
- }
-
- .tbody .tr .td {
- padding: 0.6rem 0.8rem;
- }
- }
-
- &-footer{
- padding: 10px 14px;
- display: inline-block;
-
- a{
- text-decoration: underline;
- font-size: 12px;
- color: #37639c;
- }
- }
- }
}
\ No newline at end of file
diff --git a/src/style/components/Drawers/EstimateDetails.module.scss b/src/style/components/Drawers/EstimateDetails.module.scss
index 862a42e72..86ef8d448 100644
--- a/src/style/components/Drawers/EstimateDetails.module.scss
+++ b/src/style/components/Drawers/EstimateDetails.module.scss
@@ -49,15 +49,14 @@
.total_line{
&_subtotal {
- border-bottom: 1px solid #000;
+
}
&_total {
- border-bottom: 3px double #000;
- font-weight: 600;
+
}
&_dueAmount {
- font-weight: 600;
+
}
}
diff --git a/src/style/components/Drawers/InvoiceDrawer.module.scss b/src/style/components/Drawers/InvoiceDrawer.module.scss
deleted file mode 100644
index 770744e1c..000000000
--- a/src/style/components/Drawers/InvoiceDrawer.module.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-
-.detail_panel {
- :global .card {
- padding: 22px 15px;
- }
-
- &_header {
- margin-bottom: 30px;
- }
-
- &_table {
- :global .bigcapital-datatable {
-
- .thead,
- .tbody {
-
- .quantity,
- .rate,
- .amount {
- text-align: right;
- }
- }
- }
- }
-
- &_footer {
- display: flex;
-
- :global .total_lines {
- margin-left: auto;
- }
-
- :global .total_lines_line {
-
- .amount,
- .title {
- width: 180px;
- }
-
- .amount {
- text-align: right;
- }
- }
- .total_line {
- &_subtotal {
- border-bottom: 1px solid #000;
- }
-
- &_total {
- border-bottom: 3px double #000;
- font-weight: 600;
- }
-
- &_dueAmount {
- font-weight: 600;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/style/components/Drawers/ItemDrawer.scss b/src/style/components/Drawers/ItemDrawer.scss
index b97b84eaa..e39dda44c 100644
--- a/src/style/components/Drawers/ItemDrawer.scss
+++ b/src/style/components/Drawers/ItemDrawer.scss
@@ -1,12 +1,10 @@
.item-drawer {
-
.card {
margin: 15px;
padding: 22px 15px;
}
&__content {
-
.detail-item--name {
width: 30%;
@@ -16,7 +14,6 @@
}
.detail-item--quantity {
-
.detail-item__content {
font-weight: 600;
@@ -32,7 +29,6 @@
}
.details-menu--horizantal {
-
.detail-item:not(:first-of-type) {
margin-top: 16px;
}
@@ -42,4 +38,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/style/components/Drawers/VendorCreditDetail.module.scss b/src/style/components/Drawers/VendorCreditDetail.module.scss
new file mode 100644
index 000000000..5f0de943f
--- /dev/null
+++ b/src/style/components/Drawers/VendorCreditDetail.module.scss
@@ -0,0 +1,68 @@
+.root {
+}
+
+.detail_panel {
+ :global .card {
+ padding: 22px 15px;
+ margin: 15px;
+ }
+
+ &_table {
+ :global .bigcapital-datatable {
+ margin-top: 30px;
+
+ .thead,
+ .tbody {
+ .quantity,
+ .rate,
+ .amount {
+ text-align: right;
+ }
+ }
+ }
+ }
+
+ &_footer {
+ :global .total_lines {
+ margin-left: auto;
+
+ &_line {
+ .title {
+ padding-left: 0;
+ }
+ .amount,
+ .title {
+ width: 180px;
+ }
+ .amount {
+ text-align: right;
+ }
+ }
+ }
+ }
+
+ &_footer {
+ display: flex;
+ margin-bottom: 20px;
+ }
+
+ .total_line {
+ &_subtotal {
+ border-bottom: 1px solid #000;
+ }
+
+ &_total {
+ border-bottom: 3px double #000;
+ font-weight: 600;
+ }
+ &_dueAmount {
+ font-weight: 600;
+ }
+ }
+
+ &_note {
+ b {
+ color: #727983;
+ }
+ }
+}
diff --git a/src/style/objects/form.scss b/src/style/objects/form.scss
index b426192c2..80ca55605 100644
--- a/src/style/objects/form.scss
+++ b/src/style/objects/form.scss
@@ -504,4 +504,8 @@ label.bp3-label {
}
}
}
+}
+
+.bp3-control.bp3-checkbox .bp3-control-indicator{
+ border-color: #666;
}
\ No newline at end of file
diff --git a/src/style/objects/switch.scss b/src/style/objects/switch.scss
new file mode 100644
index 000000000..16bd2d8c3
--- /dev/null
+++ b/src/style/objects/switch.scss
@@ -0,0 +1,8 @@
+.bp3-control.bp3-switch {
+ .bp3-control-indicator {
+
+ &:before {
+ box-shadow: none;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/style/pages/AllocateLandedCost/AllocateLandedCostForm.scss b/src/style/pages/AllocateLandedCost/AllocateLandedCostForm.scss
index 1040746e2..d0b23d633 100644
--- a/src/style/pages/AllocateLandedCost/AllocateLandedCostForm.scss
+++ b/src/style/pages/AllocateLandedCost/AllocateLandedCostForm.scss
@@ -8,7 +8,7 @@
}
.bp3-form-group.bp3-inline {
.bp3-label {
- min-width: 150px;
+ min-width: 165px;
}
.bp3-form-content {
width: 300px;
diff --git a/src/style/pages/AllocateLandedCost/List.scss b/src/style/pages/AllocateLandedCost/List.scss
new file mode 100644
index 000000000..a09b2fddf
--- /dev/null
+++ b/src/style/pages/AllocateLandedCost/List.scss
@@ -0,0 +1,22 @@
+.datatable--landed-cost-transactions {
+ padding: 12px;
+ .table {
+ .tbody,
+ .thead {
+ .tr .th {
+ padding: 8px 8px;
+ background-color: #fff;
+ font-size: 14px;
+ border-bottom: 1px solid #000;
+ border-top: 1px solid #000;
+ }
+ }
+ .tbody {
+ .tr .td {
+ border-bottom: 0;
+ padding-top: 0.4rem;
+ padding-bottom: 0.4rem;
+ }
+ }
+ }
+}
diff --git a/src/style/pages/Bills/List.scss b/src/style/pages/Bills/List.scss
index 2fcb700cb..55b52b0af 100644
--- a/src/style/pages/Bills/List.scss
+++ b/src/style/pages/Bills/List.scss
@@ -45,7 +45,7 @@
font-size: 13.5px;
}
.bp3-progress-bar {
- height: 4px;
+ height: 3px;
max-width: 180px;
&,
diff --git a/src/style/pages/CreditNote/List.scss b/src/style/pages/CreditNote/List.scss
new file mode 100644
index 000000000..087b2f910
--- /dev/null
+++ b/src/style/pages/CreditNote/List.scss
@@ -0,0 +1,20 @@
+.dashboard__insider--credit-note-list {
+ .bigcapital-datatable {
+ .tbody {
+ .amount.td {
+ .cell-inner {
+ > span {
+ font-weight: 600;
+ }
+ }
+ }
+ }
+ .table-size--small {
+ .status.td {
+ .bp3-progress-bar {
+ height: 3px;
+ }
+ }
+ }
+ }
+}
diff --git a/src/style/pages/CreditNote/PageForm.scss b/src/style/pages/CreditNote/PageForm.scss
new file mode 100644
index 000000000..8da43b9aa
--- /dev/null
+++ b/src/style/pages/CreditNote/PageForm.scss
@@ -0,0 +1,50 @@
+body.page-credit-note-new,
+body.page-credit-note-edit {
+ .dashboard__footer {
+ display: none;
+ }
+}
+
+.dashboard__insider--credit-note-form {
+ padding-bottom: 64px;
+}
+
+.page-form--credit-note {
+ $self: '.page-form';
+
+ #{$self}__header {
+ display: flex;
+
+ &-fields {
+ flex: 1 0 0;
+ }
+
+ .bp3-label {
+ min-width: 150px;
+ }
+ .bp3-form-content {
+ width: 100%;
+ }
+
+ .bp3-form-group {
+ &.bp3-inline {
+ max-width: 450px;
+ }
+ }
+ .col--credit-note-date {
+ max-width: 435px;
+ }
+ }
+ #{$self}__footer {
+ .form-group--note,
+ .form-group--terms_conditions {
+ max-width: 450px;
+ width: 100%;
+
+ textarea {
+ width: 100%;
+ min-height: 60px;
+ }
+ }
+ }
+}
diff --git a/src/style/pages/Expense/PageForm.scss b/src/style/pages/Expense/PageForm.scss
index 102a3819e..6aaf1fade 100644
--- a/src/style/pages/Expense/PageForm.scss
+++ b/src/style/pages/Expense/PageForm.scss
@@ -1,5 +1,5 @@
-.dashboard__insider--expenses {
-
+.dashboard__insider--expense-form {
+ padding-bottom: 64px;
.bigcapital-datatable {
.tbody {
diff --git a/src/style/pages/FinancialStatements/APAgingSummary.scss b/src/style/pages/FinancialStatements/APAgingSummary.scss
index f61ee093e..1018a293e 100644
--- a/src/style/pages/FinancialStatements/APAgingSummary.scss
+++ b/src/style/pages/FinancialStatements/APAgingSummary.scss
@@ -7,8 +7,8 @@
.bigcapital-datatable{
.tbody,
.thead{
- .tr .td.customer_name ~ .td,
- .tr .th.customer_name ~ .th{
+ .tr .td.vendor_name ~ .td,
+ .tr .th.vendor_name ~ .th{
text-align: right;
}
}
diff --git a/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss b/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss
index def379b49..df41bc845 100644
--- a/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss
+++ b/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss
@@ -1,25 +1,26 @@
.financial-sheet {
+
&--customers-balance-summary,
&--vendors-balance-summary {
.financial-sheet__table {
+
.thead,
.tbody {
- .tr .td.customer_name ~ .td,
- .tr .th.customer_name ~ .th {
+
+ .tr .td.customer_name~.td,
+ .tr .th.customer_name~.th {
text-align: right;
}
}
+
.tbody {
.tr:not(.no-results) {
- &.row-type--CUSTOMER,
- &.row-type--VENDOR {
- border-top: 1px solid #BBB
- }
.td {
border-bottom: 0;
padding-top: 0.4rem;
padding-bottom: 0.4rem;
}
+
&.row-type--TOTAL {
font-weight: 500;
@@ -33,6 +34,7 @@
}
}
}
+
.financial-statement--balance-summary {
.financial-header-drawer {
.bp3-drawer {
@@ -40,4 +42,4 @@
max-height: 415px;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/style/pages/FinancialStatements/ContactsTransactions.scss b/src/style/pages/FinancialStatements/ContactsTransactions.scss
index 7fb3ff80a..7b9bd32e0 100644
--- a/src/style/pages/FinancialStatements/ContactsTransactions.scss
+++ b/src/style/pages/FinancialStatements/ContactsTransactions.scss
@@ -1,13 +1,17 @@
.financial-sheet {
+
&--customer-transactions,
&--vendor-transactions {
width: 100%;
.financial-sheet__table {
+
.tbody,
.thead {
+
.tr .td,
.tr .th {
+
&.credit,
&.debit,
&.running_balance {
@@ -15,6 +19,7 @@
}
}
}
+
.tbody {
.tr .td {
padding-top: 0.2rem;
@@ -24,39 +29,51 @@
&.customer_name,
&.vendor_name {
- > div {
+ >div {
display: flex;
}
+
span.force-width {
position: relative;
}
}
}
+
.tr:not(.no-results) .td {
border-left: 1px solid #ececec;
}
+ .tr:last-child .td {
+ border-bottom: 1px solid #e0e0e0;
+ }
+
.tr.row-type {
+
&--CUSTOMER,
&--VENDOR {
.td {
+
&.customer_name,
&.vendor_name {
font-weight: 500;
}
+
&.name {
// border-left-color: transparent;
}
}
+
&:not(:first-child).is-expanded .td {
border-top: 1px solid #ddd;
}
}
+
&--OPENING_BALANCE,
// &--TRANSACTION,
&--CLOSING_BALANCE {
font-weight: 500;
}
+
&--CUSTOMER,
&--VENDOR {
&.is-expanded {
@@ -64,10 +81,12 @@
display: none;
}
}
+
&:not(:first-child).is-expanded .td {
border-top: 1px solid #ddd;
}
}
+
&--CUSTOMER:last-child,
&--VENDOR:last-child {
.td {
@@ -86,4 +105,4 @@
max-height: 450px;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/style/pages/FinancialStatements/GeneralLedger.scss b/src/style/pages/FinancialStatements/GeneralLedger.scss
index a50936220..c5f499aa0 100644
--- a/src/style/pages/FinancialStatements/GeneralLedger.scss
+++ b/src/style/pages/FinancialStatements/GeneralLedger.scss
@@ -1,75 +1,88 @@
+.financial-sheet {
+ &--general-ledger {
+ .financial-sheet__table {
-.financial-sheet{
- &--general-ledger{
- .financial-sheet__table{
.tbody,
- .thead{
+ .thead {
+
.tr .td,
- .tr .th{
+ .tr .th {
+
&.credit,
&.debit,
&.running_balance,
- &.amount{
+ &.amount {
text-align: right;
}
}
}
- .tbody{
-
- .tr .td{
+
+ .tbody {
+ .tr .td {
padding-top: 0.2rem;
padding-bottom: 0.2rem;
border-top-color: transparent;
border-bottom-color: transparent;
-
- &.date{
- > div{
+
+ &.date {
+ >div {
display: flex;
}
- span.force-width{
+
+ span.force-width {
position: relative;
}
}
}
- .tr:not(.no-results) .td{
+
+ .tr:not(.no-results) .td {
border-left: 1px solid #ececec;
}
- .tr{
- &.is-expanded{
+ .tr:last-child .td {
+ border-bottom: 1px solid #ececec;
+ }
- .td.amount{
+ .tr {
+ &.is-expanded {
- .cell-inner{
+ .td.amount {
+
+ .cell-inner {
display: none
}
}
}
}
- .tr.row-type{
+
+ .tr.row-type {
- &--ACCOUNT_ROW{
- .td{
- &.date{
+ &--ACCOUNT_ROW {
+ .td {
+ &.date {
font-weight: 500;
}
- &.name{
+
+ &.name {
border-left-color: transparent;
}
}
- &:not(:first-child).is-expanded .td{
+
+ &:not(:first-child).is-expanded .td {
border-top: 1px solid #DDD;
}
}
+
&--OPENING_BALANCE,
- &--CLOSING_BALANCE{
- .amount{
+ &--CLOSING_BALANCE {
+ .amount {
font-weight: 500;
}
}
- &--CLOSING_BALANCE{
- .name{
+
+ &--CLOSING_BALANCE {
+ .name {
font-weight: 500;
}
}
diff --git a/src/style/pages/FinancialStatements/InventoryItemDetails.scss b/src/style/pages/FinancialStatements/InventoryItemDetails.scss
index d2458d1c3..b795ad410 100644
--- a/src/style/pages/FinancialStatements/InventoryItemDetails.scss
+++ b/src/style/pages/FinancialStatements/InventoryItemDetails.scss
@@ -3,21 +3,25 @@
width: 100%;
.financial-sheet__table {
+
.tbody,
.thead {
- .tr .td.transaction_id ~ .td,
- .tr .th.transaction_id ~ .th {
+
+ .tr .td.transaction_id~.td,
+ .tr .th.transaction_id~.th {
text-align: right;
}
}
+
.tbody {
.tr .td {
padding-top: 0.2rem;
padding-bottom: 0.2rem;
border-top-color: transparent;
border-bottom-color: transparent;
+
&.date {
- > div {
+ >div {
display: flex;
}
@@ -26,10 +30,15 @@
}
}
}
+
.tr:not(.no-results) .td {
border-left: 1px solid #ececec;
}
+ .tr:last-child .td {
+ border-bottom: 1px solid #ddd;
+ }
+
.tr.row-type {
&--ITEM {
.td {
@@ -37,15 +46,18 @@
border-left-color: transparent;
}
}
+
&:not(:first-child).is-expanded .td {
border-top: 1px solid #ddd;
}
}
+
&--ITEM,
&--OPENING_ENTRY,
&--CLOSING_ENTRY {
font-weight: 500;
}
+
&--ITEM {
&.is-expanded {
.td.value .cell-inner {
@@ -58,20 +70,23 @@
}
}
}
+
.number-format-dropdown {
.toggles-fields {
.bp3-form-group:first-child {
display: none;
}
}
+
.form-group--money-format {
display: none;
}
}
+
.financial-statement--inventory-details {
.financial-header-drawer {
.bp3-drawer {
max-height: 350px;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/style/pages/JournalEntries/List.scss b/src/style/pages/JournalEntries/List.scss
index eb032d1c7..1c9c5a9b7 100644
--- a/src/style/pages/JournalEntries/List.scss
+++ b/src/style/pages/JournalEntries/List.scss
@@ -1,14 +1,29 @@
-.datatable--journal-entries {
- .table {
- .tbody {
- .tr .td {
- min-height: 42px;
+// .datatable--journal-entries {
+// // margin: 12px;
+// padding: 12px;
- &.credit,
- &.debit {
- font-weight: 600;
- }
- }
- }
- }
-}
+// .table {
+// .tbody,
+// .thead {
+// .tr .th {
+// padding: 8px 8px;
+// background-color: #fff;
+// font-size: 14px;
+// border-bottom: 1px solid #000;
+// border-top: 1px solid #000;
+// }
+// }
+// .tbody {
+// .tr .td {
+// border-bottom: 0;
+// padding-top: 0.4rem;
+// padding-bottom: 0.4rem;
+
+// &.credit,
+// &.debit {
+// font-weight: 600;
+// }
+// }
+// }
+// }
+// }
diff --git a/src/style/pages/ManualJournal/MakeJournal.scss b/src/style/pages/ManualJournal/MakeJournal.scss
index d10c11380..1490e7642 100644
--- a/src/style/pages/ManualJournal/MakeJournal.scss
+++ b/src/style/pages/ManualJournal/MakeJournal.scss
@@ -1,3 +1,6 @@
+.dashboard__insider--make-journal-page {
+ padding-bottom: 64px;
+}
.page-form--make-journal-entries{
$self: '.page-form';
diff --git a/src/style/pages/PaymentTransactions/List.scss b/src/style/pages/PaymentTransactions/List.scss
new file mode 100644
index 000000000..baaff57df
--- /dev/null
+++ b/src/style/pages/PaymentTransactions/List.scss
@@ -0,0 +1,23 @@
+.payment-transactions {
+ padding: 12px;
+
+ .table {
+ .tbody,
+ .thead {
+ .tr .th {
+ padding: 8px 8px;
+ background-color: #fff;
+ font-size: 14px;
+ border-bottom: 1px solid #000;
+ border-top: 1px solid #000;
+ }
+ }
+ .tbody {
+ .tr .td {
+ border-bottom: 0;
+ padding-top: 0.4rem;
+ padding-bottom: 0.4rem;
+ }
+ }
+ }
+}
diff --git a/src/style/pages/Preferences/GeneralForm.scss b/src/style/pages/Preferences/GeneralForm.scss
index 2a5bec102..283ea9fae 100644
--- a/src/style/pages/Preferences/GeneralForm.scss
+++ b/src/style/pages/Preferences/GeneralForm.scss
@@ -3,23 +3,6 @@
// General page
//---------------------------------
.preferences-page__inside-content--general {
- .card {
- padding: 25px;
-
- .card__footer {
- padding-top: 16px;
- border-top: 1px solid #e0e7ea;
- margin-top: 30px;
-
- .bp3-button {
- min-width: 70px;
-
- + .bp3-button{
- margin-left: 10px;
- }
- }
- }
- }
.bp3-form-group {
max-width: 650px;
diff --git a/src/style/pages/Preferences/Page.scss b/src/style/pages/Preferences/Page.scss
index d156b96c4..7c621b52f 100644
--- a/src/style/pages/Preferences/Page.scss
+++ b/src/style/pages/Preferences/Page.scss
@@ -33,6 +33,8 @@
}
}
&__inside-content {
+ overflow: auto;
+
.#{$ns}-tab-list {
border-bottom: 1px solid #e5e5e5;
padding-left: 15px;
diff --git a/src/style/pages/Preferences/Roles/Form.scss b/src/style/pages/Preferences/Roles/Form.scss
index 916d611c2..1b375407e 100644
--- a/src/style/pages/Preferences/Roles/Form.scss
+++ b/src/style/pages/Preferences/Roles/Form.scss
@@ -1,6 +1,8 @@
// Roles Form page
//---------------------------------
.preferences-page__inside-content--roles-form {
+ padding-bottom: 60px;
+
.card {
padding: 25px;
@@ -20,17 +22,21 @@
}
.bp3-form-group {
- max-width: 500px;
+ max-width: 600px;
margin-bottom: 14px;
&.bp3-inline {
.bp3-label {
- min-width: 100px;
+ min-width: 150px;
}
}
.bp3-form-content {
width: 100%;
}
+
+ &:last-of-type{
+ margin-bottom: 0;
+ }
}
.form-group--description {
textarea {
@@ -39,20 +45,4 @@
font-size: 14px;
}
}
- .bp3-control.bp3-checkbox {
- .bp3-control-indicator {
- border: 1px solid #c2c2c2;
- cursor: auto;
-
- &,
- &:hover {
- height: 15px;
- width: 15px;
- }
- &:before {
- width: 15px;
- height: 15px;
- }
- }
- }
}
diff --git a/src/style/pages/Preferences/Sidebar.scss b/src/style/pages/Preferences/Sidebar.scss
index 12b3dd8ae..164d88034 100644
--- a/src/style/pages/Preferences/Sidebar.scss
+++ b/src/style/pages/Preferences/Sidebar.scss
@@ -3,7 +3,7 @@
// Preferences sidebar.
// -----------------------------
.preferences-sidebar {
- background: #e5eaee;
+ background: #eaeef6;
border-right: 1px solid #c6d0d9;
min-width: 220px;
max-width: 220px;
@@ -13,13 +13,17 @@
&__wrapper {
height: 100%;
}
+
.ScrollbarsCustom-Track {
+
&.ScrollbarsCustom-TrackY,
&.ScrollbarsCustom-TrackX {
background: rgba(0, 0, 0, 0);
}
}
+
.ScrollbarsCustom-Thumb {
+
&.ScrollbarsCustom-ThumbX,
&.ScrollbarsCustom-ThumbY {
background: rgba(0, 0, 0, 0);
@@ -28,6 +32,7 @@
&:hover {
.ScrollbarsCustom-Thumb {
+
&.ScrollbarsCustom-ThumbX,
&.ScrollbarsCustom-ThumbY {
background: rgba(0, 0, 0, 0.15);
@@ -68,4 +73,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/style/pages/ReconcileCreditNote/ReconcileCreditNoteForm.scss b/src/style/pages/ReconcileCreditNote/ReconcileCreditNoteForm.scss
new file mode 100644
index 000000000..0d793aaca
--- /dev/null
+++ b/src/style/pages/ReconcileCreditNote/ReconcileCreditNoteForm.scss
@@ -0,0 +1,13 @@
+.dialog--reconcile-credit-form {
+ width: 850px;
+
+ .bp3-callout {
+ font-size: 14px;
+ }
+
+ .bp3-dialog-footer {
+ display: flex;
+ justify-content: flex-start;
+ padding-top: 10px;
+ }
+}
\ No newline at end of file
diff --git a/src/style/pages/ReconcileVendorCredit/ReconcileVendorCreditForm.scss b/src/style/pages/ReconcileVendorCredit/ReconcileVendorCreditForm.scss
new file mode 100644
index 000000000..8d8e7239f
--- /dev/null
+++ b/src/style/pages/ReconcileVendorCredit/ReconcileVendorCreditForm.scss
@@ -0,0 +1,45 @@
+.dialog--reconcile-vendor-credit-form {
+ width: 850px;
+
+ .bigcapital-datatable {
+ .table {
+ border: 1px solid #d1dee2;
+ min-width: auto;
+
+ .tbody,
+ .tbody-inner {
+ height: auto;
+ scrollbar-width: none;
+
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ }
+
+ .tbody {
+ .bp3-form-group {
+ margin-bottom: 0;
+
+ &:not(.bp3-intent-danger) .bp3-input {
+ border: 1px solid #d0dfe2;
+
+ &:focus {
+ box-shadow: 0 0 0 1px #116cd0;
+ border-color: #116cd0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .bp3-callout {
+ font-size: 14px;
+ }
+
+ .bp3-dialog-footer {
+ display: flex;
+ justify-content: flex-start;
+ padding-top: 10px;
+ }
+}
\ No newline at end of file
diff --git a/src/style/pages/RefundCreditNote/List.scss b/src/style/pages/RefundCreditNote/List.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/style/pages/RefundCreditNote/RefundCreditNote.scss b/src/style/pages/RefundCreditNote/RefundCreditNote.scss
new file mode 100644
index 000000000..a8c216880
--- /dev/null
+++ b/src/style/pages/RefundCreditNote/RefundCreditNote.scss
@@ -0,0 +1,23 @@
+.dialog--refund-credit-note {
+ .bp3-dialog-body {
+ .bp3-form-group {
+ margin-bottom: 16px;
+ }
+
+ .form-group {
+ &--description {
+ .bp3-form-content {
+ textarea {
+ width: 100%;
+ min-width: 100%;
+ font-size: 14px;
+ }
+ }
+ }
+ }
+ }
+
+ .bp3-dialog-footer {
+ padding-top: 10px;
+ }
+}
\ No newline at end of file
diff --git a/src/style/pages/RefundVendorCredit/List.scss b/src/style/pages/RefundVendorCredit/List.scss
new file mode 100644
index 000000000..05ebf36d1
--- /dev/null
+++ b/src/style/pages/RefundVendorCredit/List.scss
@@ -0,0 +1,27 @@
+.datatable--refund-transactions {
+ padding: 12px;
+ .table {
+ .tbody,
+ .thead {
+ .tr .th {
+ padding: 8px 8px;
+ background-color: #fff;
+ font-size: 14px;
+ border-bottom: 1px solid #000;
+ border-top: 1px solid #000;
+ }
+ }
+ .tbody {
+ .tr .td {
+ border-bottom: 0;
+ padding-top: 0.4rem;
+ padding-bottom: 0.4rem;
+
+ &.credit,
+ &.debit {
+ font-weight: 600;
+ }
+ }
+ }
+ }
+}
diff --git a/src/style/pages/RefundVendorCredit/RefundVendorCredit.scss b/src/style/pages/RefundVendorCredit/RefundVendorCredit.scss
new file mode 100644
index 000000000..033acd0c2
--- /dev/null
+++ b/src/style/pages/RefundVendorCredit/RefundVendorCredit.scss
@@ -0,0 +1,24 @@
+.dialog--refund-vendor-credit {
+ max-width: 450px;
+
+ .bp3-dialog-body {
+ .bp3-form-group {
+ margin-bottom: 16px;
+ }
+
+ .form-group {
+ &--description {
+ .bp3-form-content {
+ textarea {
+ width: 100%;
+ min-width: 100%;
+ font-size: 14px;
+ }
+ }
+ }
+ }
+ }
+ .bp3-dialog-footer {
+ padding-top: 10px;
+ }
+}
diff --git a/src/style/pages/SaleInvoice/List.scss b/src/style/pages/SaleInvoice/List.scss
index adb06f1e7..03e62e64a 100644
--- a/src/style/pages/SaleInvoice/List.scss
+++ b/src/style/pages/SaleInvoice/List.scss
@@ -45,7 +45,7 @@
font-size: 13.5px;
}
.bp3-progress-bar {
- height: 4px;
+ height: 3px;
max-width: 180px;
&,
@@ -55,12 +55,5 @@
}
}
}
- .table-size--small {
- .status.td {
- .bp3-progress-bar {
- height: 3px;
- }
- }
- }
}
}
diff --git a/src/style/pages/TransactionsLocking/TransactionsLockingDialog.scss b/src/style/pages/TransactionsLocking/TransactionsLockingDialog.scss
index b1aed0430..a8d8bc7e6 100644
--- a/src/style/pages/TransactionsLocking/TransactionsLockingDialog.scss
+++ b/src/style/pages/TransactionsLocking/TransactionsLockingDialog.scss
@@ -1,8 +1,9 @@
.dialog--transaction--locking {
- max-width: 400px;
+ max-width: 450px;
+
.bp3-form-group {
- margin-bottom: 15px;
- margin-top: 15px;
+ margin-bottom: 10px;
+ margin-top: 10px;
label.bp3-label {
font-size: 13px;
@@ -15,6 +16,7 @@
.bp3-form-content {
textarea {
width: 100%;
+ min-height: 85px;
min-width: 100%;
font-size: 14px;
}
@@ -22,6 +24,9 @@
}
}
.bp3-dialog-footer {
- padding-top: 10px;
+ display: flex;
+ justify-content: flex-start;
+ // padding-top: 10px;
+ margin-left: 10px;
}
}
diff --git a/src/style/pages/VendorsCreditNote/List.scss b/src/style/pages/VendorsCreditNote/List.scss
new file mode 100644
index 000000000..5119f3081
--- /dev/null
+++ b/src/style/pages/VendorsCreditNote/List.scss
@@ -0,0 +1,20 @@
+.dashboard__insider--vendors-credit-note-list {
+ .bigcapital-datatable {
+ .tbody {
+ .amount.td {
+ .cell-inner {
+ > span {
+ font-weight: 600;
+ }
+ }
+ }
+ }
+ .table-size--small {
+ .status.td {
+ .bp3-progress-bar {
+ height: 3px;
+ }
+ }
+ }
+ }
+}
diff --git a/src/style/pages/VendorsCreditNote/PageForm.scss b/src/style/pages/VendorsCreditNote/PageForm.scss
new file mode 100644
index 000000000..79be9954b
--- /dev/null
+++ b/src/style/pages/VendorsCreditNote/PageForm.scss
@@ -0,0 +1,49 @@
+body.page-vendor-credit-note-new,
+body.page-vendor-credit-note-edit {
+ .dashboard__footer {
+ display: none;
+ }
+}
+
+.dashboard__insider--vendor-credit-form {
+ padding-bottom: 64px;
+}
+
+.page-form--vendor-credit-note {
+ $self: '.page-form';
+
+ #{$self}__header {
+ display: flex;
+
+ &-fields {
+ flex: 1 0 0;
+ }
+
+ .bp3-label {
+ min-width: 150px;
+ }
+ .bp3-form-content {
+ width: 100%;
+ }
+
+ .bp3-form-group {
+ &.bp3-inline {
+ max-width: 450px;
+ }
+ }
+ .col--invoice-date {
+ max-width: 435px;
+ }
+ }
+ #{$self}__footer {
+ .form-group--note {
+ max-width: 450px;
+ width: 100%;
+
+ textarea {
+ width: 100%;
+ min-height: 60px;
+ }
+ }
+ }
+}
diff --git a/src/utils/styled-components.js b/src/utils/styled-components.js
deleted file mode 100644
index f03c8c2ad..000000000
--- a/src/utils/styled-components.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { css } from 'styled-components';
-
-export const whenRtl = (restCss) => css`
- ${({ theme }) => theme.dir === 'rtl' && restCss}
-`;
-
-export const whenLtr = (restCss) => css`
- ${({ theme }) => theme.dir === 'ltr' && restCss}
-`;