Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/tax-packs.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ It must not embed scripts, call network endpoints, or introduce a second tax-cal
## Authoring a new pack

1. Copy the shape of the bundled pack — `main/tax-packs/generic.json` — as your starting point, then add real `categories` and `rules` for your country.
2. Give it a unique `id` using the lowercase, hyphenated full country name (for example, `official-india`, `official-thailand`, or `official-united-states`). Keep `country` as its ISO alpha-2 code (for example, `IN`, `TH`, or `US`), because FloCafe uses that field to match the store. Set `publisher` to your name/org (anything other than `local` — `local` is reserved for the in-app manual/unbundled pack and can never be published), and fill in `jurisdiction`, `currency`, `taxRounding`, `payableRounding`.
2. Give it a unique `id` using the lowercase, hyphenated full country name (for example, `official-argentina`, `official-india`, `official-thailand`, or `official-united-states`). Keep `country` as its ISO alpha-2 code (for example, `AR`, `IN`, `TH`, or `US`), because FloCafe uses that field to match the store. Set `publisher` to your name/org (anything other than `local` — `local` is reserved for the in-app manual/unbundled pack and can never be published), and fill in `jurisdiction`, `currency`, `taxRounding`, `payableRounding`.
3. Define `categories` and `rules`. Every category referenced by `defaultCategories` or by a product must exist. `unclassifiedCategoryId` must point at a real category (usually a zero-rate one). A rate table can use multiple regional components (each its own rule) or a single flat rule, depending on how the country's tax works.
4. Add the file to `main/tax-packs/` in this repo (not a new repo — see "Where packs live" below) and open a PR. Only the generic/manual no-tax pack is bundled with and auto-activated by a new installation. Every official country pack is catalog-only: an owner explicitly enables the matching pack from Settings → Tax Configuration, where FloCafe downloads, verifies, installs, and activates it.
5. Add test vectors: extend `tests/tax-pack-management.test.ts` (activation validation) and, ideally, `tests/tax-engine.test.ts` / `tests/integration-tax.test.ts` with a scenario proving your rules produce the expected components, totals, and rounding for at least one representative order.
Expand Down
487 changes: 372 additions & 115 deletions frontend/src/components/settings/TaxConfigurationPanel.tsx

Large diffs are not rendered by default.

145 changes: 145 additions & 0 deletions frontend/src/lib/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,151 @@
"settings.status": "Status",
"settings.storeDetails": "Store Details",
"settings.taxConfiguration": "Tax Config",
"settings.tax.configTitle": "Tax configuration",
"settings.tax.configDescription": "Enable the verified tax rules for your store country. FloCafe applies the standard product tax group automatically; exceptions can be changed per product.",
"settings.tax.managerReadOnlyNotice": "Managers can review packs, overrides, audit history, and run test calculations. Only owners can make changes.",
"settings.tax.onlyOwnersCanEnable": "Only owners can enable taxes",
"settings.tax.onlyOwnersCanChange": "Only owners can change tax configuration",
"settings.tax.notEnabledTitle": "Country taxes are not enabled",
"settings.tax.loading": "Loading tax configuration…",
"settings.tax.refreshButton": "Refresh",
"settings.tax.notEnabledDescription": "FloCafe is using the generic no-tax profile. When you enable taxes, FloCafe will automatically install the verified plugin for {country}.",
"settings.tax.enableButton": "Enable taxes",
"settings.tax.enablingButton": "Enabling…",
"settings.tax.unavailableMessage": "Tax support for {country} is not available yet. We have requested the plugin from the FloCafe team and will build it soon. Taxes remain off until it is ready.",
"settings.tax.unavailableQueued": "Your request is queued for the team.",
"settings.tax.manualConfigTitle": "Manual tax rate",
"settings.tax.manualConfigDescription": "FloCafe will create a local tax pack from these values and use it for {country}. You can edit per-product rates later through Merchant overrides.",
"settings.tax.manualConfigReplaceWarning": "The verified pack {pack} is active for this country. Saving a manual rate replaces it; its merchant overrides are kept but stop applying until you activate that pack again from Advanced tax tools.",
"settings.tax.manualConfigReplaceConfirm": "Replace the active tax pack {pack} with your manual rate?",
"settings.tax.replaceWithManualConfig": "Replace with manual rate",
"settings.tax.rateLabel": "Rate (%)",
"settings.tax.ratePlaceholder": "21",
"settings.tax.pricingLabel": "Menu prices",
"settings.tax.pricingInclusive": "Already include tax",
"settings.tax.pricingExclusive": "Do not include tax",
"settings.tax.pricingHintInclusive": "The price you set on a product already contains the tax. The customer pays exactly the menu price and the receipt shows how much of it was tax.",
"settings.tax.pricingHintExclusive": "The price you set on a product is before tax. The tax is added on top, so the customer pays more than the menu price.",
"settings.tax.pricingExampleInclusive": "Example at {rate}%: a product priced 100 still costs the customer 100, of which {tax} is tax.",
"settings.tax.pricingExampleExclusive": "Example at {rate}%: a product priced 100 costs the customer {total} — {tax} of tax is added at checkout.",
"settings.tax.registrationLabel": "Registration label",
"settings.tax.registrationPlaceholder": "Tax registration",
"settings.tax.registrationHint": "Name of your tax number as it should print on receipts (CUIT, VAT no., GSTIN…).",
"settings.tax.saveManualConfig": "Save manual tax configuration",
"settings.tax.savingManualConfig": "Saving…",
"settings.tax.taxesEnabledTitle": "Taxes are enabled",
"settings.tax.taxesEnabledOfficial": "FloCafe is using the verified plugin for {country}.",
"settings.tax.taxesEnabledLocal": "FloCafe is using your manual tax configuration for {country}.",
"settings.tax.trustStatusLocal": "Local pack · manual configuration",
"settings.tax.turnTaxesOff": "Turn taxes off",
"settings.tax.advancedToolsTitle": "Advanced tax tools",
"settings.tax.advancedToolsDescription": "Optional testing, charge rules, exceptions, pack details, and audit history. Most stores never need these.",
"settings.tax.installedPacksTitle": "Installed country packs",
"settings.tax.installedPacksDescription": "FloCafe selects the plugin for {country} automatically.",
"settings.tax.noActiveVersion": "This pack has no active version yet — activate an installed version below.",
"settings.tax.installedVersions": "Installed versions",
"settings.tax.activeBadge": "Active",
"settings.tax.testCalcTitle": "Test calculation",
"settings.tax.testCalcDescription": "Uses the active pack and the same tax engine as checkout. It does not save a transaction.",
"settings.tax.testCalcInactivePack": "This installed pack is not active for the current store. Select the active pack to test it.",
"settings.tax.testCalcAmountPlaceholder": "Amount",
"settings.tax.testCalcBehaviorCountryDefault": "Country default",
"settings.tax.testCalcBehaviorExclusive": "Tax exclusive",
"settings.tax.testCalcBehaviorInclusive": "Tax inclusive",
"settings.tax.testCalcBehaviorExempt": "Exempt",
"settings.tax.testCalcButton": "Calculate",
"settings.tax.testCalcTaxableBase": "Taxable base",
"settings.tax.testCalcTax": "Tax",
"settings.tax.testCalcPayableTotal": "Payable total",
"settings.tax.testCalcActivationChecksPassed": "{passed} of {total} activation checks passed",
"settings.tax.testCalcActivationChecksFailed": "Activation checks failed",
"settings.tax.chargeCategoriesTitle": "Charge tax categories",
"settings.tax.chargeCategoriesDescription": "Choose the category used for each order-level charge. Unconfigured charges keep the legacy behavior and remain untaxed.",
"settings.tax.chargeNotConfigured": "Not configured · legacy behavior",
"settings.tax.merchantOverridesTitle": "Merchant overrides",
"settings.tax.merchantOverridesDescription": "Overrides take priority over product and category assignments, but transaction exemptions still win.",
"settings.tax.merchantOverridesStoreWide": "Store-wide charge",
"settings.tax.merchantOverridesTarget": "Target",
"settings.tax.merchantOverridesCategory": "Category",
"settings.tax.merchantOverridesUpdated": "Updated",
"settings.tax.merchantOverridesActions": "Actions",
"settings.tax.merchantOverridesEdit": "Edit",
"settings.tax.merchantOverridesRemove": "Remove",
"settings.tax.merchantOverridesSave": "Save override",
"settings.tax.merchantOverridesAdd": "Add override",
"settings.tax.merchantOverridesCancel": "Cancel",
"settings.tax.merchantOverridesReadOnly": "Read only",
"settings.tax.merchantOverridesEmpty": "No merchant overrides. Official pack behavior is in use.",
"settings.tax.merchantOverridesChoose": "Choose {type}",
"settings.tax.packReferenceTitle": "Pack reference",
"settings.tax.packReferenceDescription": "Read-only categories and rules from the active installed JSON pack.",
"settings.tax.packReferenceDefaultBehavior": "Default behavior",
"settings.tax.packReferenceRules": "Rules",
"settings.tax.packReferenceType": "Type",
"settings.tax.packReferenceValue": "Value",
"settings.tax.packReferenceScope": "Scope",
"settings.tax.packReferenceDependsOn": "Depends on",
"settings.tax.packReferenceNone": "None",
"settings.tax.auditHistoryTitle": "Audit history",
"settings.tax.auditHistoryEmpty": "No tax configuration changes recorded.",
"settings.tax.entityProduct": "Product",
"settings.tax.entityAddon": "Add-on",
"settings.tax.entityPackaging": "Packaging charge",
"settings.tax.entityDelivery": "Delivery charge",
"settings.tax.entityServiceCharge": "Service charge",
"settings.tax.auditBundleInstall": "Version {version} from the application bundle",
"settings.tax.auditDownloadInstall": "Version {version} verified and installed from GitHub Releases",
"settings.tax.auditCreateOverride": "{entityType} {entityId} → {categoryId}",
"settings.tax.auditUpdateOverride": "{entityType} {entityId}: {before} → {after}",
"settings.tax.auditResetOverride": "{entityType} {entityId} reset to official behavior",
"settings.tax.auditActivatePack": "Previous version: {previousVersionId}",
"settings.tax.auditRollbackPack": "Rolled back from {previousVersionId}",
"settings.tax.auditActivateManualConfig": "Manual configuration (rate {rate}%, {inclusive})",
"settings.tax.auditActivateManualConfigInclusive": "inclusive",
"settings.tax.auditActivateManualConfigExclusive": "exclusive",
"settings.tax.actionInstallBundledPack": "Bundled pack installed",
"settings.tax.actionInstallDownloadedPack": "Downloaded pack installed",
"settings.tax.actionActivatePack": "Pack activated",
"settings.tax.actionRollbackPack": "Pack rolled back",
"settings.tax.actionCreateOverride": "Override added",
"settings.tax.actionUpdateOverride": "Override edited",
"settings.tax.actionResetOverride": "Override removed",
"settings.tax.actionRemapCategories": "Tax categories remapped",
"settings.tax.auditRemapCategories": "{total} product and add-on assignments moved because the new pack does not define their category ({categories})",
"settings.tax.auditActivateManualConfigReplaced": "· replaced {pack}; {dormant} merchant overrides stopped applying",
"settings.tax.toastManualSavedChanges": "{remapped} product/add-on tax categories were remapped and {dormant} merchant overrides stopped applying. Check the audit history.",
"settings.tax.toastEnabledFor": "Taxes enabled for {country}",
"settings.tax.toastEnableError": "Could not enable taxes for this country",
"settings.tax.toastUnavailable": "Tax support for {country} is not available yet",
"settings.tax.toastDisabled": "Taxes disabled",
"settings.tax.toastDisableError": "Could not disable taxes",
"settings.tax.toastManualSaved": "Manual tax configuration saved ({passed}/{total} checks passed)",
"settings.tax.toastManualSaveError": "Could not save manual tax configuration",
"settings.tax.toastRateRange": "Enter a tax rate between 0 and 100",
"settings.tax.toastPickActivePack": "Select the active store-country pack to run a checkout calculation",
"settings.tax.toastCalcError": "Could not calculate tax",
"settings.tax.auditActorUnknown": "Unknown user",
"settings.tax.auditActorSystem": "System",
"settings.tax.toastLoadError": "Could not load tax configuration",
"settings.tax.toastLoadDetailError": "Could not load tax pack details",
"settings.tax.toastOverrideTargetRequired": "Choose both a target and a tax category",
"settings.tax.toastTestAmount": "Please enter a valid positive test calculation amount",
"settings.tax.toastOverrideAdded": "Tax override added",
"settings.tax.toastOverrideUpdated": "Tax override updated",
"settings.tax.toastOverrideRemoved": "Tax override removed; official pack behavior restored",
"settings.tax.toastOverrideSaveError": "Could not save tax override",
"settings.tax.toastOverrideRemoveError": "Could not remove tax override",
"settings.tax.toastPackagingCategorySaved": "Packaging tax category saved",
"settings.tax.toastDeliveryCategorySaved": "Delivery tax category saved",
"settings.tax.toastServiceCategorySaved": "Service charge tax category saved",
"settings.tax.toastPackagingRestored": "Packaging restored to legacy behavior",
"settings.tax.toastDeliveryRestored": "Delivery restored to legacy behavior",
"settings.tax.toastServiceRestored": "Service charge restored to legacy behavior",
"settings.tax.toastChargeCategorySaveError": "Could not save the charge tax category",
"settings.tax.toastPreviousVersionNone": "none",
"settings.tax.toastPreviousVersionUnknown": "unknown",
"settings.tax.supportTicketSubject": "Request tax support for {country}",
"settings.tax.supportTicketMessage": "The merchant selected {country} and enabled taxes, but no verified country tax plugin is currently available. Please create and publish the plugin.",
"settings.orderNumberFormat": "Order Number Format",
"settings.orderNumberPrefix": "Prefix",
"settings.orderNumberPreview": "Preview",
Expand Down
Loading
Loading