diff --git a/package.json b/package.json index f8c9ed2ca..c36506c7b 100644 --- a/package.json +++ b/package.json @@ -202,6 +202,7 @@ "*.fixture.ts", "*.fixture.tsx", "src/EventsEnums.ts", + "src/FeaturesEnums.ts", "src/core/draftjs-module.tsx" ] }, diff --git a/src/invoices/details/BillingRecordDetails.tsx b/src/invoices/details/BillingRecordDetails.tsx index dcfb637c5..6fa90017d 100644 --- a/src/invoices/details/BillingRecordDetails.tsx +++ b/src/invoices/details/BillingRecordDetails.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, useState } from 'react'; import { defaultCurrency } from '@waldur/core/formatCurrency'; import { translate } from '@waldur/i18n'; @@ -16,16 +16,30 @@ export const BillingRecordDetails: FC = ({ invoice, refreshInvoiceItems, }) => { + const [totalFiltered, setTotalFiltered] = useState(null); + return ( + {totalFiltered !== null && ( + + {translate('Total filtered')}{' '} + {translate('(VAT is not included)')} + {': '} + + {defaultCurrency(totalFiltered)} + + + )} + {translate('Total')}{' '} {translate('(VAT is not included)')}: diff --git a/src/invoices/details/InvoiceDetails.tsx b/src/invoices/details/InvoiceDetails.tsx index bf7f2c7c8..89f1ec719 100644 --- a/src/invoices/details/InvoiceDetails.tsx +++ b/src/invoices/details/InvoiceDetails.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import { Card, Col, Row } from 'react-bootstrap'; import { useSelector } from 'react-redux'; @@ -24,6 +25,8 @@ export const InvoiceDetails = ({ customer.payment_profiles, ); + const [totalFiltered, setTotalFiltered] = useState(null); + return ( <> @@ -62,11 +65,22 @@ export const InvoiceDetails = ({ refreshInvoiceItems={refreshInvoiceItems} showPrice={showPrice} showVat={Boolean(invoice.issuer_details.vat_code)} + setTotalFiltered={setTotalFiltered} footer={ showPrice && ( + {totalFiltered !== null && ( + + )} + @@ -78,7 +92,10 @@ export const InvoiceDetails = ({ - -
+ {translate('Total filtered')} + {': '} + + {defaultCurrency(totalFiltered)} + + {translate('Subtotal')}:
+ {translate('Tax')}:
+ {translate('Total')}: = ({ showVat, footer, refreshInvoiceItems, + setTotalFiltered, }) => { const filter = useFilters(); const customer = useSelector(getCustomer); @@ -66,14 +72,25 @@ export const InvoiceItemsTable: FC = ({ const providerUuid = request.filter?.provider_uuid; const projectUuid = request.filter?.project_uuid; - return Promise.resolve({ - rows: groupInvoiceItems(invoice.items).filter( - (item) => - (!query || item.resource_name.includes(query)) && - (!providerUuid || item.service_provider_uuid === providerUuid) && - (!projectUuid || item.project_uuid === projectUuid), - ), - }); + const rows = groupInvoiceItems(invoice.items).filter( + (item) => + (!query || item.resource_name.includes(query)) && + (!providerUuid || item.service_provider_uuid === providerUuid) && + (!projectUuid || item.project_uuid === projectUuid), + ); + + if (setTotalFiltered) { + if (query || providerUuid || projectUuid) { + const totalFiltered = invoiceView + ? rows.reduce((acc, item) => acc + item.total, 0) + : rows.reduce((acc, item) => acc + item.price, 0); + setTotalFiltered(totalFiltered); + } else { + setTotalFiltered(null); + } + } + + return Promise.resolve({ rows }); }, queryField: 'query', filter, @@ -115,13 +132,26 @@ export const InvoiceItemsTable: FC = ({ { title: ( <> - {translate('Total')} + {translate('Price')} ), - render: ({ row }) => <>{defaultCurrency(row.total)}, - className: 'w-150px', + render: ({ row }) => <>{defaultCurrency(row.price)}, + className: invoiceView ? undefined : 'w-150px', }, + ...(invoiceView + ? [ + { + title: translate('Tax'), + render: ({ row }) => <>{defaultCurrency(row.tax)}, + }, + { + title: translate('Total'), + render: ({ row }) => <>{defaultCurrency(row.total)}, + className: 'w-150px', + }, + ] + : []), ]} title={
diff --git a/src/invoices/details/utils.ts b/src/invoices/details/utils.ts index 42b138d61..eb1ddbb38 100644 --- a/src/invoices/details/utils.ts +++ b/src/invoices/details/utils.ts @@ -25,11 +25,15 @@ export const groupInvoiceItems = (items: InvoiceItem[]): InvoiceTableItem[] => { service_provider_name: item.details.service_provider_name, service_provider_uuid: item.details.service_provider_uuid, plan_name: item.details.plan_name, + price: 0, + tax: 0, total: 0, items: [] as InvoiceItem[], }; } + acc[key].price += Number(item.price); + acc[key].tax += Number(item.tax); acc[key].total += Number(item.total); acc[key].items.push(item); diff --git a/src/invoices/types.ts b/src/invoices/types.ts index ae71b5602..076feec84 100644 --- a/src/invoices/types.ts +++ b/src/invoices/types.ts @@ -51,7 +51,9 @@ export interface InvoiceTableItem { service_provider_name: string; service_provider_uuid: string; plan_name: string; - total: 0; + price: number; + tax: number; + total: number; items: InvoiceItem[]; } diff --git a/template.json b/template.json index 3d6eedfc9..6f5d6b7ff 100644 --- a/template.json +++ b/template.json @@ -703,6 +703,10 @@ "description": "features/FeaturesDescription.ts", "message": "Allow marketplace to function as a catalogue only." }, + "Allow marketplace to serve only as aggregator of call info.": { + "description": "features/FeaturesDescription.ts", + "message": "Allow marketplace to serve only as aggregator of call info." + }, "Allow to enable/disable component only": { "description": "marketplace/offerings/update/components/ComponentBooleanLimitField.tsx", "message": "Allow to enable/disable component only" @@ -5835,6 +5839,10 @@ "description": "resource/summary/ResourceMetadataDialog.tsx", "message": "Marketplace UUID" }, + "Marketplace landing page title.": { + "description": "SettingsDescription.ts", + "message": "Marketplace landing page title." + }, "Marketplace offering": { "description": "marketplace/offerings/OfferingViewHero.tsx", "message": "Marketplace offering" @@ -8028,7 +8036,7 @@ "message": "Price per year" }, "Price": { - "description": "invoices/list/InvoicesList.tsx, marketplace/offerings/PriceList.tsx, marketplace/resources/change-plan/utils.tsx", + "description": "invoices/details/InvoiceItemsTable.tsx, invoices/list/InvoicesList.tsx, marketplace/offerings/PriceList.tsx, marketplace/resources/change-plan/utils.tsx", "message": "Price" }, "Pricelist": { @@ -11192,7 +11200,7 @@ "message": "Tax percentage" }, "Tax": { - "description": "customer/details/CustomerBillingPanel.tsx, invoices/details/InvoiceDetails.tsx, invoices/details/InvoiceItemExpandableRow.tsx, invoices/list/InvoicesList.tsx", + "description": "customer/details/CustomerBillingPanel.tsx, invoices/details/InvoiceDetails.tsx, invoices/details/InvoiceItemExpandableRow.tsx, invoices/details/InvoiceItemsTable.tsx, invoices/list/InvoicesList.tsx", "message": "Tax" }, "Team invitations": { @@ -11847,6 +11855,10 @@ "description": "customer/list/TotalCostField.tsx", "message": "Total cost:" }, + "Total filtered": { + "description": "invoices/details/BillingRecordDetails.tsx, invoices/details/InvoiceDetails.tsx", + "message": "Total filtered" + }, "Total for the year": { "description": "customer/credits/CreditFormDialog.tsx", "message": "Total for the year"