From 000c3e40e13ad9580d6de103ca62d829ead6fa51 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 1 Dec 2024 17:59:01 +0200 Subject: [PATCH] feat: enhance discount handling in financial forms - Implemented discount and adjustment fields in Bill, Credit Note, Estimate, Invoice, and Receipt forms. - Created new components for displaying discount and adjustment totals, improving clarity in financial documents. - Updated utility functions to format discount and adjustment amounts consistently across various forms. - Enhanced user experience by integrating discount functionality into the form context, allowing for better data management and display. This update improves the overall functionality and user experience related to discounts in financial transactions. --- .../src/components/TotalLines/index.tsx | 20 +++- .../Bills/BillForm/BillFormFooterRight.tsx | 63 ++++------- .../Purchases/Bills/BillForm/utils.tsx | 51 +++++++++ .../VendorCreditNoteFormFooterRight.tsx | 35 ++++-- .../CreditNotes/CreditNoteForm/utils.tsx | 48 +++++++- .../CreditNoteFormFooterRight.tsx | 47 +++----- .../CreditNotes/CreditNoteForm/utils.tsx | 38 ++++++- .../Estimates/EstimateForm/EstimateForm.tsx | 2 +- .../EstimateForm/EstimateFormFooterRight.tsx | 56 +++------- .../Sales/Estimates/EstimateForm/utils.tsx | 103 +++++++++++++++++- .../InvoiceForm/AdjustmentTotalLine.tsx | 75 +++++++++++++ .../InvoiceForm/DiscountTotalLine.tsx | 91 ++++++++++++++++ .../InvoiceForm/InvoiceFormFooterRight.tsx | 44 +++----- .../Sales/Invoices/InvoiceForm/utils.tsx | 38 +++++++ .../ReceiptFormFloatingActions.tsx | 1 + .../ReceiptForm/ReceiptFormFooterRight.tsx | 52 ++++----- .../Sales/Receipts/ReceiptForm/utils.tsx | 74 +++++++++++++ 17 files changed, 644 insertions(+), 194 deletions(-) create mode 100644 packages/webapp/src/containers/Sales/Invoices/InvoiceForm/AdjustmentTotalLine.tsx create mode 100644 packages/webapp/src/containers/Sales/Invoices/InvoiceForm/DiscountTotalLine.tsx diff --git a/packages/webapp/src/components/TotalLines/index.tsx b/packages/webapp/src/components/TotalLines/index.tsx index ae97abd45..cc9379fe1 100644 --- a/packages/webapp/src/components/TotalLines/index.tsx +++ b/packages/webapp/src/components/TotalLines/index.tsx @@ -1,7 +1,7 @@ // @ts-nocheck import React from 'react'; import styled from 'styled-components'; - +import { x } from '@xstyled/emotion'; export const TotalLineBorderStyle = { None: 'None', SingleDark: 'SingleDark', @@ -32,14 +32,14 @@ export function TotalLines({ export function TotalLine({ title, value, borderStyle, textStyle, className }) { return ( -
{title}
{value}
-
+ ); } @@ -63,7 +63,7 @@ export const TotalLinesRoot = styled.div` `} `; -export const TotalLineRoot = styled.div` +export const TotalLinePrimitive = styled.div` display: table-row; .amount, @@ -96,5 +96,17 @@ export const TotalLineRoot = styled.div` .amount { text-align: right; + width: 25%; } `; + +const TotalLineAmount = (props) => { + return ; +}; + +export const TotalLineTitle = (props) => { + return ; +}; + +TotalLinePrimitive.Amount = TotalLineAmount; +TotalLinePrimitive.Title = TotalLineTitle; diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx index 5300bb9ed..48cef6c72 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.tsx @@ -1,23 +1,26 @@ // @ts-nocheck import styled from 'styled-components'; +import { useFormikContext } from 'formik'; import { TotalLines, TotalLine, TotalLineBorderStyle, TotalLineTextStyle, - FFormGroup, - FInputGroup, - FSelect, } from '@/components'; -import { useBillAggregatedTaxRates, useBillTotals } from './utils'; -import { useFormikContext } from 'formik'; +import { + useBillAdjustmentAmountFormatted, + useBillAggregatedTaxRates, + useBillDiscountAmountFormatted, + useBillSubtotalFormatted, + useBillTotalFormatted, + useBillTotals, +} from './utils'; import { TaxType } from '@/interfaces/TaxRates'; -import { Button } from '@blueprintjs/core'; +import { AdjustmentTotalLine } from '@/containers/Sales/Invoices/InvoiceForm/AdjustmentTotalLine'; +import { DiscountTotalLine } from '@/containers/Sales/Invoices/InvoiceForm/DiscountTotalLine'; export function BillFormFooterRight() { const { - formattedSubtotal, - formattedTotal, formattedDueTotal, formattedPaymentTotal, } = useBillTotals(); @@ -26,7 +29,11 @@ export function BillFormFooterRight() { values: { inclusive_exclusive_tax, currency_code }, } = useFormikContext(); + const subtotalFormatted = useBillSubtotalFormatted(); + const totalFormatted = useBillTotalFormatted(); const taxEntries = useBillAggregatedTaxRates(); + const discountAmount = useBillDiscountAmountFormatted(); + const adjustmentAmount = useBillAdjustmentAmountFormatted(); return ( @@ -38,37 +45,13 @@ export function BillFormFooterRight() { : 'Subtotal'} } - value={formattedSubtotal} - borderStyle={TotalLineBorderStyle.None} + value={subtotalFormatted} /> - - {/* ----------- Discount ----------- */} - - ( - - )} - filterable={false} - /> - } - /> - - - {/* ----------- Adjustment ----------- */} - - - - + + {taxEntries.map((tax, index) => ( ))} diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx index 933a4eb9f..5f7ac273e 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx @@ -66,6 +66,13 @@ export const defaultBill = { currency_code: '', entries: [...repeatValue(defaultBillEntry, MIN_LINES_NUMBER)], attachments: [], + + // Adjustment + adjustment: '', + + // Discount + discount: '', + discount_type: 'amount', }; export const ERRORS = { @@ -364,6 +371,17 @@ export const useBillSubtotal = () => { return React.useMemo(() => getEntriesTotal(entries), [entries]); }; +/** + * Retrieves the bill subtotal formatted. + * @returns {string} + */ +export const useBillSubtotalFormatted = () => { + const subtotal = useBillSubtotal(); + const { currency_code: currencyCode } = useFormikContext(); + + return formattedAmount(subtotal, currencyCode); +}; + /** * Retrieves the bill discount amount. * @returns {number} @@ -374,6 +392,17 @@ export const useBillDiscountAmount = () => { return toSafeNumber(values.discount); }; +/** + * Retrieves the bill discount amount formatted. + * @returns {string} + */ +export const useBillDiscountAmountFormatted = () => { + const discountAmount = useBillDiscountAmount(); + const { currency_code: currencyCode } = useFormikContext(); + + return formattedAmount(discountAmount, currencyCode); +}; + /** * Retrieves the bill adjustment amount. * @returns {number} @@ -384,6 +413,17 @@ export const useBillAdjustmentAmount = () => { return toSafeNumber(values.adjustment); }; +/** + * Retrieves the bill adjustment amount formatted. + * @returns {string} + */ +export const useBillAdjustmentAmountFormatted = () => { + const adjustmentAmount = useBillAdjustmentAmount(); + const { currency_code: currencyCode } = useFormikContext(); + + return formattedAmount(adjustmentAmount, currencyCode); +}; + /** * Retrieves the bill total tax amount. * @returns {number} @@ -426,3 +466,14 @@ export const useBillTotal = () => { R.subtract(R.__, adjustmentAmount), )(subtotal); }; + +/** + * Retrieves the bill total formatted. + * @returns {string} + */ +export const useBillTotalFormatted = () => { + const total = useBillTotal(); + const { currency_code: currencyCode } = useFormikContext(); + + return formattedAmount(total, currencyCode); +}; diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooterRight.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooterRight.tsx index 7d6faba57..410c9b148 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooterRight.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooterRight.tsx @@ -1,17 +1,26 @@ // @ts-nocheck import React from 'react'; import styled from 'styled-components'; +import { useFormikContext } from 'formik'; +import { T, TotalLines, TotalLine, TotalLineTextStyle } from '@/components'; import { - T, - TotalLines, - TotalLine, - TotalLineBorderStyle, - TotalLineTextStyle, -} from '@/components'; -import { useVendorCrditNoteTotals } from './utils'; + useVendorCreditAdjustmentAmountFormatted, + useVendorCreditDiscountAmount, + useVendorCreditSubtotalFormatted, + useVendorCreditTotalFormatted, +} from './utils'; +import { DiscountTotalLine } from '@/containers/Sales/Invoices/InvoiceForm/DiscountTotalLine'; +import { AdjustmentTotalLine } from '@/containers/Sales/Invoices/InvoiceForm/AdjustmentTotalLine'; export function VendorCreditNoteFormFooterRight() { - const { formattedSubtotal, formattedTotal } = useVendorCrditNoteTotals(); + const { + values: { currency_code }, + } = useFormikContext(); + const totalFormatted = useVendorCreditTotalFormatted(); + const subtotalFormatted = useVendorCreditSubtotalFormatted(); + + const discountAmount = useVendorCreditDiscountAmount(); + const adjustmentAmount = useVendorCreditAdjustmentAmountFormatted(); return ( } - value={formattedSubtotal} - borderStyle={TotalLineBorderStyle.None} + value={subtotalFormatted} /> + + } - value={formattedTotal} + value={totalFormatted} textStyle={TotalLineTextStyle.Bold} /> diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx index cd5bf031f..74300e466 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx @@ -11,6 +11,7 @@ import { transactionNumber, orderingLinesIndexes, formattedAmount, + toSafeNumber, } from '@/utils'; import { updateItemsEntriesTotal, @@ -235,6 +236,19 @@ export const useVendorCreditDiscountAmount = () => { return toSafeNumber(values.discount); }; +/** + * Retrieves the vendor credit discount amount formatted. + * @returns {string} + */ +export const useVendorCreditDiscountAmountFormatted = () => { + const discountAmount = useVendorCreditDiscountAmount(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(discountAmount, currencyCode); +}; + /** * Retrieves the vendor credit adjustment amount. * @returns {number} @@ -245,6 +259,19 @@ export const useVendorCreditAdjustment = () => { return toSafeNumber(values.adjustment); }; +/** + * Retrieves the vendor credit adjustment amount formatted. + * @returns {string} + */ +export const useVendorCreditAdjustmentAmountFormatted = () => { + const adjustmentAmount = useVendorCreditAdjustment(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(adjustmentAmount, currencyCode); +}; + /** * Retrieves the vendor credit total. * @returns {number} @@ -258,12 +285,14 @@ export const useVendorCreditTotal = () => { }; /** - * Retrieves the vendor credit formatted total. + * Retrieves the vendor credit total formatted. * @returns {string} */ -export const useVendorCreditFormattedTotal = () => { +export const useVendorCreditTotalFormatted = () => { const total = useVendorCreditTotal(); - const currencyCode = useCurrentOrganizationCurrencyCode(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); return formattedAmount(total, currencyCode); }; @@ -279,6 +308,19 @@ export const useVendorCreditFormattedSubtotal = () => { return formattedAmount(subtotal, currencyCode); }; +/** + * Retrieves the vendor credit formatted subtotal. + * @returns {string} + */ +export const useVendorCreditSubtotalFormatted = () => { + const subtotal = useVendorCreditSubtotal(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + 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 4e245e030..e6b381283 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.tsx @@ -1,58 +1,45 @@ // @ts-nocheck import React from 'react'; import styled from 'styled-components'; -import { Button } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; import { T, TotalLines, TotalLine, TotalLineBorderStyle, TotalLineTextStyle, - FInputGroup, - FFormGroup, - FSelect, } from '@/components'; import { + useCreditNoteAdjustmentFormatted, + useCreditNoteDiscountAmountFormatted, useCreditNoteSubtotalFormatted, useCreditNoteTotalFormatted, } from './utils'; +import { DiscountTotalLine } from '../../Invoices/InvoiceForm/DiscountTotalLine'; +import { AdjustmentTotalLine } from '../../Invoices/InvoiceForm/AdjustmentTotalLine'; export function CreditNoteFormFooterRight() { + const { + values: { currency_code }, + } = useFormikContext(); + const subtotalFormatted = useCreditNoteSubtotalFormatted(); const totalFormatted = useCreditNoteTotalFormatted(); + const discountAmount = useCreditNoteDiscountAmountFormatted(); + const adjustmentAmount = useCreditNoteAdjustmentFormatted(); return ( } value={subtotalFormatted} - borderStyle={TotalLineBorderStyle.None} + borderStyle={TotalLineBorderStyle.BorderBottom} /> - - ( - - )} - filterable={false} - /> - } - /> - - - - - - + + } value={totalFormatted} diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx index 4ebf087cc..382b09b07 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx @@ -196,9 +196,11 @@ export const useCreditNoteSubtotal = () => { */ export const useCreditNoteSubtotalFormatted = () => { const subtotal = useCreditNoteSubtotal(); - const { currency_code: currencyCode } = useFormikContext(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); - return formattedAmount(subtotal, currencyCode, { money: false }); + return formattedAmount(subtotal, currencyCode, { money: true }); }; /** @@ -215,6 +217,19 @@ export const useCreditNoteDiscountAmount = () => { : discount; }; +/** + * Retrieves the credit note discount amount formatted. + * @returns {string} + */ +export const useCreditNoteDiscountAmountFormatted = () => { + const discountAmount = useCreditNoteDiscountAmount(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(discountAmount, currencyCode, { money: true }); +}; + /** * Retrieves the credit note adjustment amount. * @returns {number} @@ -225,6 +240,19 @@ export const useCreditNoteAdjustmentAmount = () => { return toSafeNumber(values.adjustment); }; +/** + * Retrieves the credit note adjustment amount formatted. + * @returns {string} + */ +export const useCreditNoteAdjustmentFormatted = () => { + const adjustmentAmount = useCreditNoteAdjustmentAmount(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(adjustmentAmount, currencyCode, { money: true }); +}; + /** * Retrieves the credit note total. * @returns {number} @@ -243,9 +271,11 @@ export const useCreditNoteTotal = () => { */ export const useCreditNoteTotalFormatted = () => { const total = useCreditNoteTotal(); - const { currency_code: currencyCode } = useFormikContext(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); - return formattedAmount(total, currencyCode); + return formattedAmount(total, currencyCode, { money: true }); }; /** diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx index a9dbbbf39..119553e25 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx @@ -177,7 +177,7 @@ function EstimateForm({ {/*------- Dialogs -------*/} - + {/* */} {/*------- Effects -------*/} diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx index 3b157d3fd..d61fc71c1 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.tsx @@ -1,55 +1,35 @@ // @ts-nocheck import React from 'react'; import styled from 'styled-components'; +import { useFormikContext } from 'formik'; +import { T, TotalLines, TotalLine, TotalLineTextStyle } from '@/components'; import { - T, - TotalLines, - TotalLine, - TotalLineBorderStyle, - TotalLineTextStyle, - FInputGroup, - FFormGroup, - FSelect, -} from '@/components'; -import { useEstimateTotals } from './utils'; -import { Button } from '@blueprintjs/core'; + useEstimateAdjustmentFormatted, + useEstimateDiscountFormatted, + useEstimateTotals, +} from './utils'; +import { AdjustmentTotalLine } from '../../Invoices/InvoiceForm/AdjustmentTotalLine'; +import { DiscountTotalLine } from '../../Invoices/InvoiceForm/DiscountTotalLine'; export function EstimateFormFooterRight() { const { formattedSubtotal, formattedTotal } = useEstimateTotals(); + const { + values: { currency_code }, + } = useFormikContext(); + const discountAmount = useEstimateDiscountFormatted(); + const adjustmentAmount = useEstimateAdjustmentFormatted(); return ( } 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 95c926446..6af7c4f3a 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx @@ -64,7 +64,7 @@ export const defaultEstimate = { attachments: [], pdf_template_id: '', discount: '', - discount_type: 'amount' + discount_type: 'amount', }; const ERRORS = { @@ -238,6 +238,107 @@ export const useEstimateTotals = () => { }; }; +/** + * Retrieves the estimate subtotal. + * @returns {number} + */ +export const useEstimateSubtotal = () => { + const { + values: { entries }, + } = useFormikContext(); + + // Retrieves the invoice entries total. + const total = React.useMemo(() => getEntriesTotal(entries), [entries]); + + return total; +}; + +/** + * Retrieves the estimate subtotal formatted. + * @returns {string} + */ +export const useEstimateSubtotalFormatted = () => { + const subtotal = useEstimateSubtotal(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(subtotal, currencyCode); +}; + +/** + * Retrieves the estimate discount amount. + * @returns {number} + */ +export const useEstimateDiscount = () => { + const { values } = useFormikContext(); + const discountAmount = parseFloat(values.discount); + + return discountAmount; +}; + +/** + * Retrieves the estimate discount formatted. + * @returns {string} + */ +export const useEstimateDiscountFormatted = () => { + const discount = useEstimateDiscount(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(discount, currencyCode); +}; + +/** + * Retrieves the estimate adjustment amount. + * @returns {number} + */ +export const useEstimateAdjustment = () => { + const { values } = useFormikContext(); + const adjustmentAmount = parseFloat(values.adjustment); + + return adjustmentAmount; +}; + +/** + * Retrieves the estimate adjustment formatted. + * @returns {string} + */ +export const useEstimateAdjustmentFormatted = () => { + const adjustment = useEstimateAdjustment(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(adjustment, currencyCode); +}; + +/** + * Retrieves the estimate total. + * @returns {number} + */ +export const useEstimateTotal = () => { + const subtotal = useEstimateSubtotal(); + const discount = useEstimateDiscount(); + const adjustment = useEstimateAdjustment(); + + return subtotal - discount - adjustment; +}; + +/** + * Retrieves the estimate total formatted. + * @returns {string} + */ +export const useEstimateTotalFormatted = () => { + const total = useEstimateTotal(); + const { + values: { currency_code: currencyCode }, + } = useFormikContext(); + + return formattedAmount(total, currencyCode); +}; + /** * Detarmines whether the estimate has foreign customer. * @returns {boolean} diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/AdjustmentTotalLine.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/AdjustmentTotalLine.tsx new file mode 100644 index 000000000..36f533909 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/AdjustmentTotalLine.tsx @@ -0,0 +1,75 @@ +// @ts-nocheck +import { css } from '@emotion/css'; +import { x } from '@xstyled/emotion'; +import clsx from 'classnames'; +import { + FFormGroup, + FInputGroup, + TotalLinePrimitive, +} from '@/components'; + +const inputGroupCss = css` + & .bp4-input { + max-width: 110px; + color: rgb(17, 17, 17); + padding-left: 8px; + } +`; +const formGroupCss = css` + margin-bottom: 0; +`; + +interface AdjustmentTotalLineProps { + adjustmentAmount: number; +} + +export function AdjustmentTotalLine({ + adjustmentAmount, +}: AdjustmentTotalLineProps) { + return ( + + + + Adjustment + + + + + + + + {adjustmentAmount} + + + ); +} diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/DiscountTotalLine.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/DiscountTotalLine.tsx new file mode 100644 index 000000000..a2a1d84dc --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/DiscountTotalLine.tsx @@ -0,0 +1,91 @@ +// @ts-nocheck +import { css } from '@emotion/css'; +import { x } from '@xstyled/emotion'; +import { + FFormGroup, + FInputGroup, + FSelect, + TotalLinePrimitive, +} from '@/components'; +import { Button } from '@blueprintjs/core'; + +const inputGroupCss = css` + & .bp4-input { + max-width: 110px; + color: rgb(17, 17, 17); + padding-left: 8px; + } +`; +const formGroupCss = css` + margin-bottom: 0; +`; + +interface DiscountTotalLineProps { + currencyCode: string; + discountAmount: number; +} + +export function DiscountTotalLine({ + currencyCode, + discountAmount, +}: DiscountTotalLineProps) { + const discountButtonInput = ({ text }) => ( + + ); + + const discountTypeItems = [ + { text: currencyCode, value: 'amount', label: 'Fixed Amount' }, + { text: '%', value: 'percentage', label: 'Percentage' }, + ]; + + return ( + + + + Discount + + + } + fastField + className={inputGroupCss} + /> + + + + + + {discountAmount} + + + ); +} diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx index 950575c15..f6439f668 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx @@ -2,18 +2,18 @@ import React from 'react'; import styled from 'styled-components'; import { useFormikContext } from 'formik'; - import { T, TotalLines, TotalLine, TotalLineBorderStyle, TotalLineTextStyle, - FFormGroup, - FInputGroup, - FSelect, } from '@/components'; -import { useInvoiceAggregatedTaxRates } from './utils'; +import { + useInvoiceAdjustmentAmountFormatted, + useInvoiceAggregatedTaxRates, + useInvoiceDiscountAmountFormatted, +} from './utils'; import { TaxType } from '@/interfaces/TaxRates'; import { InvoiceDueAmountFormatted, @@ -21,7 +21,8 @@ import { InvoiceSubTotalFormatted, InvoiceTotalFormatted, } from './components'; -import { Button } from '@blueprintjs/core'; +import { AdjustmentTotalLine } from './AdjustmentTotalLine'; +import { DiscountTotalLine } from './DiscountTotalLine'; export function InvoiceFormFooterRight() { const { @@ -29,6 +30,8 @@ export function InvoiceFormFooterRight() { } = useFormikContext(); const taxEntries = useInvoiceAggregatedTaxRates(); + const adjustmentAmount = useInvoiceAdjustmentAmountFormatted(); + const discountAmount = useInvoiceDiscountAmountFormatted(); return ( @@ -42,30 +45,11 @@ export function InvoiceFormFooterRight() { } value={} /> - - ( - - )} - filterable={false} - /> - } - /> - - - - - + + {taxEntries.map((tax, index) => ( { : discount; }; +/** + * Retrieves the invoice discount amount formatted. + * @returns {string} + */ +export const useInvoiceDiscountAmountFormatted = () => { + const discountAmount = useInvoiceDiscountAmount(); + const { + values: { currency_code }, + } = useFormikContext(); + + return formattedAmount(discountAmount, currency_code); +}; + +/** + * Retrieves the invoice adjustment amount. + * @returns {number} + */ +export const useInvoiceAdjustmentAmount = () => { + const { values } = useFormikContext(); + const adjustment = parseFloat(values.adjustment); + + return adjustment; +}; + +/** + * Retrieves the invoice adjustment amount formatted. + * @returns {string} + */ +export const useInvoiceAdjustmentAmountFormatted = () => { + const adjustmentAmount = useInvoiceAdjustmentAmount(); + const { + values: { currency_code }, + } = useFormikContext(); + + return formattedAmount(adjustmentAmount, currency_code); +}; + /** * Detarmines whether the invoice has foreign customer. * @returns {boolean} diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx index 0b49d5a53..15792a5f4 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx @@ -129,6 +129,7 @@ export default function ReceiptFormFloatingActions() { /> + {/* ----------- Save As Draft ----------- */} - )} - filterable={false} - /> - } - /> - - - - - - + + } value={formattedTotal} diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx index eaecd2ae5..656fd41a9 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx @@ -10,6 +10,7 @@ import { repeatValue, transformToForm, formattedAmount, + toSafeNumber, } from '@/utils'; import { useReceiptFormContext } from './ReceiptFormProvider'; import { @@ -63,6 +64,9 @@ export const defaultReceipt = { entries: [...repeatValue(defaultReceiptEntry, MIN_LINES_NUMBER)], attachments: [], pdf_template_id: '', + discount: '', + discount_type: 'amount', + adjustment: '', }; const ERRORS = { @@ -249,6 +253,76 @@ export const useReceiptTotals = () => { }; }; +/** + * Retrieves the receipt subtotal. + * @returns {number} + */ +export const useReceiptSubtotal = () => { + const { + values: { entries }, + } = useFormikContext(); + + // Retrieves the invoice entries total. + const subtotal = React.useMemo(() => getEntriesTotal(entries), [entries]); + + return subtotal; +}; + +/** + * Retrieves the formatted discount amount. + * @returns {string} + */ +export const useReceiptDiscountAmountFormatted = () => { + const { values } = useFormikContext(); + + return formattedAmount(values.discount, values.currency_code); +}; + +/** + * Retrieves the receipt adjustment amount. + * @returns {number} + */ +export const useReceiptAdjustmentAmount = () => { + const { values } = useFormikContext(); + const adjustment = toSafeNumber(values.adjustment); + + return adjustment; +}; + +/** + * Retrieves the formatted adjustment amount. + * @returns {string} + */ +export const useReceiptAdjustmentFormatted = () => { + const { values } = useFormikContext(); + const adjustment = useReceiptAdjustmentAmount(); + + return formattedAmount(adjustment, values.currency_code); +}; + +/** + * Retrieves the receipt total. + * @returns {number} + */ +export const useReceiptTotal = () => { + const subtotal = useReceiptSubtotal(); + const adjustmentAmount = useReceiptAdjustmentAmount(); + const discountAmount = useReceiptDiscountAmount(); + + return subtotal - discountAmount + adjustmentAmount; +}; + +/** + * Retrieves the formatted receipt total. + * @returns {string} + */ +export const useReceiptTotalFormatted = () => { + const total = useReceiptTotal(); + const { values } = useFormikContext(); + + return formattedAmount(total, values.currency_code); +}; + /** * Detarmines whether the receipt has foreign customer. * @returns {boolean}