The currencies module in src/cluster_erp/modules/currencies/ serves three kinds of finance reference data: currencies, exchange rates, and payment terms. The currency and exchange-rate models live in the platform core, src/cluster_erp/core/currencies.py; this module seeds them, mounts their routes, and declares their screens. Payment terms are the module's own table. Other modules use these records as foreign-key sources in their forms.
At a glance¶
| Item | Value | Source |
|---|---|---|
| Package | src/cluster_erp/modules/currencies/ |
folder |
| Module class | Module |
src/cluster_erp/modules/currencies/module.py:18 |
name / version |
currencies / 0.1.0 |
src/cluster_erp/modules/currencies/module.py:19-25 |
| API prefix | /api/v1/currencies (ModuleBase.api_prefix) |
src/cluster_erp/core/module_base.py:37-38 |
| Sub-modules | 2 folders: exchange_rates, payment_terms; plus the currency routes in server/routes/currencies.py |
folder listing, src/cluster_erp/modules/currencies/module.py:74-81 |
| Tables | 3: core_currencies, core_exchange_rates (defined in the core), core_payment_terms |
src/cluster_erp/core/currencies.py:58, src/cluster_erp/core/currencies.py:92, src/cluster_erp/modules/currencies/payment_terms/models.py:13 |
| Entities in metadata | 3: currency, exchange_rate, payment_term |
src/cluster_erp/modules/currencies/module.py:146-150 |
| Routes | 20: 7 currency routes, 8 exchange-rate routes, 5 payment-term routes | grep for @router. |
| Web app presence | No catalogue app; the settings appear under System Apps (webapp/i18n/en.json key settings.system_apps) |
webapp/js/home.js (SYSTEM_APP_SETTINGS) |
| Desktop presence | Generic widgets only; no folder in src/cluster_erp/desktop/modules/ |
folder |
What the module does¶
- Seeds the ISO 4217 currency list and the standard payment terms at every start, without overwriting existing rows (
src/cluster_erp/modules/currencies/module.py:31-62). - Lists, creates, updates, and soft-deletes currencies, and refreshes the list from the bundled ISO data (
src/cluster_erp/server/routes/currencies.py:21-98). - Stores exchange rates per currency pair and date, converts an amount, and imports the daily rates of the Turkish central bank (
src/cluster_erp/modules/currencies/exchange_rates/routes.py:29-144). - Keeps payment terms with a category, net days, and early-payment discount (
src/cluster_erp/modules/currencies/payment_terms/models.py:12-62).
Sub-modules¶
| Sub-module | Purpose | Main entities | Router | Source |
|---|---|---|---|---|
| currency routes | Currency list | Currency |
/api/v1/currencies (module root) |
src/cluster_erp/server/routes/currencies.py:18 |
exchange_rates |
Rates, conversion, central-bank import | ExchangeRate |
/api/v1/currencies/exchange-rates |
src/cluster_erp/modules/currencies/exchange_rates/routes.py:29 |
payment_terms |
Payment terms | PaymentTerm |
/api/v1/currencies/payment-terms |
src/cluster_erp/modules/currencies/payment_terms/routes.py:21 |
The currency router is defined in the server layer and included first under the module router; the whole router depends on the currencies app entitlement (src/cluster_erp/modules/currencies/module.py:64-82). exchange_rates/models.py only re-exports the core model (src/cluster_erp/modules/currencies/exchange_rates/models.py:1-5).
Data model¶
| Entity | Table | Key fields | Notes | Source |
|---|---|---|---|---|
Currency |
core_currencies |
code, numeric_code, name, symbol, decimal_places, translations, is_active |
code and numeric code unique among live rows | src/cluster_erp/core/currencies.py:57-88 |
ExchangeRate |
core_exchange_rates |
base_currency_code, target_currency_code, buy_rate, sell_rate, rate, unit, rate_date, source |
one live row per pair and date; rates Numeric(18, 6) |
src/cluster_erp/core/currencies.py:91-132 |
PaymentTerm |
core_payment_terms |
code, name, category, net_days, discount_percent, discount_days, translations, is_active, sort_order |
code unique among live rows | src/cluster_erp/modules/currencies/payment_terms/models.py:12-62 |
The seeding and the core routes are also described on reference data and core i18n.
Screens and metadata¶
get_metadata gives the module the label Currencies & Payment Terms (Turkish Para Birimleri ve Ödeme Koşulları) and a sidebar group Finance Settings with two sections: a settings view with the tabs currency, exchange_rate, and payment_term, and a Payment Terms list (src/cluster_erp/modules/currencies/module.py:103-151). The web app lists the module in SYSTEM_APP_SETTINGS, so the settings tabs open from Settings, then System Apps; the code comment states that finance reference data has no app of its own (webapp/js/home.js (SYSTEM_APP_SETTINGS)). Payment-term categories are offered as six choices: advance, net, early discount, end of month, installment, and international (src/cluster_erp/modules/currencies/metadata.py:294-299).
Status and actions¶
Records have an is_active flag and no status field (src/cluster_erp/core/currencies.py:88, src/cluster_erp/modules/currencies/payment_terms/models.py:53-57).
| Action | Label | Condition | Endpoint | Permission | Source |
|---|---|---|---|---|---|
update_from_internet (currency) |
Update from Internet | none (global) | POST /update-from-internet |
currency.create |
src/cluster_erp/modules/currencies/metadata.py:29-37, src/cluster_erp/server/routes/currencies.py:33-40 |
sync_tcmb (exchange rate) |
Sync TCMB | none (global) | POST /exchange-rates/sync-tcmb |
exchange_rate.sync |
src/cluster_erp/modules/currencies/metadata.py:155-163, src/cluster_erp/modules/currencies/exchange_rates/routes.py:131-144 |
Business rules¶
- The currency seed takes a curated list with symbols and translations and adds every other ISO 4217 currency from
pycountry; a currency whose numeric code is blank or already used is skipped (src/cluster_erp/core/currencies.py:1811-1852). Existing codes are left unchanged (src/cluster_erp/core/currencies.py:281-309). - Update from Internet reads the same bundled data and refreshes numeric code, name, symbol, and translations of existing currencies; it makes no network request (
src/cluster_erp/core/currencies.py:311-357). - Conversion between the same currency returns the amount at rate 1. Otherwise it uses the direct rate of the given date, or the newest direct rate when no date is given, as
amount x rate / unit; failing that, the matching reverse rate asamount x unit / rate. Results are rounded to six places (src/cluster_erp/core/currencies.py:383-446). When no rate exists, the route answers not found (src/cluster_erp/modules/currencies/exchange_rates/routes.py:66-79). quantizein the conversion passes no rounding mode, and agrepforgetcontextandsetcontextinsrc/finds no change to the decimal context, so the default context of Python'sdecimalmodule applies.- Sync TCMB fetches the central bank's daily XML from the URL in the setting
tcmb_url, with the timeouttcmb_timeout_seconds. It stores each foreign currency againstTRYwith buying, selling, and average rate, creating or updating the row of that date (src/cluster_erp/modules/currencies/exchange_rates/routes.py:131-144,src/cluster_erp/core/currencies.py:448-552,src/cluster_erp/config/settings.py:418-420). The fetch runs in a worker thread; a failure is returned as an error count, not raised (src/cluster_erp/core/currencies.py:454-461). - A manual rate gets the source
manualunless another is given; currency codes are stored in upper case (src/cluster_erp/modules/currencies/exchange_rates/schemas.py:16-24,src/cluster_erp/modules/currencies/exchange_rates/services.py:80-93). - A payment term code must be free among live terms (
src/cluster_erp/modules/currencies/payment_terms/services.py:452-455). The seed holds 45 standard terms in six categories (src/cluster_erp/modules/currencies/payment_terms/services.py:32-409, entries with acodekey). assert_known_currencyrefuses a code that is not a live, active currency, withCURRENCY_UNKNOWNand HTTP 422 (src/cluster_erp/core/currencies.py:30-49). At this commit it is called by thesubscriptionsmodule (grepforassert_known_currency).
Events and queries¶
The module consumes no contract and produces none; register_events is empty (src/cluster_erp/modules/currencies/module.py:84-85). Other modules use its records as foreign-key sources in metadata: 33 ForeignKeySource entries with module="currencies" in 10 files of other modules (grep).
| Direction | Contract class | Handler or emitter | Source |
|---|---|---|---|
| none | none | none | src/cluster_erp/modules/currencies/module.py:84-85 |
Permissions¶
| Permission key | Used by | Source |
|---|---|---|
currency.read, .create, .update, .delete, .seed |
currency routes | src/cluster_erp/server/routes/currencies.py:25-94 |
exchange_rate.read, .create, .update, .delete, .sync |
rate routes; bulk delete also uses exchange_rate.delete |
src/cluster_erp/modules/currencies/exchange_rates/routes.py:40-134 |
payment_term.read, .create, .update, .delete |
payment-term routes | src/cluster_erp/modules/currencies/payment_terms/routes.py:28-82 |
Privacy, retention, and history¶
The module stores no personal data and has no privacy_handlers.py. Deletion sets deleted_at (src/cluster_erp/core/currencies.py:273-279, src/cluster_erp/modules/currencies/exchange_rates/services.py:109-133). Changes are captured by change history.
Analytics facts¶
This module has no analytics_facts.py.
Settings and reference data¶
| Setting | Meaning | Source |
|---|---|---|
tcmb_url |
Address of the central-bank daily rates file | src/cluster_erp/config/settings.py:416 |
tcmb_sync_on_startup |
Declared with default False; a grep finds no code that reads it |
src/cluster_erp/config/settings.py:417 |
tcmb_timeout_seconds |
Fetch timeout, 15 by default | src/cluster_erp/config/settings.py:418 |
See settings reference.
Tests¶
Found by a grep for modules.currencies and core.currencies in tests/ and by file name in web-client/.
| Kind | File | Covers |
|---|---|---|
| pytest | tests/test_tenant_fields.py |
imports the payment-term model in a wider contract |
| pytest | tests/test_fk_indexes.py |
imports the core currency models for the index check |
| e2e | web-client/_e2e_deseng_currencies.mjs |
currency settings under System Apps and the absence of a separate app |
Discrepancies¶
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| currency | Currency |
A reference-data row for an ISO 4217 currency with its code, symbol, and decimal places. | para birimi | src/cluster_erp/core/currencies.py:57 |
| exchange rate | ExchangeRate |
The rate of a base currency in a target currency on a date, per unit. |
Kur | src/cluster_erp/core/currencies.py:91 |
| payment term | PaymentTerm |
A coded rule for when and how an invoice is paid. | Ödeme koşulu | src/cluster_erp/modules/currencies/payment_terms/models.py:12 |
Related pages¶
- Modules index
- Reference data and core i18n
- Money and Decimal
- Settings reference
- API reference for this module
Verified against commit 92f8051 on 2026-11-13.