diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx
index 0657299d6..5300bb9ed 100644
--- a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx
+++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx
@@ -5,10 +5,14 @@ import {
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
+ FFormGroup,
+ FInputGroup,
+ FSelect,
} from '@/components';
import { useBillAggregatedTaxRates, useBillTotals } from './utils';
import { useFormikContext } from 'formik';
import { TaxType } from '@/interfaces/TaxRates';
+import { Button } from '@blueprintjs/core';
export function BillFormFooterRight() {
const {
@@ -37,6 +41,34 @@ export function BillFormFooterRight() {
value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
+
+ {/* ----------- Discount ----------- */}
+
+ (
+
+ )}
+ filterable={false}
+ />
+ }
+ />
+
+
+ {/* ----------- Adjustment ----------- */}
+
+
+
+
{taxEntries.map((tax, index) => (
{
};
/**
- * Retreives the bill total tax amount.
+ * Retrieves the bill discount amount.
+ * @returns {number}
+ */
+export const useBillDiscountAmount = () => {
+ const { values } = useFormikContext();
+
+ return toSafeNumber(values.discount);
+};
+
+/**
+ * Retrieves the bill adjustment amount.
+ * @returns {number}
+ */
+export const useBillAdjustmentAmount = () => {
+ const { values } = useFormikContext();
+
+ return toSafeNumber(values.adjustment);
+};
+
+/**
+ * Retrieves the bill total tax amount.
* @returns {number}
*/
export const useBillTotalTaxAmount = () => {
@@ -389,15 +410,19 @@ export const useIsBillTaxExclusive = () => {
};
/**
- * Retreives the bill total.
+ * Retrieves the bill total.
* @returns {number}
*/
export const useBillTotal = () => {
const subtotal = useBillSubtotal();
const totalTaxAmount = useBillTotalTaxAmount();
const isExclusiveTax = useIsBillTaxExclusive();
+ const discountAmount = useBillDiscountAmount();
+ const adjustmentAmount = useBillAdjustmentAmount();
- return R.compose(R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)))(
- subtotal,
- );
+ return R.compose(
+ R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)),
+ R.subtract(R.__, discountAmount),
+ R.subtract(R.__, adjustmentAmount),
+ )(subtotal);
};
diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx
index a4ce4c66a..cd5bf031f 100644
--- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx
+++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx
@@ -53,6 +53,9 @@ export const defaultVendorsCreditNote = {
currency_code: '',
entries: [...repeatValue(defaultCreditNoteEntry, MIN_LINES_NUMBER)],
attachments: [],
+ discount: '',
+ discount_type: 'amount',
+ adjustment: '',
};
/**
@@ -207,6 +210,75 @@ export const useVendorCrditNoteTotals = () => {
};
};
+/**
+ * Retrieves the vendor credit subtotal.
+ * @returns {number}
+ */
+export const useVendorCreditSubtotal = () => {
+ const {
+ values: { entries },
+ } = useFormikContext();
+
+ // Retrieves the invoice entries total.
+ const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
+
+ return total;
+};
+
+/**
+ * Retrieves the vendor credit discount amount.
+ * @returns {number}
+ */
+export const useVendorCreditDiscountAmount = () => {
+ const { values } = useFormikContext();
+
+ return toSafeNumber(values.discount);
+};
+
+/**
+ * Retrieves the vendor credit adjustment amount.
+ * @returns {number}
+ */
+export const useVendorCreditAdjustment = () => {
+ const { values } = useFormikContext();
+
+ return toSafeNumber(values.adjustment);
+};
+
+/**
+ * Retrieves the vendor credit total.
+ * @returns {number}
+ */
+export const useVendorCreditTotal = () => {
+ const subtotal = useVendorCreditSubtotal();
+ const discountAmount = useVendorCreditDiscountAmount();
+ const adjustment = useVendorCreditAdjustment();
+
+ return subtotal - discountAmount - adjustment;
+};
+
+/**
+ * Retrieves the vendor credit formatted total.
+ * @returns {string}
+ */
+export const useVendorCreditFormattedTotal = () => {
+ const total = useVendorCreditTotal();
+ const currencyCode = useCurrentOrganizationCurrencyCode();
+
+ return formattedAmount(total, currencyCode);
+};
+
+/**
+ * Retrieves the vendor credit formatted subtotal.
+ * @returns {string}
+ */
+export const useVendorCreditFormattedSubtotal = () => {
+ const subtotal = useVendorCreditSubtotal();
+ const currencyCode = useCurrentOrganizationCurrencyCode();
+
+ return formattedAmount(subtotal, currencyCode);
+};
+
/**
* Detarmines whether the vendor note has foreign customer.
* @returns {boolean}
diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.tsx
index 7aa4a9fea..4e245e030 100644
--- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.tsx
+++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.tsx
@@ -1,28 +1,61 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
+import { Button } from '@blueprintjs/core';
import {
T,
TotalLines,
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
+ FInputGroup,
+ FFormGroup,
+ FSelect,
} from '@/components';
-import { useCreditNoteTotals } from './utils';
+import {
+ useCreditNoteSubtotalFormatted,
+ useCreditNoteTotalFormatted,
+} from './utils';
export function CreditNoteFormFooterRight() {
- const { formattedSubtotal, formattedTotal } = useCreditNoteTotals();
+ const subtotalFormatted = useCreditNoteSubtotalFormatted();
+ const totalFormatted = useCreditNoteTotalFormatted();
return (
}
- value={formattedSubtotal}
+ value={subtotalFormatted}
borderStyle={TotalLineBorderStyle.None}
/>
+
+ (
+
+ )}
+ filterable={false}
+ />
+ }
+ />
+
+
+
+
+
+
}
- value={formattedTotal}
+ value={totalFormatted}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/components.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/components.tsx
index afe139f48..ed1aafe3d 100644
--- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/components.tsx
+++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/components.tsx
@@ -4,7 +4,7 @@ import { useFormikContext } from 'formik';
import * as R from 'ramda';
import { ExchangeRateInputGroup } from '@/components';
import { useCurrentOrganization } from '@/hooks/state';
-import { useCreditNoteIsForeignCustomer, useCreditNoteTotals } from './utils';
+import { useCreditNoteIsForeignCustomer, useCreditNoteSubtotal } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import { transactionNumber } from '@/utils';
import {
@@ -78,13 +78,13 @@ export const CreditNoteSyncIncrementSettingsToForm = R.compose(
*/
export const CreditNoteExchangeRateSync = R.compose(withDialogActions)(
({ openDialog }) => {
- const { total } = useCreditNoteTotals();
+ const subtotal = useCreditNoteSubtotal();
const timeout = useRef();
useSyncExRateToForm({
onSynced: () => {
// If the total bigger then zero show alert to the user after adjusting entries.
- if (total > 0) {
+ if (subtotal > 0) {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => {
openDialog(DialogsName.InvoiceExchangeRateChangeNotice);
diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx
index fad59288f..4ebf087cc 100644
--- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx
+++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx
@@ -10,6 +10,7 @@ import {
repeatValue,
formattedAmount,
orderingLinesIndexes,
+ toSafeNumber,
} from '@/utils';
import { useFormikContext } from 'formik';
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
@@ -57,6 +58,9 @@ export const defaultCreditNote = {
entries: [...repeatValue(defaultCreditNoteEntry, MIN_LINES_NUMBER)],
attachments: [],
pdf_template_id: '',
+ discount: '',
+ discount_type: 'amount',
+ adjustment: '',
};
/**
@@ -174,32 +178,74 @@ export const useSetPrimaryWarehouseToForm = () => {
};
/**
- * Retreives the credit note totals.
+ * Retrieves the credit note subtotal.
+ * @returns {number}
*/
-export const useCreditNoteTotals = () => {
+export const useCreditNoteSubtotal = () => {
const {
- values: { entries, currency_code: currencyCode },
+ values: { entries },
} = useFormikContext();
-
- // Retrieves the invoice entries total.
const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
- // Retrieves the formatted total money.
- const formattedTotal = React.useMemo(
- () => formattedAmount(total, currencyCode),
- [total, currencyCode],
- );
- // Retrieves the formatted subtotal.
- const formattedSubtotal = React.useMemo(
- () => formattedAmount(total, currencyCode, { money: false }),
- [total, currencyCode],
- );
+ return total;
+};
- return {
- total,
- formattedTotal,
- formattedSubtotal,
- };
+/**
+ * Retrieves the credit note subtotal formatted.
+ * @returns {string}
+ */
+export const useCreditNoteSubtotalFormatted = () => {
+ const subtotal = useCreditNoteSubtotal();
+ const { currency_code: currencyCode } = useFormikContext();
+
+ return formattedAmount(subtotal, currencyCode, { money: false });
+};
+
+/**
+ * Retrieves the credit note discount amount.
+ * @returns {number}
+ */
+export const useCreditNoteDiscountAmount = () => {
+ const { values } = useFormikContext();
+ const subtotal = useCreditNoteSubtotal();
+ const discount = toSafeNumber(values.discount);
+
+ return values?.discount_type === 'percentage'
+ ? (discount * subtotal) / 100
+ : discount;
+};
+
+/**
+ * Retrieves the credit note adjustment amount.
+ * @returns {number}
+ */
+export const useCreditNoteAdjustmentAmount = () => {
+ const { values } = useFormikContext();
+
+ return toSafeNumber(values.adjustment);
+};
+
+/**
+ * Retrieves the credit note total.
+ * @returns {number}
+ */
+export const useCreditNoteTotal = () => {
+ const subtotal = useCreditNoteSubtotal();
+ const discountAmount = useCreditNoteDiscountAmount();
+ const adjustmentAmount = useCreditNoteAdjustmentAmount();
+
+ return subtotal - discountAmount - adjustmentAmount;
+};
+
+/**
+ * Retrieves the credit note total formatted.
+ * @returns {string}
+ */
+export const useCreditNoteTotalFormatted = () => {
+ const total = useCreditNoteTotal();
+ const { currency_code: currencyCode } = useFormikContext();
+
+ return formattedAmount(total, currencyCode);
};
/**
@@ -217,7 +263,6 @@ export const useCreditNoteIsForeignCustomer = () => {
return isForeignCustomer;
};
-
export const useCreditNoteFormBrandingTemplatesOptions = () => {
const { brandingTemplates } = useCreditNoteFormContext();
diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx
index 93135fdd2..3b157d3fd 100644
--- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx
+++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx
@@ -7,8 +7,12 @@ import {
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
+ FInputGroup,
+ FFormGroup,
+ FSelect,
} from '@/components';
import { useEstimateTotals } from './utils';
+import { Button } from '@blueprintjs/core';
export function EstimateFormFooterRight() {
const { formattedSubtotal, formattedTotal } = useEstimateTotals();
@@ -20,6 +24,32 @@ export function EstimateFormFooterRight() {
value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
+
+
+ (
+
+ )}
+ filterable={false}
+ />
+ }
+ />
+
+
+
+
+
+
}
value={formattedTotal}
diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx
index 355c7619e..95c926446 100644
--- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx
+++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx
@@ -63,6 +63,8 @@ export const defaultEstimate = {
entries: [...repeatValue(defaultEstimateEntry, MIN_LINES_NUMBER)],
attachments: [],
pdf_template_id: '',
+ discount: '',
+ discount_type: 'amount'
};
const ERRORS = {
diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx
index 68bc36872..950575c15 100644
--- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx
+++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx
@@ -9,6 +9,9 @@ import {
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
+ FFormGroup,
+ FInputGroup,
+ FSelect,
} from '@/components';
import { useInvoiceAggregatedTaxRates } from './utils';
import { TaxType } from '@/interfaces/TaxRates';
@@ -18,6 +21,7 @@ import {
InvoiceSubTotalFormatted,
InvoiceTotalFormatted,
} from './components';
+import { Button } from '@blueprintjs/core';
export function InvoiceFormFooterRight() {
const {
@@ -38,6 +42,31 @@ export function InvoiceFormFooterRight() {
}
value={}
/>
+
+ (
+
+ )}
+ filterable={false}
+ />
+ }
+ />
+
+
+
+
+
+
{taxEntries.map((tax, index) => (
{
return React.useMemo(() => getEntriesTotal(entries), [entries]);
};
+/**
+ * Retrieves the invoice discount amount.
+ * @returns {number}
+ */
+export const useInvoiceDiscountAmount = () => {
+ const { values } = useFormikContext();
+ const subtotal = useInvoiceSubtotal();
+ const discount = parseFloat(values.discount);
+
+ return values?.discount_type === 'percentage'
+ ? (subtotal * discount) / 100
+ : discount;
+};
+
/**
* Detarmines whether the invoice has foreign customer.
* @returns {boolean}
@@ -382,10 +399,12 @@ export const useInvoiceTotal = () => {
const subtotal = useInvoiceSubtotal();
const totalTaxAmount = useInvoiceTotalTaxAmount();
const isExclusiveTax = useIsInvoiceTaxExclusive();
+ const discountAmount = useInvoiceDiscountAmount();
- return R.compose(R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)))(
- subtotal,
- );
+ return R.compose(
+ R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)),
+ R.subtract(R.__, discountAmount),
+ )(subtotal);
};
/**
diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.tsx
index 87f4bb896..76c2698d3 100644
--- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.tsx
+++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.tsx
@@ -8,8 +8,12 @@ import {
TotalLine,
TotalLineBorderStyle,
TotalLineTextStyle,
+ FInputGroup,
+ FFormGroup,
+ FSelect,
} from '@/components';
import { useReceiptTotals } from './utils';
+import { Button } from '@blueprintjs/core';
export function ReceiptFormFooterRight() {
const {
@@ -26,6 +30,31 @@ export function ReceiptFormFooterRight() {
value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
+
+ (
+
+ )}
+ filterable={false}
+ />
+ }
+ />
+
+
+
+
+
+
}
value={formattedTotal}