How to add multi-currency field
Glossary Item Box
One of the common configuration tasks is adding a "multi-currency field" control element on a page. The multi-currency field enables users to enter monetary sums, specify currencies and exchange rates. If a user changes the currency of a multi-currency field, the amount in it will be automatically re-calculated according to the current exchange rate. Fig. 1 shows an example of a multi-currency field in the system interface.
Fig.1 — Multi-currency field
How to add a multi-currency field on an edit page
- Add 4 fields to the view model:
- [Currency]
- [Exchange rate]
- [Amount]
- [Amount in base currency]
The object itself must contain only the [Amount] field. The rest of the fields can be virtual, unless the business task requires their values to be stored in the database.
- Specify 3 modules in the view model class declaration as dependencies:
- MoneyModule,
- MultiCurrencyEdit,
- MultiCurrencyEditUtilities.
- Connect Terrasoft.MultiCurrencyEditUtilities mixin to the view model and initialize it in the overridden init method.
- Add a configuration object with the multi-currency field settings to the diff array of the edit page schema. In addition to common control element properties, the values property must contain:
- primaryAmount – name of the column that contains the amount in the base currency
- currency – name of the column that references the currency lookup
- rate – name of the column that contains the currency exchange rate
- generator – control element generator. Specify "MultiCurrencyEditViewGenerator.generate".
- Add recalculation logic. Apply the calculated field mechanism, as described in the How to add a computed field article.
Below is a multi-currency field implementation example.
Case description
Add a multi-currency [Amount] field to the project edit page.
Case implementation
1. Create replacing Project object and add [Currency], [Amount] and [PrimaryAmount] columns
For more information on creating replacing objects and adding columns, please refer to the "Adding a new field to the edit page" article.
Column properties are available on Fig. 2, 3 and 4,
Fig. 2. [Currency] column properties
Fig. 3. [Amount] column properties
Fig. 4. [PrimaryAmount] column properties
2. Create a replacing edit page for the [Projects] section in the custom package
Create a replacing client module and specify [ProjectPageV2] as the parent object (Fig. 5).
For more information on creating replacing pages, please refer to the "Creating a custom client module schema" article.
Fig. 5. Properties of the replacing project edit page
3. The [Currency rate] field must be declared directly in the attributes value of the edit page schema
"CurrencyRate": {
dataValueType: Terrasoft.DataValueType.FLOAT,
}
4. Specify the following modules as dependencies when declaring view model class:
- MoneyModule,
- MultiCurrencyEdit,
- MultiCurrencyEditUtilities.
define("ProjectPageV2", ["MoneyModule", "MultiCurrencyEdit", "MultiCurrencyEditUtilities"], function(MoneyModule, MultiCurrencyEdit, MultiCurrencyEditUtilities) {
5. Connect the Terrasoft.MultiCurrencyEditUtilities mixin to the view model
mixins: { /** * Multi-currency management mixin in the record edit page. */ MultiCurrencyEditUtilities: "Terrasoft.MultiCurrencyEditUtilities" }
Additionally, initialize the mixin in the overridden init method:
// Overriding the Terrasoft.BasePageV2.init base method init: function() { // Initializing the multi-currency management mixin. this.mixins.MultiCurrencyEditUtilities.init.call(this); // Calling parent implementation of the init method. this.callParent(arguments); },
6. Add a configuration object with multi-currency field settings to the diff array
diff: /**SCHEMA_DIFF*/[ { "operation": "insert", // Parent container name. "parentName": "Header", "propertyName": "items", // Control element name. "name": "Amount", "values": { // View model column name in which the binding is done. "bindTo": "Amount", // Item location in container. "layout": {"column": 0, "row": 2, "colSpan": 12}, // Name of the column, which contains amount in base currency. "primaryAmount": "PrimaryAmount", // Name of the column, which contains the currency of the amount. "currency": "Currency", // Name of the column, which contains the currency rate. "rate": "CurrencyRate", // The property that determines if the base currency amount field is editable. "primaryAmountEnabled": false, // Control element view generator. "generator": "MultiCurrencyEditViewGenerator.generate" } } ],/**SCHEMA_DIFF*/
7. Implement the amount recalculation logic
In the attributes property, add dependencies for the [CurrencyRate] and [Amount] attributes. Add handler methods for these dependencies to the methods collection.
Below is the complete source code of the edit page.
// Specify modules as dependencies in the view model class declaration // MoneyModule, MultiCurrencyEdit, MultiCurrencyEditUtilities define("ProjectPageV2", ["MoneyModule", "MultiCurrencyEdit", "MultiCurrencyEditUtilities"], function (MoneyModule, MultiCurrencyEdit, MultiCurrencyEditUtilities) { return { // Edit page object schema name. entitySchemaName: "Project", // The attributes property of the view model. attributes: { // View model column name. "CurrencyRate": { // Data type of the view model column. dataValueType: Terrasoft.DataValueType.FLOAT, // Array of configuration objects that determine the dependencies of the [CurrencyRate] column. dependencies: [ { // The [CurrencyRate] column value depends on the [Currency] column value. columns: ["Currency"], // Handler method that is called when the value in the [Currency] column changes. methodName: "setCurrencyRate" } ] }, // View model column name. "Amount": { // View model column data type. dataValueType: Terrasoft.DataValueType.FLOAT, // Array of configuration objects that determine dependencies of the [Amount] column. dependencies: [ { // Value in the [Amount] column. columns: ["Amount"], // Handler method, which is called when the value in the [Amount] column changes. methodName: "recalculatePrimaryAmount" } ] } }, // Collection of view model mixins. mixins: { // Multi-currency management mixin on the edit page. MultiCurrencyEditUtilities: "Terrasoft.MultiCurrencyEditUtilities" }, // Collection of page view model methods. methods: { // Overriding base method Terrasoft.BasePageV2.init. init: function () { // Initialize multi-currency management mixin. this.mixins.MultiCurrencyEditUtilities.init.call(this); // Calling parent implementation of the init method. this.callParent(arguments); }, // Handler method, which is called on changing the currency. setCurrencyRate: function () { // Calling the LoadCurrencyRate function of the MoneyModule, which calculates // currency exchange rate. [Currency] and [CurrencyRate] are passed as parameters. MoneyModule.LoadCurrencyRate.call(this, "Currency", "CurrencyRate", this.get("StartDate"), function () { var division = this.getCurrencyDivision(); MoneyModule.RecalcCurrencyValue.call(this, "CurrencyRate", "Amount", "PrimaryAmount", division); } ); }, // Auxiliary method, which returns delimiting coefficient for a currency. getCurrencyDivision: function () { var currency = this.get("Currency"); return currency && currency.Division; }, // Handler method, which is called if the amount is modified and conducts recalculation of amount // in base currency. recalculatePrimaryAmount: function () { // Determining the delimiting coefficient for the current currency. var division = this.getCurrencyDivision(); // Calling the RecalcBaseValue function of the MoneyModule, which calculates // amount for the [Amount in base currency] field. Column names for // [CurrencyRate], [Amount], [PrimaryAmount], as well as delimiting coefficient are passed as parameters. MoneyModule.RecalcBaseValue.call(this, "CurrencyRate", "Amount", "PrimaryAmount", division); } }, // Multi-currency field visualization setup. diff: /**SCHEMA_DIFF*/[ // Metadata to add the [Amount] field. { "operation": "insert", // Parent container name. "parentName": "Header", "propertyName": "items", // Control element name. "name": "Amount", "values": { // View model column name, to which the binding is made. "bindTo": "Amount", // Element position within container. "layout": { "column": 0, "row": 2, "colSpan": 12 }, // Name of the column that contains amount in base currency. "primaryAmount": "PrimaryAmount", // Name of the column that contains the currency. "currency": "Currency", // Name of the column that contains exchange rate. "rate": "CurrencyRate", // Property that determines availability of the base currency amount field. "primaryAmountEnabled": false, // Control element view generator. "generator": "MultiCurrencyEditViewGenerator.generate" } } ],/**SCHEMA_DIFF*/ details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/ }; });
8. Save page replacing schema
After saving the schema and updating the web page, a new multi-currency edit field [Amount] will appear on the page (Fig. 6).
Fig. 6. Case results