The customer portal bootstrap now returns current_company_currency
alongside the customer's own currency. The store falls back to the
company currency when the customer has no currency assigned.
Fixes#142
SendInvoiceModal and SendEstimateModal were only mounted on detail
views. Resend from table dropdowns did nothing because the modal
component was not in the DOM. Added to index views and dashboard.
Pass canCreatePayment and canCreateEstimate props to InvoiceDropdown
from detail view and dashboard.
Copy PDF URL now checks window.isSecureContext before using
navigator.clipboard, falls back to textarea+execCommand on HTTP,
and shows a success notification.
Invoice dropdown: Mark as Sent uses its own condition instead of
reusing Send, Resend hidden in detail view.
Estimate dropdown: Mark as Accepted/Rejected hidden when already in
the other terminal state, Convert to Invoice hidden on rejected
estimates. Added Convert to Estimate action for invoices.
fetchBasicMailConfig() was calling the wrong endpoint (company-config
instead of default config). Also, the response has no .data wrapper so
from_mail was never extracted. Fixed in all three send modals.
Estimate and payment preview blob construction now falls back to the
raw response when .data is undefined, matching the invoice modal.
Global percentage taxes are now recalculated when items or discount
change, preventing stale tax amounts. Math.round() applied to
sub_total, total, and tax in invoice/estimate submit payloads to
ensure the backend always receives whole-cent integers.
Read default_invoice_template and default_estimate_template from
useUserStore().currentUserSettings instead of relying on a parameter
that was never passed from the create views.
- Fix exchange-rate service types to match actual backend response shapes
(exchangeRate array, activeProvider success/error, used currencies as strings)
- Add ExchangeRateConverter to payments, expenses, and recurring invoices
- Set currency_id from customer currency in invoice/estimate selectCustomer()
- Load globalStore.currencies in ExchangeRateConverter on mount
- Pass driver/key/driver_config params to getSupportedCurrencies in provider modal
- Fix OpenExchangeRateDriver validateConnection to use base=USD (free plan compat)
- Fix checkActiveCurrencies SQLite whereJsonContains with array values
- Remove broken currency/companyCurrency props from ExpenseCreateView, use stores
- Show base currency equivalent in document line items and totals when exchange
rate is active
- Add manifest.json generation script (scripts/generate-manifest.php)
- Add Updater::cleanStaleFiles() that removes files not in manifest
- Add /api/v1/update/clean endpoint with backward compatibility
- Add configurable update_protected_paths in config/invoiceshelf.php
- Update frontend to use clean step instead of delete step
- Add GitHub Actions release workflow triggered on version tags
- Add .github/release.yml for auto-generated changelog categories
- Update Makefile to include manifest generation and scripts directory