@spaceinvoices/react-ui 0.4.12 → 0.4.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/common/autocomplete.tsx +7 -1
- package/src/components/advance-invoices/advance-invoices.hooks.ts +35 -44
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +189 -73
- package/src/components/advance-invoices/create/locales/bg.ts +17 -9
- package/src/components/advance-invoices/create/locales/cs.ts +17 -9
- package/src/components/advance-invoices/create/locales/de.ts +15 -7
- package/src/components/advance-invoices/create/locales/en.ts +15 -7
- package/src/components/advance-invoices/create/locales/es.ts +15 -7
- package/src/components/advance-invoices/create/locales/et.ts +17 -9
- package/src/components/advance-invoices/create/locales/fi.ts +18 -10
- package/src/components/advance-invoices/create/locales/fr.ts +16 -8
- package/src/components/advance-invoices/create/locales/hr.ts +15 -7
- package/src/components/advance-invoices/create/locales/is.ts +17 -9
- package/src/components/advance-invoices/create/locales/it.ts +15 -7
- package/src/components/advance-invoices/create/locales/nb.ts +17 -9
- package/src/components/advance-invoices/create/locales/nl.ts +15 -7
- package/src/components/advance-invoices/create/locales/pl.ts +17 -9
- package/src/components/advance-invoices/create/locales/pt.ts +16 -8
- package/src/components/advance-invoices/create/locales/sk.ts +17 -9
- package/src/components/advance-invoices/create/locales/sl.ts +14 -5
- package/src/components/advance-invoices/create/locales/sv.ts +17 -9
- package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +47 -1
- package/src/components/advance-invoices/list/list-table.tsx +2 -1
- package/src/components/credit-notes/create/create-credit-note-form.tsx +253 -85
- package/src/components/credit-notes/create/locales/bg.ts +22 -8
- package/src/components/credit-notes/create/locales/cs.ts +22 -8
- package/src/components/credit-notes/create/locales/de.ts +20 -7
- package/src/components/credit-notes/create/locales/en.ts +19 -5
- package/src/components/credit-notes/create/locales/es.ts +20 -7
- package/src/components/credit-notes/create/locales/et.ts +22 -8
- package/src/components/credit-notes/create/locales/fi.ts +23 -9
- package/src/components/credit-notes/create/locales/fr.ts +21 -8
- package/src/components/credit-notes/create/locales/hr.ts +20 -7
- package/src/components/credit-notes/create/locales/is.ts +22 -8
- package/src/components/credit-notes/create/locales/it.ts +20 -7
- package/src/components/credit-notes/create/locales/nb.ts +22 -8
- package/src/components/credit-notes/create/locales/nl.ts +20 -7
- package/src/components/credit-notes/create/locales/pl.ts +22 -9
- package/src/components/credit-notes/create/locales/pt.ts +21 -8
- package/src/components/credit-notes/create/locales/sk.ts +22 -8
- package/src/components/credit-notes/create/locales/sl.ts +19 -5
- package/src/components/credit-notes/create/locales/sv.ts +22 -8
- package/src/components/credit-notes/create/prepare-credit-note-submission.ts +35 -1
- package/src/components/credit-notes/credit-notes.hooks.ts +21 -2
- package/src/components/credit-notes/list/list-table.tsx +2 -1
- package/src/components/delivery-notes/create/create-delivery-note-form.tsx +132 -30
- package/src/components/delivery-notes/create/locales/bg.ts +1 -0
- package/src/components/delivery-notes/create/locales/cs.ts +1 -0
- package/src/components/delivery-notes/create/locales/de.ts +1 -0
- package/src/components/delivery-notes/create/locales/en.ts +1 -0
- package/src/components/delivery-notes/create/locales/es.ts +1 -0
- package/src/components/delivery-notes/create/locales/et.ts +1 -0
- package/src/components/delivery-notes/create/locales/fi.ts +1 -0
- package/src/components/delivery-notes/create/locales/fr.ts +1 -0
- package/src/components/delivery-notes/create/locales/hr.ts +1 -0
- package/src/components/delivery-notes/create/locales/is.ts +1 -0
- package/src/components/delivery-notes/create/locales/it.ts +1 -0
- package/src/components/delivery-notes/create/locales/nb.ts +1 -0
- package/src/components/delivery-notes/create/locales/nl.ts +1 -0
- package/src/components/delivery-notes/create/locales/pl.ts +1 -0
- package/src/components/delivery-notes/create/locales/pt.ts +1 -0
- package/src/components/delivery-notes/create/locales/sk.ts +1 -0
- package/src/components/delivery-notes/create/locales/sl.ts +1 -0
- package/src/components/delivery-notes/create/locales/sv.ts +1 -0
- package/src/components/delivery-notes/create/prepare-delivery-note-submission.ts +34 -1
- package/src/components/delivery-notes/delivery-notes.hooks.ts +15 -1
- package/src/components/delivery-notes/list/list-table.tsx +2 -1
- package/src/components/documents/create/custom-create-template.ts +114 -0
- package/src/components/documents/create/document-add-item-form.tsx +12 -8
- package/src/components/documents/create/document-add-item-tax-rate-field.tsx +1 -2
- package/src/components/documents/create/document-date-validation.ts +111 -0
- package/src/components/documents/create/document-details-section.tsx +93 -48
- package/src/components/documents/create/document-form-item.ts +67 -0
- package/src/components/documents/create/document-item-validation.ts +6 -2
- package/src/components/documents/create/form-types.ts +2 -2
- package/src/components/documents/create/linked-documents-info.tsx +2 -11
- package/src/components/documents/create/live-preview.tsx +3 -3
- package/src/components/documents/create/mark-as-paid-section.tsx +14 -11
- package/src/components/documents/create/payment-rows.ts +30 -0
- package/src/components/documents/create/prepare-document-submission.ts +143 -103
- package/src/components/documents/create/prepare-preview-data.ts +12 -0
- package/src/components/documents/create/preserved-expected-total.ts +90 -0
- package/src/components/documents/public/public-document-summary.tsx +6 -13
- package/src/components/documents/view/document-actions-bar.tsx +10 -1
- package/src/components/documents/view/document-details-card.tsx +4 -12
- package/src/components/documents/view/document-relations-list.tsx +4 -4
- package/src/components/documents/view/locales/bg.ts +8 -8
- package/src/components/documents/view/locales/cs.ts +8 -8
- package/src/components/documents/view/locales/de.ts +1 -1
- package/src/components/documents/view/locales/en.ts +14 -14
- package/src/components/documents/view/locales/es.ts +1 -1
- package/src/components/documents/view/locales/et.ts +8 -8
- package/src/components/documents/view/locales/fi.ts +10 -10
- package/src/components/documents/view/locales/fr.ts +1 -1
- package/src/components/documents/view/locales/hr.ts +6 -6
- package/src/components/documents/view/locales/is.ts +8 -8
- package/src/components/documents/view/locales/it.ts +1 -1
- package/src/components/documents/view/locales/nb.ts +8 -8
- package/src/components/documents/view/locales/nl.ts +1 -1
- package/src/components/documents/view/locales/pl.ts +1 -1
- package/src/components/documents/view/locales/pt.ts +1 -1
- package/src/components/documents/view/locales/sk.ts +8 -8
- package/src/components/documents/view/locales/sl.ts +9 -9
- package/src/components/documents/view/locales/sv.ts +1 -1
- package/src/components/documents/view/use-document-download.ts +2 -2
- package/src/components/entities/entity-settings-form/locales/bg.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/cs.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/de.ts +9 -0
- package/src/components/entities/entity-settings-form/locales/en.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/es.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/et.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/fi.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/fr.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/hr.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/is.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/it.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/nb.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/nl.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/pl.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/pt.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/sk.ts +7 -0
- package/src/components/entities/entity-settings-form/locales/sl.ts +12 -4
- package/src/components/entities/entity-settings-form/locales/sv.ts +7 -0
- package/src/components/entities/settings/tax-rules-settings-form.tsx +36 -0
- package/src/components/estimates/create/create-estimate-form.tsx +195 -47
- package/src/components/estimates/create/locales/bg.ts +6 -5
- package/src/components/estimates/create/locales/cs.ts +6 -5
- package/src/components/estimates/create/locales/de.ts +4 -3
- package/src/components/estimates/create/locales/en.ts +4 -3
- package/src/components/estimates/create/locales/es.ts +4 -3
- package/src/components/estimates/create/locales/et.ts +6 -5
- package/src/components/estimates/create/locales/fi.ts +9 -8
- package/src/components/estimates/create/locales/fr.ts +4 -3
- package/src/components/estimates/create/locales/hr.ts +7 -6
- package/src/components/estimates/create/locales/is.ts +6 -5
- package/src/components/estimates/create/locales/it.ts +4 -3
- package/src/components/estimates/create/locales/nb.ts +6 -5
- package/src/components/estimates/create/locales/nl.ts +4 -3
- package/src/components/estimates/create/locales/pl.ts +4 -3
- package/src/components/estimates/create/locales/pt.ts +4 -3
- package/src/components/estimates/create/locales/sk.ts +6 -5
- package/src/components/estimates/create/locales/sl.ts +7 -6
- package/src/components/estimates/create/locales/sv.ts +6 -5
- package/src/components/estimates/create/prepare-estimate-submission.ts +37 -3
- package/src/components/estimates/estimates.hooks.ts +11 -2
- package/src/components/estimates/list/list-table.tsx +11 -1
- package/src/components/estimates/list/locales/bg.ts +2 -0
- package/src/components/estimates/list/locales/cs.ts +2 -0
- package/src/components/estimates/list/locales/de.ts +2 -0
- package/src/components/estimates/list/locales/en.ts +2 -0
- package/src/components/estimates/list/locales/es.ts +2 -0
- package/src/components/estimates/list/locales/et.ts +2 -0
- package/src/components/estimates/list/locales/fi.ts +2 -0
- package/src/components/estimates/list/locales/fr.ts +2 -0
- package/src/components/estimates/list/locales/hr.ts +7 -5
- package/src/components/estimates/list/locales/is.ts +2 -0
- package/src/components/estimates/list/locales/it.ts +2 -0
- package/src/components/estimates/list/locales/nb.ts +2 -0
- package/src/components/estimates/list/locales/nl.ts +2 -0
- package/src/components/estimates/list/locales/pl.ts +2 -0
- package/src/components/estimates/list/locales/pt.ts +2 -0
- package/src/components/estimates/list/locales/sk.ts +2 -0
- package/src/components/estimates/list/locales/sl.ts +9 -7
- package/src/components/estimates/list/locales/sv.ts +2 -0
- package/src/components/invoices/create/create-invoice-form.tsx +230 -60
- package/src/components/invoices/create/locales/bg.ts +23 -14
- package/src/components/invoices/create/locales/cs.ts +23 -14
- package/src/components/invoices/create/locales/de.ts +17 -9
- package/src/components/invoices/create/locales/en.ts +16 -7
- package/src/components/invoices/create/locales/es.ts +18 -9
- package/src/components/invoices/create/locales/et.ts +23 -14
- package/src/components/invoices/create/locales/fi.ts +24 -15
- package/src/components/invoices/create/locales/fr.ts +19 -11
- package/src/components/invoices/create/locales/hr.ts +18 -9
- package/src/components/invoices/create/locales/is.ts +23 -14
- package/src/components/invoices/create/locales/it.ts +19 -11
- package/src/components/invoices/create/locales/nb.ts +23 -14
- package/src/components/invoices/create/locales/nl.ts +19 -10
- package/src/components/invoices/create/locales/pl.ts +19 -11
- package/src/components/invoices/create/locales/pt.ts +19 -10
- package/src/components/invoices/create/locales/sk.ts +23 -14
- package/src/components/invoices/create/locales/sl.ts +17 -9
- package/src/components/invoices/create/locales/sv.ts +17 -8
- package/src/components/invoices/create/prepare-invoice-submission.ts +55 -1
- package/src/components/invoices/invoices.hooks.ts +11 -2
- package/src/components/invoices/list/list-table.tsx +2 -1
- package/src/components/invoices/send-email-dialog/locales/bg.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/cs.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/de.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/en.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/es.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/et.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/fi.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/fr.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/hr.ts +8 -3
- package/src/components/invoices/send-email-dialog/locales/is.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/it.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/nb.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/nl.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/pl.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/pt.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/sk.ts +5 -0
- package/src/components/invoices/send-email-dialog/locales/sl.ts +8 -3
- package/src/components/invoices/send-email-dialog/locales/sv.ts +5 -0
- package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +2 -1
- package/src/components/items/item-combobox.tsx +4 -4
- package/src/components/payments/create-payment-form/create-payment-form.tsx +5 -2
- package/src/components/payments/edit-payment-form/edit-payment-form.tsx +5 -1
- package/src/components/recurring-invoices/create-recurring-invoice-form/create-recurring-invoice-form.tsx +98 -22
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/bg.ts +26 -26
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/cs.ts +25 -25
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/et.ts +26 -26
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/fi.ts +36 -36
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/is.ts +26 -26
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/nb.ts +26 -26
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/sk.ts +25 -25
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/sv.ts +26 -26
- package/src/components/recurring-invoices/list/list-row-actions.tsx +9 -1
- package/src/components/recurring-invoices/list/list-table.tsx +53 -5
- package/src/components/recurring-invoices/list/locales/bg.ts +4 -0
- package/src/components/recurring-invoices/list/locales/cs.ts +4 -0
- package/src/components/recurring-invoices/list/locales/de.ts +4 -0
- package/src/components/recurring-invoices/list/locales/en.ts +4 -0
- package/src/components/recurring-invoices/list/locales/es.ts +4 -0
- package/src/components/recurring-invoices/list/locales/et.ts +4 -0
- package/src/components/recurring-invoices/list/locales/fi.ts +4 -0
- package/src/components/recurring-invoices/list/locales/fr.ts +4 -0
- package/src/components/recurring-invoices/list/locales/hr.ts +4 -0
- package/src/components/recurring-invoices/list/locales/is.ts +4 -0
- package/src/components/recurring-invoices/list/locales/it.ts +4 -0
- package/src/components/recurring-invoices/list/locales/nb.ts +4 -0
- package/src/components/recurring-invoices/list/locales/nl.ts +4 -0
- package/src/components/recurring-invoices/list/locales/pl.ts +4 -0
- package/src/components/recurring-invoices/list/locales/pt.ts +4 -0
- package/src/components/recurring-invoices/list/locales/sk.ts +4 -0
- package/src/components/recurring-invoices/list/locales/sl.ts +4 -0
- package/src/components/recurring-invoices/list/locales/sv.ts +4 -0
- package/src/components/tax-reports/slovenia-tax-profile-step.tsx +4 -1
- package/src/components/tax-reports/slovenia-yearly-export-form.tsx +3 -0
- package/src/components/tax-reports/slovenia-yearly-review-step.tsx +2 -1
- package/src/components/ui/form.tsx +5 -13
- package/src/components/ui/select.tsx +0 -1
- package/src/components/ui/sidebar.tsx +2 -2
- package/src/generate-schemas.ts +132 -99
- package/src/generated/schemas/acceptentityinvitation_body.ts +4 -3
- package/src/generated/schemas/accountwebhook.ts +4 -8
- package/src/generated/schemas/addentityuser_body.ts +4 -3
- package/src/generated/schemas/advanceinvoice.ts +167 -168
- package/src/generated/schemas/authorizeshopify_body.ts +4 -3
- package/src/generated/schemas/calculatedocumentpreview.ts +120 -0
- package/src/generated/schemas/checktransactiontype.ts +35 -0
- package/src/generated/schemas/creditnote.ts +203 -76
- package/src/generated/schemas/customadvanceinvoice.ts +172 -165
- package/src/generated/schemas/customcreditnote.ts +183 -155
- package/src/generated/schemas/customdeliverynote.ts +166 -0
- package/src/generated/schemas/customer.ts +4 -8
- package/src/generated/schemas/customestimate.ts +123 -97
- package/src/generated/schemas/customincomingpurchasedocument.ts +142 -0
- package/src/generated/schemas/custominvoice.ts +183 -154
- package/src/generated/schemas/deliverynote.ts +124 -79
- package/src/generated/schemas/einvoice.ts +19 -0
- package/src/generated/schemas/einvoicingsettings.ts +21 -0
- package/src/generated/schemas/einvoicingsupplier.ts +45 -0
- package/src/generated/schemas/entity.ts +44 -40
- package/src/generated/schemas/entityapikey.ts +1 -3
- package/src/generated/schemas/entityuserrole.ts +1 -3
- package/src/generated/schemas/estimate.ts +120 -127
- package/src/generated/schemas/exportsloveniavodxml_body.ts +4 -3
- package/src/generated/schemas/exportsloveniayearlynormiranireport_body.ts +4 -3
- package/src/generated/schemas/finadevice.ts +15 -0
- package/src/generated/schemas/finalizedocument.ts +52 -0
- package/src/generated/schemas/finapremise.ts +15 -0
- package/src/generated/schemas/finasettings.ts +1 -3
- package/src/generated/schemas/furselectronicdevice.ts +15 -0
- package/src/generated/schemas/furssettings.ts +1 -3
- package/src/generated/schemas/image.ts +15 -0
- package/src/generated/schemas/incomingpurchasedocument.ts +7 -27
- package/src/generated/schemas/incomingpurchasedocumentattachment.ts +15 -0
- package/src/generated/schemas/incomingpurchasedocumentpayment.ts +1 -3
- package/src/generated/schemas/index.ts +20 -5
- package/src/generated/schemas/invoice.ts +182 -183
- package/src/generated/schemas/item.ts +6 -10
- package/src/generated/schemas/legacymigrationauth.ts +18 -0
- package/src/generated/schemas/me.ts +2 -24
- package/src/generated/schemas/migrationjob.ts +20 -0
- package/src/generated/schemas/order.ts +4 -8
- package/src/generated/schemas/orderintegration.ts +4 -8
- package/src/generated/schemas/payment.ts +4 -8
- package/src/generated/schemas/ptatcudseries.ts +1 -3
- package/src/generated/schemas/queryentitystats.ts +15 -0
- package/src/generated/schemas/recurringinvoice.ts +4 -8
- package/src/generated/schemas/registerfursmovablepremise_body.ts +1 -3
- package/src/generated/schemas/registerfursrealestatepremise_body.ts +1 -3
- package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +10 -16
- package/src/generated/schemas/rendercreditnotepreview_body.ts +10 -16
- package/src/generated/schemas/renderdeliverynotepreview_body.ts +9 -5
- package/src/generated/schemas/renderestimatepreview_body.ts +11 -7
- package/src/generated/schemas/renderinvoicepreview_body.ts +10 -16
- package/src/generated/schemas/reviewsloveniayearlynormiranireport.ts +15 -0
- package/src/generated/schemas/searcheinvoicingcustomer.ts +18 -0
- package/src/generated/schemas/senddocument_body.ts +1 -3
- package/src/generated/schemas/sendemail_body.ts +2 -24
- package/src/generated/schemas/sloveniataxprofile.ts +8 -10
- package/src/generated/schemas/starteslogexport_body.ts +4 -3
- package/src/generated/schemas/startpdfexport_body.ts +8 -87
- package/src/generated/schemas/stripeappconnect_body.ts +4 -3
- package/src/generated/schemas/stripeappcreateinvoice_body.ts +4 -6
- package/src/generated/schemas/stripeappmarketplaceauthorize.ts +15 -0
- package/src/generated/schemas/stripeappupdatesettings_body.ts +6 -6
- package/src/generated/schemas/supplier.ts +4 -8
- package/src/generated/schemas/syncshopifyorders_body.ts +4 -3
- package/src/generated/schemas/tax.ts +6 -8
- package/src/generated/schemas/uploadfile_body.ts +1 -3
- package/src/generated/schemas/uploadfurscertificate_body.ts +6 -6
- package/src/generated/schemas/userfinasettings.ts +1 -3
- package/src/generated/schemas/userfurssettings.ts +1 -3
- package/src/generated/schemas/userptsettings.ts +1 -3
- package/src/generated/schemas/voidinvoice_body.ts +8 -3
- package/src/generated/schemas/webhook.ts +4 -8
- package/src/generated/schemas/wlsubscriptionbillingemail.ts +17 -0
- package/src/hooks/use-duplicate-document.ts +61 -30
- package/src/lib/date-only.ts +58 -0
- package/src/lib/document-display.ts +18 -0
- package/src/lib/payment-display.ts +5 -3
- package/src/lib/schemas/shared.ts +11 -0
- package/src/providers/wl-subscription-provider.tsx +5 -0
- package/src/generated/schemas/account_webhook.ts +0 -43
- package/src/generated/schemas/previewadvanceinvoice_body.ts +0 -354
- package/src/generated/schemas/previewestimate_body.ts +0 -309
- package/src/generated/schemas/registerfinamovablepremise_body.ts +0 -26
- package/src/generated/schemas/registerfinarealestatepremise_body.ts +0 -37
- package/src/generated/schemas/renderdocument_body.ts +0 -594
|
@@ -190,6 +190,13 @@ export default {
|
|
|
190
190
|
"tax-rules.require_gross_prices.label": "Exigir preços brutos",
|
|
191
191
|
"tax-rules.require_gross_prices.description":
|
|
192
192
|
"Exigir preços brutos quando a autoliquidação é aplicada. Previne variações inesperadas nos valores totais das faturas.",
|
|
193
|
+
"tax-rules.calculation_mode.label": "Calculation mode",
|
|
194
|
+
"tax-rules.calculation_mode.description": "Choose how discounts and VAT are ordered when document totals are calculated.",
|
|
195
|
+
"tax-rules.calculation_mode.b2b_standard.label": "B2B standard",
|
|
196
|
+
"tax-rules.calculation_mode.b2b_standard.description": "Discounts reduce the net line amount first, then VAT is calculated.",
|
|
197
|
+
"tax-rules.calculation_mode.b2c_gross_discount.label": "B2C gross discount",
|
|
198
|
+
"tax-rules.calculation_mode.b2c_gross_discount.description":
|
|
199
|
+
"Discounts reduce the final gross payable amount, then net and VAT are derived from that result.",
|
|
193
200
|
// Tax clauses settings
|
|
194
201
|
"Default Tax Clauses": "Cláusulas fiscais predefinidas",
|
|
195
202
|
"Set default tax clauses that are automatically added to documents based on transaction type":
|
|
@@ -169,6 +169,13 @@ export default {
|
|
|
169
169
|
"tax-rules.auto_remove_tax_export.description": "tax-rules.auto_remove_tax_export.description",
|
|
170
170
|
"tax-rules.require_gross_prices.label": "tax-rules.require_gross_prices.label",
|
|
171
171
|
"tax-rules.require_gross_prices.description": "tax-rules.require_gross_prices.description",
|
|
172
|
+
"tax-rules.calculation_mode.label": "Calculation mode",
|
|
173
|
+
"tax-rules.calculation_mode.description": "Choose how discounts and VAT are ordered when document totals are calculated.",
|
|
174
|
+
"tax-rules.calculation_mode.b2b_standard.label": "B2B standard",
|
|
175
|
+
"tax-rules.calculation_mode.b2b_standard.description": "Discounts reduce the net line amount first, then VAT is calculated.",
|
|
176
|
+
"tax-rules.calculation_mode.b2c_gross_discount.label": "B2C gross discount",
|
|
177
|
+
"tax-rules.calculation_mode.b2c_gross_discount.description":
|
|
178
|
+
"Discounts reduce the final gross payable amount, then net and VAT are derived from that result.",
|
|
172
179
|
"Default Tax Clauses": "Default Tax Clauses",
|
|
173
180
|
"Set default tax clauses that are automatically added to documents based on transaction type":
|
|
174
181
|
"Set default tax clauses that are automatically added to documents based on transaction type",
|
|
@@ -64,19 +64,19 @@ export default {
|
|
|
64
64
|
"This note will be pre-filled when creating new invoices":
|
|
65
65
|
"Ta pripis bo vnaprej izpolnjen pri ustvarjanju novih računov",
|
|
66
66
|
"This note will be pre-filled when creating new estimates":
|
|
67
|
-
"Ta pripis bo vnaprej izpolnjen pri ustvarjanju novih
|
|
67
|
+
"Ta pripis bo vnaprej izpolnjen pri ustvarjanju novih ponudb",
|
|
68
68
|
"This note will be pre-filled when creating new credit notes":
|
|
69
69
|
"Ta pripis bo vnaprej izpolnjen pri ustvarjanju novih dobropisov",
|
|
70
70
|
"Payment terms pre-filled when creating new invoices":
|
|
71
71
|
"Plačilni pogoji bodo vnaprej izpolnjeni pri ustvarjanju novih računov",
|
|
72
72
|
"Payment terms pre-filled when creating new estimates":
|
|
73
|
-
"Plačilni pogoji bodo vnaprej izpolnjeni pri ustvarjanju novih
|
|
73
|
+
"Plačilni pogoji bodo vnaprej izpolnjeni pri ustvarjanju novih ponudb",
|
|
74
74
|
"Payment terms pre-filled when creating new credit notes":
|
|
75
75
|
"Plačilni pogoji bodo vnaprej izpolnjeni pri ustvarjanju novih dobropisov",
|
|
76
76
|
"Optional note for the document.": "Neobvezna opomba za dokument.",
|
|
77
77
|
"Please remit payment using the bank details shown on the document.":
|
|
78
78
|
"Plačilo izvedite po bančnih podatkih, navedenih na dokumentu.",
|
|
79
|
-
"This estimate is valid until {document_valid_until}.": "Ta
|
|
79
|
+
"This estimate is valid until {document_valid_until}.": "Ta ponudba velja do {document_valid_until}.",
|
|
80
80
|
"Payment due upon acceptance.": "Plačilo ob sprejemu.",
|
|
81
81
|
"Credit note for invoice {document_number}.": "Dobropis za račun {document_number}.",
|
|
82
82
|
"Credit will be applied to your account.": "Dobropis bo upoštevan na vašem računu.",
|
|
@@ -167,7 +167,7 @@ export default {
|
|
|
167
167
|
"UPN QR je slovenski standard za plačilne naloge. Ko je omogočen, bodo vaši računi vključevali QR kodo, ki jo stranke lahko skenirajo z mobilno bančno aplikacijo za takojšnje plačilo.",
|
|
168
168
|
// Number format settings
|
|
169
169
|
Invoice: "Račun",
|
|
170
|
-
Estimate: "
|
|
170
|
+
Estimate: "Ponudba",
|
|
171
171
|
"Credit Note": "Dobropis",
|
|
172
172
|
"Advance Invoice": "Avansni račun",
|
|
173
173
|
"Number Format": "Format številke",
|
|
@@ -186,6 +186,14 @@ export default {
|
|
|
186
186
|
"tax-rules.require_gross_prices.label": "Zahtevaj bruto cene",
|
|
187
187
|
"tax-rules.require_gross_prices.description":
|
|
188
188
|
"Zahtevaj bruto cene, ko se uporabi obrnjena davčna obveznost. Prepreči nepričakovane spremembe skupnih zneskov računov.",
|
|
189
|
+
"tax-rules.calculation_mode.label": "Način izračuna",
|
|
190
|
+
"tax-rules.calculation_mode.description": "Izberite vrstni red popustov in DDV pri izračunu zneskov dokumenta.",
|
|
191
|
+
"tax-rules.calculation_mode.b2b_standard.label": "Standard B2B",
|
|
192
|
+
"tax-rules.calculation_mode.b2b_standard.description":
|
|
193
|
+
"Popusti najprej zmanjšajo neto znesek postavke, nato se obračuna DDV.",
|
|
194
|
+
"tax-rules.calculation_mode.b2c_gross_discount.label": "B2C bruto popust",
|
|
195
|
+
"tax-rules.calculation_mode.b2c_gross_discount.description":
|
|
196
|
+
"Popusti zmanjšajo končni bruto znesek za plačilo, neto osnova in DDV pa se izračunata iz tega rezultata.",
|
|
189
197
|
// Tax clauses settings
|
|
190
198
|
"Default Tax Clauses": "Privzete davčne klavzule",
|
|
191
199
|
"Set default tax clauses that are automatically added to documents based on transaction type":
|
|
@@ -175,6 +175,13 @@ export default {
|
|
|
175
175
|
"tax-rules.auto_remove_tax_export.description": "tax-rules.auto_remove_tax_export.description",
|
|
176
176
|
"tax-rules.require_gross_prices.label": "tax-rules.require_gross_prices.label",
|
|
177
177
|
"tax-rules.require_gross_prices.description": "tax-rules.require_gross_prices.description",
|
|
178
|
+
"tax-rules.calculation_mode.label": "Calculation mode",
|
|
179
|
+
"tax-rules.calculation_mode.description": "Choose how discounts and VAT are ordered when document totals are calculated.",
|
|
180
|
+
"tax-rules.calculation_mode.b2b_standard.label": "B2B standard",
|
|
181
|
+
"tax-rules.calculation_mode.b2b_standard.description": "Discounts reduce the net line amount first, then VAT is calculated.",
|
|
182
|
+
"tax-rules.calculation_mode.b2c_gross_discount.label": "B2C gross discount",
|
|
183
|
+
"tax-rules.calculation_mode.b2c_gross_discount.description":
|
|
184
|
+
"Discounts reduce the final gross payable amount, then net and VAT are derived from that result.",
|
|
178
185
|
"Default Tax Clauses": "Standardskatteklausuler",
|
|
179
186
|
"Set default tax clauses that are automatically added to documents based on transaction type":
|
|
180
187
|
"Ange standardskatteklausuler som automatiskt läggs till i dokument utifrån transaktionstyp",
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "@/ui/components/ui/form";
|
|
18
18
|
import { Switch } from "@/ui/components/ui/switch";
|
|
19
19
|
import { Textarea } from "@/ui/components/ui/textarea";
|
|
20
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/ui/components/ui/select";
|
|
20
21
|
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
21
22
|
import { createTranslation } from "@/ui/lib/translation";
|
|
22
23
|
import { cn } from "@/ui/lib/utils";
|
|
@@ -28,6 +29,7 @@ import sl from "../entity-settings-form/locales/sl";
|
|
|
28
29
|
const translations = { sl, de } as const;
|
|
29
30
|
|
|
30
31
|
const taxRulesSettingsSchema = z.object({
|
|
32
|
+
calculation_mode: z.enum(["b2b_standard", "b2c_gross_discount"]),
|
|
31
33
|
vies_validate_vat: z.boolean(),
|
|
32
34
|
auto_reverse_charge: z.boolean(),
|
|
33
35
|
auto_remove_tax_export: z.boolean(),
|
|
@@ -83,6 +85,7 @@ export function TaxRulesSettingsForm({
|
|
|
83
85
|
|
|
84
86
|
const defaultValues = useMemo(
|
|
85
87
|
(): TaxRulesSettingsSchema => ({
|
|
88
|
+
calculation_mode: currentSettings.calculation?.default_mode ?? "b2b_standard",
|
|
86
89
|
vies_validate_vat: currentTaxRules.vies_validate_vat ?? true,
|
|
87
90
|
auto_reverse_charge: currentTaxRules.auto_reverse_charge ?? false,
|
|
88
91
|
auto_remove_tax_export: currentTaxRules.auto_remove_tax_export ?? false,
|
|
@@ -129,6 +132,10 @@ export function TaxRulesSettingsForm({
|
|
|
129
132
|
const onSubmit = (values: TaxRulesSettingsSchema) => {
|
|
130
133
|
const updatedSettings: EntitySettings = {
|
|
131
134
|
...currentSettings,
|
|
135
|
+
calculation: {
|
|
136
|
+
...currentSettings.calculation,
|
|
137
|
+
default_mode: values.calculation_mode,
|
|
138
|
+
},
|
|
132
139
|
tax_rules: {
|
|
133
140
|
eu: {
|
|
134
141
|
vies_validate_vat: values.vies_validate_vat,
|
|
@@ -165,6 +172,35 @@ export function TaxRulesSettingsForm({
|
|
|
165
172
|
// Tax rules section content (switches)
|
|
166
173
|
const taxRulesContent = (
|
|
167
174
|
<div className="space-y-4">
|
|
175
|
+
<FormField
|
|
176
|
+
control={form.control}
|
|
177
|
+
name="calculation_mode"
|
|
178
|
+
render={({ field }) => (
|
|
179
|
+
<FormItem className="rounded-lg border p-4">
|
|
180
|
+
<FormLabel className="text-base">{t("tax-rules.calculation_mode.label")}</FormLabel>
|
|
181
|
+
<FormDescription>{t("tax-rules.calculation_mode.description")}</FormDescription>
|
|
182
|
+
<FormControl>
|
|
183
|
+
<Select value={field.value} onValueChange={field.onChange}>
|
|
184
|
+
<SelectTrigger className="mt-3">
|
|
185
|
+
<SelectValue />
|
|
186
|
+
</SelectTrigger>
|
|
187
|
+
<SelectContent>
|
|
188
|
+
<SelectItem value="b2b_standard">{t("tax-rules.calculation_mode.b2b_standard.label")}</SelectItem>
|
|
189
|
+
<SelectItem value="b2c_gross_discount">
|
|
190
|
+
{t("tax-rules.calculation_mode.b2c_gross_discount.label")}
|
|
191
|
+
</SelectItem>
|
|
192
|
+
</SelectContent>
|
|
193
|
+
</Select>
|
|
194
|
+
</FormControl>
|
|
195
|
+
<div className="mt-3 space-y-1 text-muted-foreground text-sm">
|
|
196
|
+
<p>{t("tax-rules.calculation_mode.b2b_standard.description")}</p>
|
|
197
|
+
<p>{t("tax-rules.calculation_mode.b2c_gross_discount.description")}</p>
|
|
198
|
+
</div>
|
|
199
|
+
<FormMessage />
|
|
200
|
+
</FormItem>
|
|
201
|
+
)}
|
|
202
|
+
/>
|
|
203
|
+
|
|
168
204
|
<FormField
|
|
169
205
|
control={form.control}
|
|
170
206
|
name="vies_validate_vat"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
2
|
-
import type { CreateEstimateRequest, Estimate } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import type { CreateEstimateRequest, Estimate, UpdateEstimate } from "@spaceinvoices/js-sdk";
|
|
3
3
|
import { useQueryClient } from "@tanstack/react-query";
|
|
4
|
-
import {
|
|
4
|
+
import { ArrowUpDown } from "lucide-react";
|
|
5
5
|
import type { ReactNode } from "react";
|
|
6
6
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
7
7
|
import type { Resolver } from "react-hook-form";
|
|
@@ -17,11 +17,13 @@ import {
|
|
|
17
17
|
type PtDocumentInputForm,
|
|
18
18
|
ptDocumentInputFormSchema,
|
|
19
19
|
} from "@/ui/lib/pt-document-input";
|
|
20
|
+
import { normalizeLineItemDiscountsForForm } from "@/ui/lib/schemas/shared";
|
|
20
21
|
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
21
22
|
import { createTranslation } from "@/ui/lib/translation";
|
|
22
23
|
import { useEntities } from "@/ui/providers/entities-context";
|
|
23
24
|
import { useFormFooterRegistration } from "@/ui/providers/form-footer-context";
|
|
24
25
|
import { CUSTOMERS_CACHE_KEY } from "../../customers/customers.hooks";
|
|
26
|
+
import { withEstimateIssueDateValidation } from "../../documents/create/document-date-validation";
|
|
25
27
|
import {
|
|
26
28
|
DocumentDetailsSection,
|
|
27
29
|
DocumentFooterField,
|
|
@@ -33,8 +35,11 @@ import {
|
|
|
33
35
|
import { withRequiredDocumentItemFields } from "../../documents/create/document-item-validation";
|
|
34
36
|
import { DocumentItemsSection, type PriceModesMap } from "../../documents/create/document-items-section";
|
|
35
37
|
import { DocumentRecipientSection } from "../../documents/create/document-recipient-section";
|
|
38
|
+
import { prepareDocumentItems } from "../../documents/create/prepare-document-submission";
|
|
39
|
+
import { applyCustomCreateTemplate } from "../../documents/create/custom-create-template";
|
|
40
|
+
import { financialInputsMatchInitial, resolvePreservedExpectedTotal } from "../../documents/create/preserved-expected-total";
|
|
36
41
|
import type { DocumentTypes } from "../../documents/types";
|
|
37
|
-
import { useCreateEstimate } from "../estimates.hooks";
|
|
42
|
+
import { useCreateCustomEstimate, useCreateEstimate, useUpdateEstimate } from "../estimates.hooks";
|
|
38
43
|
import de from "./locales/de";
|
|
39
44
|
import es from "./locales/es";
|
|
40
45
|
import fr from "./locales/fr";
|
|
@@ -44,7 +49,7 @@ import nl from "./locales/nl";
|
|
|
44
49
|
import pl from "./locales/pl";
|
|
45
50
|
import pt from "./locales/pt";
|
|
46
51
|
import sl from "./locales/sl";
|
|
47
|
-
import { prepareEstimateSubmission } from "./prepare-estimate-submission";
|
|
52
|
+
import { prepareEstimateSubmission, prepareEstimateUpdateSubmission } from "./prepare-estimate-submission";
|
|
48
53
|
import { useEstimateCustomerForm } from "./use-estimate-customer-form";
|
|
49
54
|
|
|
50
55
|
function calculateDueDate(dateIso: string, days: number): string {
|
|
@@ -64,10 +69,12 @@ const translations = {
|
|
|
64
69
|
pl,
|
|
65
70
|
hr,
|
|
66
71
|
} as const;
|
|
67
|
-
const createEstimateFormSchema =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
const createEstimateFormSchema = withEstimateIssueDateValidation(
|
|
73
|
+
withRequiredDocumentItemFields(
|
|
74
|
+
createEstimateSchema.extend({
|
|
75
|
+
pt: ptDocumentInputFormSchema.optional(),
|
|
76
|
+
}),
|
|
77
|
+
),
|
|
71
78
|
);
|
|
72
79
|
|
|
73
80
|
// Form values: extend schema with local-only fields (number is for display, not sent to API)
|
|
@@ -88,7 +95,12 @@ type CreateEstimateFormProps = {
|
|
|
88
95
|
/** Callback to update header action (title toggle) */
|
|
89
96
|
onHeaderActionChange?: (action: ReactNode) => void;
|
|
90
97
|
/** Initial values for form fields (used for document duplication) */
|
|
91
|
-
initialValues?: Partial<CreateEstimateRequest
|
|
98
|
+
initialValues?: Partial<CreateEstimateRequest> & {
|
|
99
|
+
number?: string;
|
|
100
|
+
title_type?: "estimate" | "proforma_invoice" | null;
|
|
101
|
+
};
|
|
102
|
+
mode?: "create" | "edit";
|
|
103
|
+
documentId?: string;
|
|
92
104
|
/** Whether draft actions should be available in the UI */
|
|
93
105
|
allowDrafts?: boolean;
|
|
94
106
|
/** Optional app-level content rendered inside the details section. */
|
|
@@ -105,6 +117,8 @@ export default function CreateEstimateForm({
|
|
|
105
117
|
onAddNewTax,
|
|
106
118
|
onHeaderActionChange,
|
|
107
119
|
initialValues,
|
|
120
|
+
mode = "create",
|
|
121
|
+
documentId,
|
|
108
122
|
allowDrafts = true,
|
|
109
123
|
detailsExtras,
|
|
110
124
|
translationLocale,
|
|
@@ -122,9 +136,12 @@ export default function CreateEstimateForm({
|
|
|
122
136
|
|
|
123
137
|
const { activeEntity } = useEntities();
|
|
124
138
|
const queryClient = useQueryClient();
|
|
139
|
+
const isEditMode = mode === "edit";
|
|
125
140
|
|
|
126
|
-
// Title type state: "estimate" (default) or "
|
|
127
|
-
const [titleType, setTitleType] = useState<"estimate" | "
|
|
141
|
+
// Title type state: "estimate" (default) or "proforma_invoice"
|
|
142
|
+
const [titleType, setTitleType] = useState<"estimate" | "proforma_invoice">(
|
|
143
|
+
(initialValues as any)?.title_type || "estimate",
|
|
144
|
+
);
|
|
128
145
|
|
|
129
146
|
// Draft submission state
|
|
130
147
|
const [isDraftPending, setIsDraftPending] = useState(false);
|
|
@@ -135,7 +152,7 @@ export default function CreateEstimateForm({
|
|
|
135
152
|
|
|
136
153
|
// Fetch next estimate number
|
|
137
154
|
const { data: nextNumberData } = useNextDocumentNumber(entityId, "estimate", {
|
|
138
|
-
enabled: !!entityId,
|
|
155
|
+
enabled: !!entityId && !isEditMode,
|
|
139
156
|
});
|
|
140
157
|
|
|
141
158
|
// Get default payment terms and footer from entity settings
|
|
@@ -145,22 +162,28 @@ export default function CreateEstimateForm({
|
|
|
145
162
|
const form = useForm<CreateEstimateFormValues>({
|
|
146
163
|
resolver: zodResolver(createEstimateFormSchema) as Resolver<CreateEstimateFormValues>,
|
|
147
164
|
defaultValues: {
|
|
148
|
-
number: "",
|
|
165
|
+
number: initialValues?.number ?? "",
|
|
166
|
+
calculation_mode: (initialValues as any)?.calculation_mode ?? undefined,
|
|
149
167
|
date: initialValues?.date || new Date().toISOString(),
|
|
150
168
|
customer_id: initialValues?.customer_id ?? undefined,
|
|
151
169
|
// Cast customer to form schema type (API type may have additional fields)
|
|
152
170
|
customer: (initialValues?.customer as CreateEstimateFormValues["customer"]) ?? undefined,
|
|
153
171
|
items: initialValues?.items?.length
|
|
154
172
|
? initialValues.items.map((item: any) => ({
|
|
155
|
-
type: item.type,
|
|
173
|
+
type: item.type ?? undefined,
|
|
156
174
|
name: item.name || "",
|
|
157
175
|
description: item.description || "",
|
|
158
176
|
...(item.type !== "separator"
|
|
159
177
|
? {
|
|
178
|
+
item_id: item.item_id ?? undefined,
|
|
179
|
+
classification: item.classification ?? undefined,
|
|
180
|
+
unit: item.unit ?? undefined,
|
|
160
181
|
quantity: item.quantity ?? 1,
|
|
161
182
|
// Use gross_price if set, otherwise use price
|
|
162
183
|
price: item.gross_price ?? item.price,
|
|
184
|
+
gross_price: item.gross_price ?? undefined,
|
|
163
185
|
taxes: item.taxes || [],
|
|
186
|
+
discounts: normalizeLineItemDiscountsForForm(item.discounts),
|
|
164
187
|
}
|
|
165
188
|
: {}),
|
|
166
189
|
}))
|
|
@@ -175,13 +198,16 @@ export default function CreateEstimateForm({
|
|
|
175
198
|
],
|
|
176
199
|
currency_code: initialValues?.currency_code || activeEntity?.currency_code || "EUR",
|
|
177
200
|
reference: (initialValues as any)?.reference ?? "",
|
|
178
|
-
note: initialValues?.note ?? defaultEstimateNote,
|
|
201
|
+
note: initialValues?.note ?? (isEditMode ? "" : defaultEstimateNote),
|
|
179
202
|
tax_clause: (initialValues as any)?.tax_clause ?? "",
|
|
180
|
-
payment_terms: initialValues?.payment_terms ?? defaultPaymentTerms,
|
|
181
|
-
|
|
203
|
+
payment_terms: initialValues?.payment_terms ?? (isEditMode ? "" : defaultPaymentTerms),
|
|
204
|
+
signature: (initialValues as any)?.signature ?? "",
|
|
205
|
+
footer: (initialValues as any)?.footer ?? (isEditMode ? "" : defaultFooter),
|
|
182
206
|
date_valid_till:
|
|
183
207
|
initialValues?.date_valid_till ||
|
|
184
|
-
|
|
208
|
+
(isEditMode
|
|
209
|
+
? undefined
|
|
210
|
+
: calculateDueDate(initialValues?.date || new Date().toISOString(), defaultEstimateValidDays)),
|
|
185
211
|
pt: ((initialValues as any)?.pt as PtDocumentInputForm | undefined) ?? undefined,
|
|
186
212
|
},
|
|
187
213
|
});
|
|
@@ -189,6 +215,7 @@ export default function CreateEstimateForm({
|
|
|
189
215
|
// Price modes per item (gross vs net) - collected from component state at submit
|
|
190
216
|
const onHeaderActionChangeRef = useRef(onHeaderActionChange);
|
|
191
217
|
onHeaderActionChangeRef.current = onHeaderActionChange;
|
|
218
|
+
const headerActionSignatureRef = useRef<string | null>(null);
|
|
192
219
|
|
|
193
220
|
const onChangeRef = useRef(onChange);
|
|
194
221
|
onChangeRef.current = onChange;
|
|
@@ -201,16 +228,48 @@ export default function CreateEstimateForm({
|
|
|
201
228
|
}, {} as PriceModesMap);
|
|
202
229
|
}, [initialValues?.items]);
|
|
203
230
|
const priceModesRef = useRef<PriceModesMap>(initialPriceModes);
|
|
231
|
+
const customCreateTemplate = (initialValues as any)?._custom_create_template;
|
|
232
|
+
const financialInputsMatchSource = useCallback(
|
|
233
|
+
(values: { items?: any[]; currency_code?: string; calculation_mode?: string | null }) =>
|
|
234
|
+
financialInputsMatchInitial({
|
|
235
|
+
initialItems: initialValues?.items,
|
|
236
|
+
currentItems: values.items,
|
|
237
|
+
initialCurrencyCode: initialValues?.currency_code,
|
|
238
|
+
currentCurrencyCode: values.currency_code,
|
|
239
|
+
initialCalculationMode: (initialValues as any)?.calculation_mode ?? null,
|
|
240
|
+
currentCalculationMode: values.calculation_mode ?? null,
|
|
241
|
+
initialPriceModes,
|
|
242
|
+
currentPriceModes: priceModesRef.current,
|
|
243
|
+
}),
|
|
244
|
+
[initialPriceModes, initialValues],
|
|
245
|
+
);
|
|
246
|
+
const getPreservedExpectedTotalWithTax = useCallback(
|
|
247
|
+
(values: { items?: any[]; currency_code?: string; calculation_mode?: string | null }) =>
|
|
248
|
+
resolvePreservedExpectedTotal({
|
|
249
|
+
initialExpectedTotalWithTax: (initialValues as any)?._preserved_expected_total_with_tax,
|
|
250
|
+
initialItems: initialValues?.items,
|
|
251
|
+
currentItems: values.items,
|
|
252
|
+
initialCurrencyCode: initialValues?.currency_code,
|
|
253
|
+
currentCurrencyCode: values.currency_code,
|
|
254
|
+
initialCalculationMode: (initialValues as any)?.calculation_mode ?? null,
|
|
255
|
+
currentCalculationMode: values.calculation_mode ?? null,
|
|
256
|
+
initialPriceModes,
|
|
257
|
+
currentPriceModes: priceModesRef.current,
|
|
258
|
+
}),
|
|
259
|
+
[initialPriceModes, initialValues],
|
|
260
|
+
);
|
|
204
261
|
|
|
205
262
|
// Update number when fetched
|
|
206
263
|
useEffect(() => {
|
|
264
|
+
if (isEditMode) return;
|
|
207
265
|
if (nextNumberData?.number) {
|
|
208
266
|
form.setValue("number", nextNumberData.number);
|
|
209
267
|
}
|
|
210
|
-
}, [nextNumberData?.number
|
|
268
|
+
}, [form, isEditMode, nextNumberData?.number]);
|
|
211
269
|
|
|
212
270
|
// Update default note and valid-till date when entity loads
|
|
213
271
|
useEffect(() => {
|
|
272
|
+
if (isEditMode) return;
|
|
214
273
|
const entityDefaultNote = (activeEntity?.settings as any)?.default_estimate_note;
|
|
215
274
|
if (entityDefaultNote && !form.getValues("note")) {
|
|
216
275
|
form.setValue("note", entityDefaultNote);
|
|
@@ -226,7 +285,7 @@ export default function CreateEstimateForm({
|
|
|
226
285
|
form.setValue("date_valid_till", calculateDueDate(currentDate, validDays));
|
|
227
286
|
}
|
|
228
287
|
}
|
|
229
|
-
}, [activeEntity, form, initialValues?.date_valid_till]);
|
|
288
|
+
}, [activeEntity, form, initialValues?.date_valid_till, isEditMode]);
|
|
230
289
|
|
|
231
290
|
// Auto-add tax field for tax subject entities
|
|
232
291
|
useEffect(() => {
|
|
@@ -241,12 +300,39 @@ export default function CreateEstimateForm({
|
|
|
241
300
|
// Update header with clickable title toggle
|
|
242
301
|
useEffect(() => {
|
|
243
302
|
const callback = onHeaderActionChangeRef.current;
|
|
244
|
-
if (!callback)
|
|
303
|
+
if (!callback) {
|
|
304
|
+
headerActionSignatureRef.current = null;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
245
307
|
|
|
246
308
|
const toggleTitle = () => {
|
|
247
|
-
setTitleType((prev) => (prev === "estimate" ? "
|
|
309
|
+
setTitleType((prev) => (prev === "estimate" ? "proforma_invoice" : "estimate"));
|
|
248
310
|
};
|
|
249
311
|
|
|
312
|
+
const titleLabel = isEditMode
|
|
313
|
+
? titleType === "estimate"
|
|
314
|
+
? t("Estimate")
|
|
315
|
+
: t("Proforma invoice")
|
|
316
|
+
: titleType === "estimate"
|
|
317
|
+
? t("Create Estimate")
|
|
318
|
+
: t("Create Proforma invoice");
|
|
319
|
+
const tooltipLabel = isEditMode
|
|
320
|
+
? titleType === "estimate"
|
|
321
|
+
? t("Click to switch to Proforma invoice")
|
|
322
|
+
: t("Click to switch to Estimate")
|
|
323
|
+
: titleType === "estimate"
|
|
324
|
+
? t("Click to switch to Proforma invoice")
|
|
325
|
+
: t("Click to switch to Estimate");
|
|
326
|
+
const headerActionSignature = JSON.stringify({
|
|
327
|
+
titleLabel,
|
|
328
|
+
tooltipLabel,
|
|
329
|
+
isEditMode,
|
|
330
|
+
titleType,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
if (headerActionSignatureRef.current === headerActionSignature) return;
|
|
334
|
+
headerActionSignatureRef.current = headerActionSignature;
|
|
335
|
+
|
|
250
336
|
callback(
|
|
251
337
|
<TooltipProvider>
|
|
252
338
|
<Tooltip>
|
|
@@ -256,17 +342,24 @@ export default function CreateEstimateForm({
|
|
|
256
342
|
onClick={toggleTitle}
|
|
257
343
|
className="flex cursor-pointer items-center gap-2 font-bold text-2xl hover:text-primary"
|
|
258
344
|
>
|
|
259
|
-
{
|
|
260
|
-
<
|
|
345
|
+
{titleLabel}
|
|
346
|
+
<ArrowUpDown className="size-4 text-muted-foreground" />
|
|
261
347
|
</button>
|
|
262
348
|
</TooltipTrigger>
|
|
263
|
-
<TooltipContent side="bottom">
|
|
264
|
-
{titleType === "estimate" ? t("Click to switch to Quote") : t("Click to switch to Estimate")}
|
|
265
|
-
</TooltipContent>
|
|
349
|
+
<TooltipContent side="bottom">{tooltipLabel}</TooltipContent>
|
|
266
350
|
</Tooltip>
|
|
267
351
|
</TooltipProvider>,
|
|
268
352
|
);
|
|
269
|
-
}, [
|
|
353
|
+
}, [isEditMode, t, titleType]);
|
|
354
|
+
|
|
355
|
+
useEffect(() => {
|
|
356
|
+
const callback = onHeaderActionChangeRef.current;
|
|
357
|
+
return () => {
|
|
358
|
+
if (!callback || headerActionSignatureRef.current === null) return;
|
|
359
|
+
headerActionSignatureRef.current = null;
|
|
360
|
+
callback(null);
|
|
361
|
+
};
|
|
362
|
+
}, []);
|
|
270
363
|
|
|
271
364
|
const formValues = useWatch({
|
|
272
365
|
control: form.control,
|
|
@@ -297,13 +390,14 @@ export default function CreateEstimateForm({
|
|
|
297
390
|
useEffect(() => {
|
|
298
391
|
if (effectiveTransactionType === prevTransactionTypeRef.current) return;
|
|
299
392
|
prevTransactionTypeRef.current = effectiveTransactionType;
|
|
393
|
+
if (isEditMode) return;
|
|
300
394
|
|
|
301
395
|
const taxClauseDefaults = (activeEntity?.settings as any)?.tax_clause_defaults;
|
|
302
396
|
if (!taxClauseDefaults) return;
|
|
303
397
|
|
|
304
398
|
const clause = taxClauseDefaults[effectiveTransactionType] ?? "";
|
|
305
399
|
form.setValue("tax_clause", clause);
|
|
306
|
-
}, [effectiveTransactionType, activeEntity, form]);
|
|
400
|
+
}, [effectiveTransactionType, activeEntity, form, isEditMode]);
|
|
307
401
|
|
|
308
402
|
// Extract customer management logic into a custom hook
|
|
309
403
|
const {
|
|
@@ -327,18 +421,59 @@ export default function CreateEstimateForm({
|
|
|
327
421
|
},
|
|
328
422
|
onError,
|
|
329
423
|
});
|
|
424
|
+
const { mutate: createCustomEstimate, isPending: isCreateCustomPending } = useCreateCustomEstimate({
|
|
425
|
+
entityId,
|
|
426
|
+
onSuccess: (data) => {
|
|
427
|
+
if (data.customer_id) {
|
|
428
|
+
queryClient.invalidateQueries({ queryKey: [CUSTOMERS_CACHE_KEY] });
|
|
429
|
+
}
|
|
430
|
+
onSuccess?.(data);
|
|
431
|
+
},
|
|
432
|
+
onError,
|
|
433
|
+
});
|
|
434
|
+
const { mutate: updateEstimate, isPending: isUpdatePending } = useUpdateEstimate({
|
|
435
|
+
entityId,
|
|
436
|
+
onSuccess,
|
|
437
|
+
onError,
|
|
438
|
+
});
|
|
330
439
|
|
|
331
440
|
// Shared submit logic for both regular save and save as draft
|
|
332
441
|
const submitEstimate = useCallback(
|
|
333
442
|
(values: CreateEstimateFormValues, isDraft: boolean) => {
|
|
334
443
|
try {
|
|
444
|
+
if (isEditMode) {
|
|
445
|
+
if (!documentId) {
|
|
446
|
+
throw new Error("Estimate edit mode requires a documentId");
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const submission = prepareEstimateUpdateSubmission(values as any, {
|
|
450
|
+
originalCustomer,
|
|
451
|
+
priceModes: priceModesRef.current,
|
|
452
|
+
titleType,
|
|
453
|
+
}) as UpdateEstimate;
|
|
454
|
+
|
|
455
|
+
updateEstimate({ id: documentId, data: submission });
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
335
459
|
const submission = prepareEstimateSubmission(values, {
|
|
336
460
|
originalCustomer,
|
|
337
461
|
priceModes: priceModesRef.current,
|
|
338
462
|
titleType,
|
|
339
463
|
isDraft,
|
|
340
464
|
});
|
|
341
|
-
|
|
465
|
+
const preservedExpectedTotalWithTax = getPreservedExpectedTotalWithTax(values);
|
|
466
|
+
if (preservedExpectedTotalWithTax !== undefined) {
|
|
467
|
+
(submission as any).expected_total_with_tax = preservedExpectedTotalWithTax;
|
|
468
|
+
} else {
|
|
469
|
+
delete (submission as any).expected_total_with_tax;
|
|
470
|
+
}
|
|
471
|
+
if (customCreateTemplate && financialInputsMatchSource(values)) {
|
|
472
|
+
delete (submission as any).expected_total_with_tax;
|
|
473
|
+
createCustomEstimate(applyCustomCreateTemplate(submission as any, customCreateTemplate));
|
|
474
|
+
} else {
|
|
475
|
+
createEstimate(submission);
|
|
476
|
+
}
|
|
342
477
|
} catch (error) {
|
|
343
478
|
console.error("Estimate submission error:", error);
|
|
344
479
|
if (onError) {
|
|
@@ -346,7 +481,19 @@ export default function CreateEstimateForm({
|
|
|
346
481
|
}
|
|
347
482
|
}
|
|
348
483
|
},
|
|
349
|
-
[
|
|
484
|
+
[
|
|
485
|
+
createEstimate,
|
|
486
|
+
createCustomEstimate,
|
|
487
|
+
customCreateTemplate,
|
|
488
|
+
documentId,
|
|
489
|
+
financialInputsMatchSource,
|
|
490
|
+
getPreservedExpectedTotalWithTax,
|
|
491
|
+
isEditMode,
|
|
492
|
+
onError,
|
|
493
|
+
originalCustomer,
|
|
494
|
+
titleType,
|
|
495
|
+
updateEstimate,
|
|
496
|
+
],
|
|
350
497
|
);
|
|
351
498
|
|
|
352
499
|
// Handle save as draft
|
|
@@ -365,26 +512,27 @@ export default function CreateEstimateForm({
|
|
|
365
512
|
|
|
366
513
|
const secondaryAction = useMemo(
|
|
367
514
|
() =>
|
|
368
|
-
allowDrafts
|
|
515
|
+
allowDrafts && !isEditMode
|
|
369
516
|
? {
|
|
370
517
|
label: t("Save as Draft"),
|
|
371
518
|
onClick: handleSaveAsDraft,
|
|
372
519
|
isPending: isDraftPending,
|
|
373
520
|
}
|
|
374
521
|
: undefined,
|
|
375
|
-
[allowDrafts, t, handleSaveAsDraft, isDraftPending],
|
|
522
|
+
[allowDrafts, t, handleSaveAsDraft, isDraftPending, isEditMode],
|
|
376
523
|
);
|
|
377
524
|
|
|
378
525
|
useFormFooterRegistration({
|
|
379
526
|
formId: "create-estimate-form",
|
|
380
|
-
isPending,
|
|
527
|
+
isPending: isPending || isCreateCustomPending || isUpdatePending,
|
|
381
528
|
isDirty: form.formState.isDirty || !!initialValues,
|
|
382
|
-
label: titleType === "estimate" ? t("Create Estimate") : t("Create
|
|
529
|
+
label: isEditMode ? t("Update") : titleType === "estimate" ? t("Create Estimate") : t("Create Proforma invoice"),
|
|
383
530
|
secondaryAction,
|
|
384
531
|
});
|
|
385
532
|
|
|
386
533
|
// Set default payment terms and footer from entity settings when entity data is available
|
|
387
534
|
useEffect(() => {
|
|
535
|
+
if (isEditMode) return;
|
|
388
536
|
const entityDefaultPaymentTerms = (activeEntity?.settings as any)?.default_estimate_payment_terms;
|
|
389
537
|
if (entityDefaultPaymentTerms && !form.getValues("payment_terms")) {
|
|
390
538
|
form.setValue("payment_terms", entityDefaultPaymentTerms);
|
|
@@ -393,44 +541,44 @@ export default function CreateEstimateForm({
|
|
|
393
541
|
if (entityDefaultFooter && !form.getValues("footer")) {
|
|
394
542
|
form.setValue("footer", entityDefaultFooter);
|
|
395
543
|
}
|
|
396
|
-
}, [activeEntity, form]);
|
|
544
|
+
}, [activeEntity, form, isEditMode]);
|
|
397
545
|
|
|
398
546
|
// Recalculate valid-till date when document date changes
|
|
399
547
|
const prevDateRef = useRef(form.getValues("date"));
|
|
400
548
|
useEffect(() => {
|
|
549
|
+
if (isEditMode) return;
|
|
401
550
|
const currentDate = formValues.date;
|
|
402
551
|
if (!currentDate || currentDate === prevDateRef.current) return;
|
|
403
552
|
prevDateRef.current = currentDate;
|
|
404
553
|
const validDays = (activeEntity?.settings as any)?.default_estimate_valid_days ?? 30;
|
|
405
554
|
form.setValue("date_valid_till", calculateDueDate(currentDate, validDays));
|
|
406
|
-
}, [formValues.date, activeEntity, form]);
|
|
555
|
+
}, [formValues.date, activeEntity, form, isEditMode]);
|
|
407
556
|
|
|
408
557
|
const buildPreviewPayload = useCallback(
|
|
409
558
|
(values: CreateEstimateFormValues): EstimatePreviewPayload => {
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
const transformedItems = currentItems.map((item: any, index: number) => {
|
|
413
|
-
const { price, ...rest } = item;
|
|
414
|
-
const isGross = priceModesRef.current[index] ?? false;
|
|
415
|
-
return isGross ? { ...rest, gross_price: price } : { ...rest, price };
|
|
416
|
-
});
|
|
417
|
-
|
|
559
|
+
const preservedExpectedTotalWithTax = getPreservedExpectedTotalWithTax(values);
|
|
418
560
|
return {
|
|
419
561
|
number: values.number,
|
|
420
562
|
date: values.date,
|
|
421
563
|
customer_id: values.customer_id,
|
|
422
564
|
customer: values.customer,
|
|
423
|
-
items:
|
|
565
|
+
items: prepareDocumentItems(values.items, priceModesRef.current),
|
|
424
566
|
currency_code: values.currency_code,
|
|
425
567
|
reference: values.reference,
|
|
426
568
|
note: values.note,
|
|
569
|
+
tax_clause: values.tax_clause,
|
|
427
570
|
payment_terms: values.payment_terms,
|
|
428
571
|
signature: values.signature,
|
|
572
|
+
footer: values.footer,
|
|
573
|
+
date_valid_till: values.date_valid_till,
|
|
429
574
|
title_type: titleType,
|
|
575
|
+
...(preservedExpectedTotalWithTax !== undefined
|
|
576
|
+
? { expected_total_with_tax: preservedExpectedTotalWithTax }
|
|
577
|
+
: {}),
|
|
430
578
|
...(normalizePtDocumentInput(values.pt) ? { pt: normalizePtDocumentInput(values.pt) } : {}),
|
|
431
579
|
};
|
|
432
580
|
},
|
|
433
|
-
[titleType],
|
|
581
|
+
[getPreservedExpectedTotalWithTax, titleType],
|
|
434
582
|
);
|
|
435
583
|
|
|
436
584
|
const emitPreviewPayload = useCallback((payload: EstimatePreviewPayload) => {
|