@spaceinvoices/react-ui 0.4.12 → 0.4.32
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 +190 -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 +254 -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 +133 -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 +151 -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 +196 -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 +231 -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 +74 -32
- 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,29 @@ 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),
|
|
187
|
+
metadata: item.metadata ?? undefined,
|
|
164
188
|
}
|
|
165
189
|
: {}),
|
|
166
190
|
}))
|
|
@@ -175,13 +199,16 @@ export default function CreateEstimateForm({
|
|
|
175
199
|
],
|
|
176
200
|
currency_code: initialValues?.currency_code || activeEntity?.currency_code || "EUR",
|
|
177
201
|
reference: (initialValues as any)?.reference ?? "",
|
|
178
|
-
note: initialValues?.note ?? defaultEstimateNote,
|
|
202
|
+
note: initialValues?.note ?? (isEditMode ? "" : defaultEstimateNote),
|
|
179
203
|
tax_clause: (initialValues as any)?.tax_clause ?? "",
|
|
180
|
-
payment_terms: initialValues?.payment_terms ?? defaultPaymentTerms,
|
|
181
|
-
|
|
204
|
+
payment_terms: initialValues?.payment_terms ?? (isEditMode ? "" : defaultPaymentTerms),
|
|
205
|
+
signature: (initialValues as any)?.signature ?? "",
|
|
206
|
+
footer: (initialValues as any)?.footer ?? (isEditMode ? "" : defaultFooter),
|
|
182
207
|
date_valid_till:
|
|
183
208
|
initialValues?.date_valid_till ||
|
|
184
|
-
|
|
209
|
+
(isEditMode
|
|
210
|
+
? undefined
|
|
211
|
+
: calculateDueDate(initialValues?.date || new Date().toISOString(), defaultEstimateValidDays)),
|
|
185
212
|
pt: ((initialValues as any)?.pt as PtDocumentInputForm | undefined) ?? undefined,
|
|
186
213
|
},
|
|
187
214
|
});
|
|
@@ -189,6 +216,7 @@ export default function CreateEstimateForm({
|
|
|
189
216
|
// Price modes per item (gross vs net) - collected from component state at submit
|
|
190
217
|
const onHeaderActionChangeRef = useRef(onHeaderActionChange);
|
|
191
218
|
onHeaderActionChangeRef.current = onHeaderActionChange;
|
|
219
|
+
const headerActionSignatureRef = useRef<string | null>(null);
|
|
192
220
|
|
|
193
221
|
const onChangeRef = useRef(onChange);
|
|
194
222
|
onChangeRef.current = onChange;
|
|
@@ -201,16 +229,48 @@ export default function CreateEstimateForm({
|
|
|
201
229
|
}, {} as PriceModesMap);
|
|
202
230
|
}, [initialValues?.items]);
|
|
203
231
|
const priceModesRef = useRef<PriceModesMap>(initialPriceModes);
|
|
232
|
+
const customCreateTemplate = (initialValues as any)?._custom_create_template;
|
|
233
|
+
const financialInputsMatchSource = useCallback(
|
|
234
|
+
(values: { items?: any[]; currency_code?: string; calculation_mode?: string | null }) =>
|
|
235
|
+
financialInputsMatchInitial({
|
|
236
|
+
initialItems: initialValues?.items,
|
|
237
|
+
currentItems: values.items,
|
|
238
|
+
initialCurrencyCode: initialValues?.currency_code,
|
|
239
|
+
currentCurrencyCode: values.currency_code,
|
|
240
|
+
initialCalculationMode: (initialValues as any)?.calculation_mode ?? null,
|
|
241
|
+
currentCalculationMode: values.calculation_mode ?? null,
|
|
242
|
+
initialPriceModes,
|
|
243
|
+
currentPriceModes: priceModesRef.current,
|
|
244
|
+
}),
|
|
245
|
+
[initialPriceModes, initialValues],
|
|
246
|
+
);
|
|
247
|
+
const getPreservedExpectedTotalWithTax = useCallback(
|
|
248
|
+
(values: { items?: any[]; currency_code?: string; calculation_mode?: string | null }) =>
|
|
249
|
+
resolvePreservedExpectedTotal({
|
|
250
|
+
initialExpectedTotalWithTax: (initialValues as any)?._preserved_expected_total_with_tax,
|
|
251
|
+
initialItems: initialValues?.items,
|
|
252
|
+
currentItems: values.items,
|
|
253
|
+
initialCurrencyCode: initialValues?.currency_code,
|
|
254
|
+
currentCurrencyCode: values.currency_code,
|
|
255
|
+
initialCalculationMode: (initialValues as any)?.calculation_mode ?? null,
|
|
256
|
+
currentCalculationMode: values.calculation_mode ?? null,
|
|
257
|
+
initialPriceModes,
|
|
258
|
+
currentPriceModes: priceModesRef.current,
|
|
259
|
+
}),
|
|
260
|
+
[initialPriceModes, initialValues],
|
|
261
|
+
);
|
|
204
262
|
|
|
205
263
|
// Update number when fetched
|
|
206
264
|
useEffect(() => {
|
|
265
|
+
if (isEditMode) return;
|
|
207
266
|
if (nextNumberData?.number) {
|
|
208
267
|
form.setValue("number", nextNumberData.number);
|
|
209
268
|
}
|
|
210
|
-
}, [nextNumberData?.number
|
|
269
|
+
}, [form, isEditMode, nextNumberData?.number]);
|
|
211
270
|
|
|
212
271
|
// Update default note and valid-till date when entity loads
|
|
213
272
|
useEffect(() => {
|
|
273
|
+
if (isEditMode) return;
|
|
214
274
|
const entityDefaultNote = (activeEntity?.settings as any)?.default_estimate_note;
|
|
215
275
|
if (entityDefaultNote && !form.getValues("note")) {
|
|
216
276
|
form.setValue("note", entityDefaultNote);
|
|
@@ -226,7 +286,7 @@ export default function CreateEstimateForm({
|
|
|
226
286
|
form.setValue("date_valid_till", calculateDueDate(currentDate, validDays));
|
|
227
287
|
}
|
|
228
288
|
}
|
|
229
|
-
}, [activeEntity, form, initialValues?.date_valid_till]);
|
|
289
|
+
}, [activeEntity, form, initialValues?.date_valid_till, isEditMode]);
|
|
230
290
|
|
|
231
291
|
// Auto-add tax field for tax subject entities
|
|
232
292
|
useEffect(() => {
|
|
@@ -241,12 +301,39 @@ export default function CreateEstimateForm({
|
|
|
241
301
|
// Update header with clickable title toggle
|
|
242
302
|
useEffect(() => {
|
|
243
303
|
const callback = onHeaderActionChangeRef.current;
|
|
244
|
-
if (!callback)
|
|
304
|
+
if (!callback) {
|
|
305
|
+
headerActionSignatureRef.current = null;
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
245
308
|
|
|
246
309
|
const toggleTitle = () => {
|
|
247
|
-
setTitleType((prev) => (prev === "estimate" ? "
|
|
310
|
+
setTitleType((prev) => (prev === "estimate" ? "proforma_invoice" : "estimate"));
|
|
248
311
|
};
|
|
249
312
|
|
|
313
|
+
const titleLabel = isEditMode
|
|
314
|
+
? titleType === "estimate"
|
|
315
|
+
? t("Estimate")
|
|
316
|
+
: t("Proforma invoice")
|
|
317
|
+
: titleType === "estimate"
|
|
318
|
+
? t("Create Estimate")
|
|
319
|
+
: t("Create Proforma invoice");
|
|
320
|
+
const tooltipLabel = isEditMode
|
|
321
|
+
? titleType === "estimate"
|
|
322
|
+
? t("Click to switch to Proforma invoice")
|
|
323
|
+
: t("Click to switch to Estimate")
|
|
324
|
+
: titleType === "estimate"
|
|
325
|
+
? t("Click to switch to Proforma invoice")
|
|
326
|
+
: t("Click to switch to Estimate");
|
|
327
|
+
const headerActionSignature = JSON.stringify({
|
|
328
|
+
titleLabel,
|
|
329
|
+
tooltipLabel,
|
|
330
|
+
isEditMode,
|
|
331
|
+
titleType,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
if (headerActionSignatureRef.current === headerActionSignature) return;
|
|
335
|
+
headerActionSignatureRef.current = headerActionSignature;
|
|
336
|
+
|
|
250
337
|
callback(
|
|
251
338
|
<TooltipProvider>
|
|
252
339
|
<Tooltip>
|
|
@@ -256,17 +343,24 @@ export default function CreateEstimateForm({
|
|
|
256
343
|
onClick={toggleTitle}
|
|
257
344
|
className="flex cursor-pointer items-center gap-2 font-bold text-2xl hover:text-primary"
|
|
258
345
|
>
|
|
259
|
-
{
|
|
260
|
-
<
|
|
346
|
+
{titleLabel}
|
|
347
|
+
<ArrowUpDown className="size-4 text-muted-foreground" />
|
|
261
348
|
</button>
|
|
262
349
|
</TooltipTrigger>
|
|
263
|
-
<TooltipContent side="bottom">
|
|
264
|
-
{titleType === "estimate" ? t("Click to switch to Quote") : t("Click to switch to Estimate")}
|
|
265
|
-
</TooltipContent>
|
|
350
|
+
<TooltipContent side="bottom">{tooltipLabel}</TooltipContent>
|
|
266
351
|
</Tooltip>
|
|
267
352
|
</TooltipProvider>,
|
|
268
353
|
);
|
|
269
|
-
}, [
|
|
354
|
+
}, [isEditMode, t, titleType]);
|
|
355
|
+
|
|
356
|
+
useEffect(() => {
|
|
357
|
+
const callback = onHeaderActionChangeRef.current;
|
|
358
|
+
return () => {
|
|
359
|
+
if (!callback || headerActionSignatureRef.current === null) return;
|
|
360
|
+
headerActionSignatureRef.current = null;
|
|
361
|
+
callback(null);
|
|
362
|
+
};
|
|
363
|
+
}, []);
|
|
270
364
|
|
|
271
365
|
const formValues = useWatch({
|
|
272
366
|
control: form.control,
|
|
@@ -297,13 +391,14 @@ export default function CreateEstimateForm({
|
|
|
297
391
|
useEffect(() => {
|
|
298
392
|
if (effectiveTransactionType === prevTransactionTypeRef.current) return;
|
|
299
393
|
prevTransactionTypeRef.current = effectiveTransactionType;
|
|
394
|
+
if (isEditMode) return;
|
|
300
395
|
|
|
301
396
|
const taxClauseDefaults = (activeEntity?.settings as any)?.tax_clause_defaults;
|
|
302
397
|
if (!taxClauseDefaults) return;
|
|
303
398
|
|
|
304
399
|
const clause = taxClauseDefaults[effectiveTransactionType] ?? "";
|
|
305
400
|
form.setValue("tax_clause", clause);
|
|
306
|
-
}, [effectiveTransactionType, activeEntity, form]);
|
|
401
|
+
}, [effectiveTransactionType, activeEntity, form, isEditMode]);
|
|
307
402
|
|
|
308
403
|
// Extract customer management logic into a custom hook
|
|
309
404
|
const {
|
|
@@ -327,18 +422,59 @@ export default function CreateEstimateForm({
|
|
|
327
422
|
},
|
|
328
423
|
onError,
|
|
329
424
|
});
|
|
425
|
+
const { mutate: createCustomEstimate, isPending: isCreateCustomPending } = useCreateCustomEstimate({
|
|
426
|
+
entityId,
|
|
427
|
+
onSuccess: (data) => {
|
|
428
|
+
if (data.customer_id) {
|
|
429
|
+
queryClient.invalidateQueries({ queryKey: [CUSTOMERS_CACHE_KEY] });
|
|
430
|
+
}
|
|
431
|
+
onSuccess?.(data);
|
|
432
|
+
},
|
|
433
|
+
onError,
|
|
434
|
+
});
|
|
435
|
+
const { mutate: updateEstimate, isPending: isUpdatePending } = useUpdateEstimate({
|
|
436
|
+
entityId,
|
|
437
|
+
onSuccess,
|
|
438
|
+
onError,
|
|
439
|
+
});
|
|
330
440
|
|
|
331
441
|
// Shared submit logic for both regular save and save as draft
|
|
332
442
|
const submitEstimate = useCallback(
|
|
333
443
|
(values: CreateEstimateFormValues, isDraft: boolean) => {
|
|
334
444
|
try {
|
|
445
|
+
if (isEditMode) {
|
|
446
|
+
if (!documentId) {
|
|
447
|
+
throw new Error("Estimate edit mode requires a documentId");
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const submission = prepareEstimateUpdateSubmission(values as any, {
|
|
451
|
+
originalCustomer,
|
|
452
|
+
priceModes: priceModesRef.current,
|
|
453
|
+
titleType,
|
|
454
|
+
}) as UpdateEstimate;
|
|
455
|
+
|
|
456
|
+
updateEstimate({ id: documentId, data: submission });
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
335
460
|
const submission = prepareEstimateSubmission(values, {
|
|
336
461
|
originalCustomer,
|
|
337
462
|
priceModes: priceModesRef.current,
|
|
338
463
|
titleType,
|
|
339
464
|
isDraft,
|
|
340
465
|
});
|
|
341
|
-
|
|
466
|
+
const preservedExpectedTotalWithTax = getPreservedExpectedTotalWithTax(values);
|
|
467
|
+
if (preservedExpectedTotalWithTax !== undefined) {
|
|
468
|
+
(submission as any).expected_total_with_tax = preservedExpectedTotalWithTax;
|
|
469
|
+
} else {
|
|
470
|
+
delete (submission as any).expected_total_with_tax;
|
|
471
|
+
}
|
|
472
|
+
if (customCreateTemplate && financialInputsMatchSource(values)) {
|
|
473
|
+
delete (submission as any).expected_total_with_tax;
|
|
474
|
+
createCustomEstimate(applyCustomCreateTemplate(submission as any, customCreateTemplate));
|
|
475
|
+
} else {
|
|
476
|
+
createEstimate(submission);
|
|
477
|
+
}
|
|
342
478
|
} catch (error) {
|
|
343
479
|
console.error("Estimate submission error:", error);
|
|
344
480
|
if (onError) {
|
|
@@ -346,7 +482,19 @@ export default function CreateEstimateForm({
|
|
|
346
482
|
}
|
|
347
483
|
}
|
|
348
484
|
},
|
|
349
|
-
[
|
|
485
|
+
[
|
|
486
|
+
createEstimate,
|
|
487
|
+
createCustomEstimate,
|
|
488
|
+
customCreateTemplate,
|
|
489
|
+
documentId,
|
|
490
|
+
financialInputsMatchSource,
|
|
491
|
+
getPreservedExpectedTotalWithTax,
|
|
492
|
+
isEditMode,
|
|
493
|
+
onError,
|
|
494
|
+
originalCustomer,
|
|
495
|
+
titleType,
|
|
496
|
+
updateEstimate,
|
|
497
|
+
],
|
|
350
498
|
);
|
|
351
499
|
|
|
352
500
|
// Handle save as draft
|
|
@@ -365,26 +513,27 @@ export default function CreateEstimateForm({
|
|
|
365
513
|
|
|
366
514
|
const secondaryAction = useMemo(
|
|
367
515
|
() =>
|
|
368
|
-
allowDrafts
|
|
516
|
+
allowDrafts && !isEditMode
|
|
369
517
|
? {
|
|
370
518
|
label: t("Save as Draft"),
|
|
371
519
|
onClick: handleSaveAsDraft,
|
|
372
520
|
isPending: isDraftPending,
|
|
373
521
|
}
|
|
374
522
|
: undefined,
|
|
375
|
-
[allowDrafts, t, handleSaveAsDraft, isDraftPending],
|
|
523
|
+
[allowDrafts, t, handleSaveAsDraft, isDraftPending, isEditMode],
|
|
376
524
|
);
|
|
377
525
|
|
|
378
526
|
useFormFooterRegistration({
|
|
379
527
|
formId: "create-estimate-form",
|
|
380
|
-
isPending,
|
|
528
|
+
isPending: isPending || isCreateCustomPending || isUpdatePending,
|
|
381
529
|
isDirty: form.formState.isDirty || !!initialValues,
|
|
382
|
-
label: titleType === "estimate" ? t("Create Estimate") : t("Create
|
|
530
|
+
label: isEditMode ? t("Update") : titleType === "estimate" ? t("Create Estimate") : t("Create Proforma invoice"),
|
|
383
531
|
secondaryAction,
|
|
384
532
|
});
|
|
385
533
|
|
|
386
534
|
// Set default payment terms and footer from entity settings when entity data is available
|
|
387
535
|
useEffect(() => {
|
|
536
|
+
if (isEditMode) return;
|
|
388
537
|
const entityDefaultPaymentTerms = (activeEntity?.settings as any)?.default_estimate_payment_terms;
|
|
389
538
|
if (entityDefaultPaymentTerms && !form.getValues("payment_terms")) {
|
|
390
539
|
form.setValue("payment_terms", entityDefaultPaymentTerms);
|
|
@@ -393,44 +542,44 @@ export default function CreateEstimateForm({
|
|
|
393
542
|
if (entityDefaultFooter && !form.getValues("footer")) {
|
|
394
543
|
form.setValue("footer", entityDefaultFooter);
|
|
395
544
|
}
|
|
396
|
-
}, [activeEntity, form]);
|
|
545
|
+
}, [activeEntity, form, isEditMode]);
|
|
397
546
|
|
|
398
547
|
// Recalculate valid-till date when document date changes
|
|
399
548
|
const prevDateRef = useRef(form.getValues("date"));
|
|
400
549
|
useEffect(() => {
|
|
550
|
+
if (isEditMode) return;
|
|
401
551
|
const currentDate = formValues.date;
|
|
402
552
|
if (!currentDate || currentDate === prevDateRef.current) return;
|
|
403
553
|
prevDateRef.current = currentDate;
|
|
404
554
|
const validDays = (activeEntity?.settings as any)?.default_estimate_valid_days ?? 30;
|
|
405
555
|
form.setValue("date_valid_till", calculateDueDate(currentDate, validDays));
|
|
406
|
-
}, [formValues.date, activeEntity, form]);
|
|
556
|
+
}, [formValues.date, activeEntity, form, isEditMode]);
|
|
407
557
|
|
|
408
558
|
const buildPreviewPayload = useCallback(
|
|
409
559
|
(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
|
-
|
|
560
|
+
const preservedExpectedTotalWithTax = getPreservedExpectedTotalWithTax(values);
|
|
418
561
|
return {
|
|
419
562
|
number: values.number,
|
|
420
563
|
date: values.date,
|
|
421
564
|
customer_id: values.customer_id,
|
|
422
565
|
customer: values.customer,
|
|
423
|
-
items:
|
|
566
|
+
items: prepareDocumentItems(values.items, priceModesRef.current),
|
|
424
567
|
currency_code: values.currency_code,
|
|
425
568
|
reference: values.reference,
|
|
426
569
|
note: values.note,
|
|
570
|
+
tax_clause: values.tax_clause,
|
|
427
571
|
payment_terms: values.payment_terms,
|
|
428
572
|
signature: values.signature,
|
|
573
|
+
footer: values.footer,
|
|
574
|
+
date_valid_till: values.date_valid_till,
|
|
429
575
|
title_type: titleType,
|
|
576
|
+
...(preservedExpectedTotalWithTax !== undefined
|
|
577
|
+
? { expected_total_with_tax: preservedExpectedTotalWithTax }
|
|
578
|
+
: {}),
|
|
430
579
|
...(normalizePtDocumentInput(values.pt) ? { pt: normalizePtDocumentInput(values.pt) } : {}),
|
|
431
580
|
};
|
|
432
581
|
},
|
|
433
|
-
[titleType],
|
|
582
|
+
[getPreservedExpectedTotalWithTax, titleType],
|
|
434
583
|
);
|
|
435
584
|
|
|
436
585
|
const emitPreviewPayload = useCallback((payload: EstimatePreviewPayload) => {
|