feat(accounting): consolidate VAT/financial config into Settings → Accounting
- Remove the orphaned "Default VAT rate %" from Business profile; the rates are the Accounting VAT codes. The invoice/quote VAT picker (VatRateSelect) is now code-only — options are exactly the Accounting output codes, no free-text custom rate. Off-list legacy values on existing invoices are preserved as a read-only "(not configured)" option so issued documents aren't silently changed. - Move VAT label + default hourly rate to the Accounting tab (new AccountingProfileFields card; storage stays on business_profile, own save). Wire vat_label onto the PDF VAT-line label via the issuer block (covers invoices + quotes), falling back to the locale default when blank. - Default currency stays on Business profile but becomes a normalizing dropdown (an old free-text "chf" auto-selects "CHF"; unknown values preserved). Add a moved-note callout. Strip the moved fields from the Business-profile save so it can't clobber an Accounting-tab edit.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Currency codes for the Business-profile "Default currency" dropdown.
|
||||
* CH/LI-first ordering (picpeak's primary scope), then the common EUR/USD/GBP
|
||||
* and a broad set of other ISO 4217 codes. Stored value is the bare 3-letter
|
||||
* code (e.g. "CHF").
|
||||
*/
|
||||
export const CURRENCY_CODES: string[] = [
|
||||
'CHF', 'EUR', 'USD', 'GBP',
|
||||
'AUD', 'CAD', 'CNY', 'CZK', 'DKK', 'HKD', 'HUF', 'ILS', 'INR', 'JPY',
|
||||
'NOK', 'NZD', 'PLN', 'RON', 'SEK', 'SGD', 'THB', 'TRY', 'ZAR',
|
||||
];
|
||||
|
||||
/**
|
||||
* Normalise a stored/typed currency value to a known code. Upper-cases + trims
|
||||
* (so an old free-text "chf" resolves to "CHF"). Returns the matched code, or
|
||||
* the cleaned input if it isn't in the known list (caller preserves it as an
|
||||
* extra option so nothing is lost), or '' for empty input.
|
||||
*/
|
||||
export function normalizeCurrency(value: string | null | undefined): string {
|
||||
const cleaned = (value || '').trim().toUpperCase();
|
||||
if (!cleaned) return '';
|
||||
return CURRENCY_CODES.includes(cleaned) ? cleaned : cleaned;
|
||||
}
|
||||
|
||||
/** Build the option list, prepending an unknown-but-set value so it's preserved. */
|
||||
export function currencyOptions(current: string | null | undefined): string[] {
|
||||
const cur = normalizeCurrency(current);
|
||||
if (cur && !CURRENCY_CODES.includes(cur)) return [cur, ...CURRENCY_CODES];
|
||||
return CURRENCY_CODES;
|
||||
}
|
||||
Reference in New Issue
Block a user