From 4650b1eeda9ee112efe8427168a1fe681c9fae7d Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Thu, 2 Dec 2021 14:10:40 +0530 Subject: [PATCH 01/25] refactor: shift pesa init with currency to books --- src/initialization.js | 3 +++ src/pages/SetupWizard/setupCompany.js | 6 ++++- src/utils.js | 36 +++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/initialization.js b/src/initialization.js index e2eb4772..e61be3c2 100644 --- a/src/initialization.js +++ b/src/initialization.js @@ -7,6 +7,7 @@ import postStart from '../server/postStart'; import { DB_CONN_FAILURE } from './messages'; import migrate from './migrate'; import { getSavePath } from './utils'; +import { callInitializeMoneyMaker } from './utils'; export async function createNewDatabase() { const { canceled, filePath } = await getSavePath('books', 'db'); @@ -49,6 +50,8 @@ export async function connectToLocalDatabase(filePath) { return { connectionSuccess: false, reason: DB_CONN_FAILURE.CANT_CONNECT }; } + await callInitializeMoneyMaker(); + try { await runRegionalModelUpdates(); } catch (error) { diff --git a/src/pages/SetupWizard/setupCompany.js b/src/pages/SetupWizard/setupCompany.js index 42ce9332..80c8cfc7 100644 --- a/src/pages/SetupWizard/setupCompany.js +++ b/src/pages/SetupWizard/setupCompany.js @@ -3,6 +3,7 @@ import frappe from 'frappejs'; import countryList from '~/fixtures/countryInfo.json'; import generateTaxes from '../../../models/doctype/Tax/RegionalEntries'; import regionalModelUpdates from '../../../models/regionalModelUpdates'; +import { callInitializeMoneyMaker } from '../../utils'; export default async function setupCompany(setupWizardValues) { const { @@ -17,6 +18,9 @@ export default async function setupCompany(setupWizardValues) { } = setupWizardValues; const accountingSettings = frappe.AccountingSettings; + const currency = countryList[country]['currency']; + await callInitializeMoneyMaker(currency); + await accountingSettings.update({ companyName, country, @@ -25,7 +29,7 @@ export default async function setupCompany(setupWizardValues) { bankName, fiscalYearStart, fiscalYearEnd, - currency: countryList[country]['currency'], + currency, }); const printSettings = await frappe.getSingle('PrintSettings'); diff --git a/src/utils.js b/src/utils.js index baa28c2c..3219a23f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -351,3 +351,39 @@ export function titleCase(phrase) { }) .join(' '); } + +export async function getIsSetupComplete() { + try { + const { setupComplete } = await frappe.getSingle('AccountingSettings'); + return !!setupComplete; + } catch { + return false; + } +} + +export async function getCurrency() { + let currency = frappe?.AccoutingSettings?.currency ?? undefined; + + if (!currency) { + try { + currency = ( + await frappe.db.getSingleValues({ + fieldname: 'currency', + parent: 'AccountingSettings', + }) + )[0].value; + } catch (err) { + currency = undefined; + } + } + + return currency; +} + +export async function callInitializeMoneyMaker(currency) { + currency ??= await getCurrency(); + if (!currency && frappe.pesa) { + return; + } + await frappe.initializeMoneyMaker(currency); +} From 44a60a84ddb745c3e0c294f3967b3d0e2d7761e6 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Thu, 2 Dec 2021 14:50:32 +0530 Subject: [PATCH 02/25] patch: convert existing currency values to precision adjusted int str --- patches/0.0.4/convertCurrencyToStrings.js | 41 +++++++++++++++++++++++ patches/patches.json | 5 +++ 2 files changed, 46 insertions(+) create mode 100644 patches/0.0.4/convertCurrencyToStrings.js diff --git a/patches/0.0.4/convertCurrencyToStrings.js b/patches/0.0.4/convertCurrencyToStrings.js new file mode 100644 index 00000000..a4a72ca7 --- /dev/null +++ b/patches/0.0.4/convertCurrencyToStrings.js @@ -0,0 +1,41 @@ +import frappe from 'frappejs'; + +function getTablesToConvert() { + // Do not change loops to map, doesn't work for some reason. + const toConvert = []; + for (let key in frappe.models) { + const model = frappe.models[key]; + + const fieldsToConvert = []; + for (let i in model.fields) { + const field = model.fields[i]; + + if (field.fieldtype === 'Currency') { + fieldsToConvert.push(field.fieldname); + } + } + + if (fieldsToConvert.length > 0 && !model.isSingle && !model.basedOn) { + toConvert.push({ name: key, fields: fieldsToConvert }); + } + } + + return toConvert; +} + +export default async function execute() { + const toConvert = getTablesToConvert(); + for (let { name, fields } of toConvert) { + const rows = await frappe.db.knex(name); + const convertedRows = rows.map((row) => { + for (let field of fields) { + if (row[field] === null) { + continue; + } + row[field] = frappe.pesa(row[field]).store; + } + return row; + }); + await frappe.db.prestigeTheTable(name, convertedRows); + } +} diff --git a/patches/patches.json b/patches/patches.json index 31ad50ee..e450d707 100644 --- a/patches/patches.json +++ b/patches/patches.json @@ -3,5 +3,10 @@ "version": "0.0.3", "fileName": "makePaymentRefIdNullable", "beforeMigrate": true + }, + { + "version": "0.0.4", + "fileName": "convertCurrencyToStrings", + "beforeMigrate": true } ] From ec3558f513de1251639d54916eb45cc7eebd6cee Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Thu, 23 Dec 2021 14:40:45 +0530 Subject: [PATCH 03/25] fix: call validate on blur - number type Float, Int - remove floatPrecision --- accounting/ledgerPosting.js | 2 +- src/components/Controls/Base.vue | 53 +++++++++++++++++++++++-------- src/components/Controls/Float.vue | 9 ++++-- src/components/Controls/Int.vue | 9 ++++-- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/accounting/ledgerPosting.js b/accounting/ledgerPosting.js index fda9ce86..965fe9d0 100644 --- a/accounting/ledgerPosting.js +++ b/accounting/ledgerPosting.js @@ -162,7 +162,7 @@ export default class LedgerPosting { } getPrecision() { - return frappe.SystemSettings.floatPrecision; + return frappe.SystemSettings.internalPrecision; } getRoundOffAccount() { diff --git a/src/components/Controls/Base.vue b/src/components/Controls/Base.vue index 8a927505..e27e35b9 100644 --- a/src/components/Controls/Base.vue +++ b/src/components/Controls/Base.vue @@ -10,14 +10,17 @@ :value="value" :placeholder="inputPlaceholder" :readonly="isReadOnly" - @blur="e => triggerChange(e.target.value)" - @focus="e => $emit('focus', e)" - @input="e => $emit('input', e)" + :max="df.maxValue" + :min="df.minValue" + @blur="(e) => triggerChange(e.target.value)" + @focus="(e) => $emit('focus', e)" + @input="(e) => $emit('input', e)" /> diff --git a/src/components/Controls/Float.vue b/src/components/Controls/Float.vue index e740ff69..cd0b0ff9 100644 --- a/src/components/Controls/Float.vue +++ b/src/components/Controls/Float.vue @@ -4,11 +4,16 @@ import Int from './Int'; export default { name: 'Float', extends: Int, + computed: { + inputType() { + return 'number'; + } + }, methods: { parse(value) { let parsedValue = parseFloat(value); return isNaN(parsedValue) ? 0 : parsedValue; - } - } + }, + }, }; diff --git a/src/components/Controls/Int.vue b/src/components/Controls/Int.vue index 920418a2..354ca247 100644 --- a/src/components/Controls/Int.vue +++ b/src/components/Controls/Int.vue @@ -4,11 +4,16 @@ import Data from './Data'; export default { name: 'Int', extends: Data, + computed: { + inputType() { + return 'number'; + }, + }, methods: { parse(value) { let parsedValue = parseInt(value, 10); return isNaN(parsedValue) ? 0 : parsedValue; - } - } + }, + }, }; From facf5dbfb699823213b26b731cb069b238bd9b76 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Thu, 23 Dec 2021 18:07:50 +0530 Subject: [PATCH 04/25] feat: add locales, reword a get started --- fixtures/countryInfo.json | 2041 ++++++++++++++++--------- src/pages/GetStarted.vue | 2 +- src/pages/SetupWizard/setupCompany.js | 4 + 3 files changed, 1333 insertions(+), 714 deletions(-) diff --git a/fixtures/countryInfo.json b/fixtures/countryInfo.json index 46531129..28e57266 100644 --- a/fixtures/countryInfo.json +++ b/fixtures/countryInfo.json @@ -1,69 +1,85 @@ { - "Afghanistan": { + "Afghanistan": + { "code": "af", "currency": "AFN", "currency_fraction": "Pul", "currency_fraction_units": 100, - "currency_symbol": "\u060b", + "currency_symbol": "؋", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Kabul" ], "fiscal_year_start": "12-20", - "fiscal_year_end": "12-21" + "fiscal_year_end": "12-21", + "locale": "ps-AF" }, - "Albania": { + "Albania": + { "code": "al", "currency": "ALL", - "currency_fraction": "Qindark\u00eb", + "currency_fraction": "Qindarkë", "currency_fraction_units": 100, "currency_name": "Lek", "currency_symbol": "L", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Tirane" - ] + ], + "locale": "sq-AL" }, - "Algeria": { + "Algeria": + { "code": "dz", "currency": "DZD", "currency_fraction": "Santeem", "currency_fraction_units": 100, "currency_name": "Algerian Dinar", - "currency_symbol": "\u062f.\u062c", + "currency_symbol": "د.ج", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Algiers" - ] + ], + "locale": "ar-DZ" }, - "American Samoa": { + "American Samoa": + { "code": "as", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "en-AS" }, - "Andorra": { + "Andorra": + { "code": "ad", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Andorra" ] }, - "Angola": { + "Angola": + { "code": "ao", "currency": "KZ", - "currency_fraction": "C\u00eantimo", + "currency_fraction": "Cêntimo", "currency_fraction_units": 100, "currency_symbol": "AOA", "currency_name": "Kwanza", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Luanda" ] }, - "Anguilla": { + "Anguilla": + { "code": "ai", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -71,14 +87,17 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Anguilla" ] }, - "Antarctica": { + "Antarctica": + { "code": "aq", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Antarctica/Casey", "Antarctica/Davis", "Antarctica/DumontDUrville", @@ -91,7 +110,8 @@ "Antarctica/Vostok" ] }, - "Antigua and Barbuda": { + "Antigua and Barbuda": + { "code": "ag", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -99,11 +119,13 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Antigua" ] }, - "Argentina": { + "Argentina": + { "code": "ar", "currency": "ARS", "currency_fraction": "Centavo", @@ -111,7 +133,8 @@ "currency_name": "Argentine Peso", "currency_symbol": "$", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "America/Argentina/Buenos_Aires", "America/Argentina/Catamarca", "America/Argentina/Cordoba", @@ -124,21 +147,26 @@ "America/Argentina/San_Luis", "America/Argentina/Tucuman", "America/Argentina/Ushuaia" - ] + ], + "locale": "es-AR" }, - "Armenia": { + "Armenia": + { "code": "am", "currency": "AMD", "currency_fraction": "Luma", "currency_fraction_units": 100, "currency_name": "Armenian Dram", - "currency_symbol": "\u058f", + "currency_symbol": "֏", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Yerevan" - ] + ], + "locale": "hy-AM" }, - "Aruba": { + "Aruba": + { "code": "aw", "currency": "AWG", "currency_fraction": "Cent", @@ -146,11 +174,13 @@ "currency_name": "Aruban Florin", "currency_symbol": "Afl", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Aruba" ] }, - "Australia": { + "Australia": + { "code": "au", "currency": "AUD", "currency_fraction": "Cent", @@ -158,7 +188,8 @@ "currency_name": "Australian Dollar", "currency_symbol": "$", "number_format": "# ###.##", - "timezones": [ + "timezones": + [ "Australia/Adelaide", "Australia/Brisbane", "Australia/Broken_Hill", @@ -173,65 +204,80 @@ "Australia/Sydney" ], "fiscal_year_start": "07-01", - "fiscal_year_end": "06-30" + "fiscal_year_end": "06-30", + "locale": "en-AU" }, - "Austria": { + "Austria": + { "code": "at", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Vienna" - ] + ], + "locale": "de-AT" }, - "Azerbaijan": { + "Azerbaijan": + { "code": "az", - "currency_fraction": "Q\u0259pik", + "currency_fraction": "Qəpik", "currency_fraction_units": 100, "currency_symbol": "", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Baku" ] }, - "Bahamas": { + "Bahamas": + { "code": "bs", "currency": "BSD", "currency_name": "Bahamian Dollar", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Nassau" ] }, - "Bahrain": { + "Bahrain": + { "code": "bh", "currency": "BHD", "currency_fraction": "Fils", "currency_fraction_units": 1000, "currency_name": "Bahraini Dinar", - "currency_symbol": ".\u062f.\u0628", + "currency_symbol": ".د.ب", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Asia/Bahrain" - ] + ], + "locale": "ar-BH" }, - "Bangladesh": { + "Bangladesh": + { "code": "bd", "currency": "BDT", "currency_fraction": "Paisa", "currency_fraction_units": 100, "currency_name": "Taka", - "currency_symbol": "\u09f3", + "currency_symbol": "৳", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Dhaka" ], "fiscal_year_start": "07-01", - "fiscal_year_end": "06-30" + "fiscal_year_end": "06-30", + "locale": "bn-BD" }, - "Barbados": { + "Barbados": + { "code": "bb", "currency": "BBD", "currency_fraction": "Cent", @@ -239,32 +285,40 @@ "currency_name": "Barbados Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Barbados" ] }, - "Belarus": { + "Belarus": + { "code": "by", "currency_fraction": "Kapyeyka", "currency_fraction_units": 100, "currency_symbol": "Br", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Minsk" - ] + ], + "locale": "be-BY" }, - "Belgium": { + "Belgium": + { "code": "be", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Brussels" - ] + ], + "locale": "en-BE" }, - "Belize": { + "Belize": + { "code": "bz", "currency": "BZD", "currency_fraction": "Cent", @@ -273,11 +327,14 @@ "currency_symbol": "$", "date_format": "MM-dd-yyyy", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Belize" - ] + ], + "locale": "en-BZ" }, - "Benin": { + "Benin": + { "code": "bj", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -285,11 +342,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Porto-Novo" - ] + ], + "locale": "fr-BJ" }, - "Bermuda": { + "Bermuda": + { "code": "bm", "currency": "BMD", "currency_fraction": "Cent", @@ -297,11 +357,13 @@ "currency_name": "Bermudian Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Atlantic/Bermuda" ] }, - "Bhutan": { + "Bhutan": + { "code": "bt", "currency": "BTN", "currency_fraction": "Chetrum", @@ -309,32 +371,40 @@ "currency_name": "Ngultrum", "currency_symbol": "Nu.", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Thimphu" ] }, - "Bolivia, Plurinational State of": { + "Bolivia, Plurinational State of": + { "code": "bo", "currency": "BOB", "currency_name": "Boliviano", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "es-BO" }, - "Bonaire, Sint Eustatius and Saba": { + "Bonaire, Sint Eustatius and Saba": + { "code": "bq", "number_format": "#,###.##" }, - "Bosnia and Herzegovina": { + "Bosnia and Herzegovina": + { "code": "ba", "currency": "BAM", "currency_fraction": "Fening", "currency_fraction_units": 100, "currency_symbol": "KM", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Sarajevo" - ] + ], + "locale": "bs-BA" }, - "Botswana": { + "Botswana": + { "code": "bw", "currency": "BWP", "currency_fraction": "Thebe", @@ -342,15 +412,19 @@ "currency_name": "Pula", "currency_symbol": "P", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Gaborone" - ] + ], + "locale": "en-BW" }, - "Bouvet Island": { + "Bouvet Island": + { "code": "bv", "number_format": "#,###.##" }, - "Brazil": { + "Brazil": + { "code": "br", "currency": "BRL", "currency_fraction": "Centavo", @@ -358,7 +432,8 @@ "currency_symbol": "R$", "date_format": "dd/MM/yyyy", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "America/Araguaina", "America/Bahia", "America/Belem", @@ -375,40 +450,50 @@ "America/Rio_Branco", "America/Santarem", "America/Sao_Paulo" - ] + ], + "locale": "pt-BR" }, - "British Indian Ocean Territory": { + "British Indian Ocean Territory": + { "code": "io", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Chagos" ] }, - "Brunei Darussalam": { + "Brunei Darussalam": + { "code": "bn", "currency": "BND", "currency_name": "Brunei Dollar", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Brunei" - ] + ], + "locale": "ms-BN" }, - "Bulgaria": { + "Bulgaria": + { "code": "bg", "currency": "BGN", "currency_name": "Bulgarian Lev", "currency_fraction": "Stotinka", "currency_fraction_units": 100, - "currency_symbol": "\u043b\u0432", + "currency_symbol": "лв", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Sofia" - ] + ], + "locale": "bg-BG" }, - "Burkina Faso": { + "Burkina Faso": + { "code": "bf", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -416,11 +501,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Ouagadougou" - ] + ], + "locale": "fr-BF" }, - "Burundi": { + "Burundi": + { "code": "bi", "currency": "BIF", "currency_fraction": "Centime", @@ -428,23 +516,29 @@ "currency_name": "Burundi Franc", "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Bujumbura" - ] + ], + "locale": "fr-BI" }, - "Cambodia": { + "Cambodia": + { "code": "kh", "currency": "KHR", "currency_fraction": "Sen", "currency_fraction_units": 100, "currency_name": "Riel", - "currency_symbol": "\u17db", + "currency_symbol": "៛", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Phnom_Penh" - ] + ], + "locale": "km-KH" }, - "Cameroon": { + "Cameroon": + { "code": "cm", "currency": "XAF", "currency_name": "Central African CFA Franc", @@ -452,11 +546,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Douala" - ] + ], + "locale": "fr-CM" }, - "Canada": { + "Canada": + { "code": "ca", "currency": "CAD", "currency_fraction": "Cent", @@ -465,7 +562,8 @@ "currency_symbol": "$", "date_format": "MM-dd-yyyy", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Atikokan", "America/Blanc-Sablon", "America/Cambridge_Bay", @@ -496,9 +594,11 @@ "America/Yellowknife" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "en-CA" }, - "Cape Verde": { + "Cape Verde": + { "code": "cv", "currency": "CVE", "currency_fraction": "Centavo", @@ -506,11 +606,14 @@ "currency_name": "Cape Verde Escudo", "currency_symbol": "Esc or $", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Atlantic/Cape_Verde" - ] + ], + "locale": "kea-CV" }, - "Cayman Islands": { + "Cayman Islands": + { "code": "ky", "currency": "KYD", "currency_fraction": "Cent", @@ -518,11 +621,13 @@ "currency_name": "Cayman Islands Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Cayman" ] }, - "Central African Republic": { + "Central African Republic": + { "code": "cf", "currency": "XAF", "currency_fraction": "Centime", @@ -530,11 +635,14 @@ "currency_name": "Central African CFA Franc", "currency_symbol": "FCFA", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Bangui" - ] + ], + "locale": "fr-CF" }, - "Chad": { + "Chad": + { "code": "td", "currency": "XAF", "currency_name": "Central African CFA Franc", @@ -542,11 +650,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Ndjamena" - ] + ], + "locale": "fr-TD" }, - "Chile": { + "Chile": + { "code": "cl", "currency": "CLP", "currency_fraction": "Centavo", @@ -554,43 +665,53 @@ "currency_name": "Chilean Peso", "currency_symbol": "$", "number_format": "#.###", - "timezones": [ + "timezones": + [ "America/Santiago", "Pacific/Easter" - ] + ], + "locale": "es-CL" }, - "China": { + "China": + { "code": "cn", "currency": "CNY", "currency_name": "Yuan Renminbi", "date_format": "yyyy-MM-dd", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Chongqing", "Asia/Harbin", "Asia/Kashgar", "Asia/Shanghai", "Asia/Urumqi" - ] + ], + "locale": "ii-CN" }, - "Christmas Island": { + "Christmas Island": + { "code": "cx", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Christmas" ] }, - "Cocos (Keeling) Islands": { + "Cocos (Keeling) Islands": + { "code": "cc", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Cocos" ] }, - "Colombia": { + "Colombia": + { "code": "co", "currency": "COP", "currency_fraction": "Centavo", @@ -598,11 +719,14 @@ "currency_name": "Colombian Peso", "currency_symbol": "$", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "America/Bogota" - ] + ], + "locale": "es-CO" }, - "Comoros": { + "Comoros": + { "code": "km", "currency": "KMF", "currency_fraction": "Centime", @@ -610,48 +734,60 @@ "currency_name": "Comoro Franc", "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Comoro" - ] + ], + "locale": "fr-KM" }, - "Congo": { + "Congo": + { "code": "cg", "number_format": "#,###.##", "currency": "XAF", "currency_name": "Central African CFA Franc", "currency_symbol": "FCFA", "currency_fraction": "Centime", - "currency_fraction_units": 100 + "currency_fraction_units": 100, + "locale": "fr-CG" }, - "Congo, The Democratic Republic of the": { + "Congo, The Democratic Republic of the": + { "code": "cd", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "fr-CD" }, - "Cook Islands": { + "Cook Islands": + { "code": "ck", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Rarotonga" ] }, - "Costa Rica": { + "Costa Rica": + { "code": "cr", "currency": "CRC", - "currency_fraction": "C\u00e9ntimo", + "currency_fraction": "Céntimo", "currency_fraction_units": 100, "currency_name": "Costa Rican Colon", - "currency_symbol": "\u20a1", + "currency_symbol": "₡", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "America/Costa_Rica" ], "fiscal_year_start": "10-01", - "fiscal_year_end": "09-30" + "fiscal_year_end": "09-30", + "locale": "es-CR" }, - "Croatia": { + "Croatia": + { "code": "hr", "currency": "HRK", "currency_fraction": "Lipa", @@ -659,11 +795,14 @@ "currency_name": "Croatian Kuna", "currency_symbol": "kn", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Zagreb" - ] + ], + "locale": "hr-HR" }, - "Cuba": { + "Cuba": + { "code": "cu", "currency": "CUP", "currency_fraction": "Centavo", @@ -671,54 +810,66 @@ "currency_name": "Cuban Peso", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Havana" ] }, - "Cura\u00e7ao": { + "Curaçao": + { "code": "cw", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u0192", + "currency_symbol": "ƒ", "number_format": "#,###.##" }, - "Cyprus": { + "Cyprus": + { "code": "cy", "currency": "CYP", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_name": "Cyprus Pound", - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Asia/Nicosia" - ] + ], + "locale": "el-CY" }, - "Czech Republic": { + "Czech Republic": + { "code": "cz", "currency": "CZK", - "currency_fraction": "Hal\u00e9\u0159", + "currency_fraction": "Haléř", "currency_fraction_units": 100, "currency_name": "Czech Koruna", - "currency_symbol": "K\u010d", + "currency_symbol": "Kč", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Prague" - ] + ], + "locale": "cs-CZ" }, - "Denmark": { + "Denmark": + { "code": "dk", "currency": "DKK", - "currency_fraction": "\u00d8re", + "currency_fraction": "Øre", "currency_fraction_units": 100, "currency_name": "Danish Krone", "currency_symbol": "kr", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Copenhagen" - ] + ], + "locale": "da-DK" }, - "Djibouti": { + "Djibouti": + { "code": "dj", "currency": "DJF", "currency_fraction": "Centime", @@ -726,11 +877,14 @@ "currency_name": "Djibouti Franc", "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Djibouti" - ] + ], + "locale": "fr-DJ" }, - "Dominica": { + "Dominica": + { "code": "dm", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -738,11 +892,13 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Dominica" ] }, - "Dominican Republic": { + "Dominican Republic": + { "code": "do", "currency": "DOP", "currency_fraction": "Centavo", @@ -750,48 +906,60 @@ "currency_name": "Dominican Peso", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Santo_Domingo" - ] + ], + "locale": "es-DO" }, - "Ecuador": { + "Ecuador": + { "code": "ec", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Guayaquil", "Pacific/Galapagos" - ] + ], + "locale": "es-EC" }, - "Egypt": { + "Egypt": + { "code": "eg", "currency": "EGP", "currency_fraction": "Piastre[F]", "currency_fraction_units": 100, "currency_name": "Egyptian Pound", - "currency_symbol": "\u00a3 or \u062c.\u0645", + "currency_symbol": "£ or ج.م", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Cairo" ], "fiscal_year_start": "07-01", - "fiscal_year_end": "06-30" + "fiscal_year_end": "06-30", + "locale": "ar-EG" }, - "El Salvador": { + "El Salvador": + { "code": "sv", "currency": "SVC", "currency_fraction": "Centavo", "currency_fraction_units": 100, "currency_name": "El Salvador Colon", - "currency_symbol": "\u20a1", + "currency_symbol": "₡", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/El_Salvador" - ] + ], + "locale": "es-SV" }, - "Equatorial Guinea": { + "Equatorial Guinea": + { "code": "gq", "currency": "XAF", "currency_name": "Central African CFA Franc", @@ -799,11 +967,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Malabo" - ] + ], + "locale": "fr-GQ" }, - "Eritrea": { + "Eritrea": + { "code": "er", "currency": "ERN", "currency_fraction": "Cent", @@ -811,50 +982,63 @@ "currency_name": "Nakfa", "currency_symbol": "Nfk", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Asmara" - ] + ], + "locale": "ti-ER" }, - "Estonia": { + "Estonia": + { "code": "ee", "currency": "EEK", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_name": "Kroon", - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Tallinn" - ] + ], + "locale": "et-EE" }, - "Ethiopia": { + "Ethiopia": + { "code": "et", "currency_fraction": "Santim", "currency_fraction_units": 100, "currency_name": "Ethiopian Birr", "currency_symbol": "Br", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Addis_Ababa" - ] + ], + "locale": "am-ET" }, - "Falkland Islands (Malvinas)": { + "Falkland Islands (Malvinas)": + { "code": "fk", "currency": "FKP", "currency_name": "Falkland Islands Pound", "number_format": "#,###.##" }, - "Faroe Islands": { + "Faroe Islands": + { "code": "fo", - "currency_fraction": "\u00d8re", + "currency_fraction": "Øre", "currency_fraction_units": 100, "currency_symbol": "kr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Atlantic/Faroe" - ] + ], + "locale": "fo-FO" }, - "Fiji": { + "Fiji": + { "code": "fj", "currency": "FJD", "currency_fraction": "Cent", @@ -862,57 +1046,70 @@ "currency_name": "Fiji Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Fiji" ] }, - "Finland": { + "Finland": + { "code": "fi", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Helsinki" - ] + ], + "locale": "fi-FI" }, - "France": { + "France": + { "code": "fr", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "# ###,##", "date_format": "dd/MM/yyyy", - "timezones": [ + "timezones": + [ "Europe/Paris" - ] + ], + "locale": "fr-FR" }, - "French Guiana": { + "French Guiana": + { "code": "gf", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Cayenne" ] }, - "French Polynesia": { + "French Polynesia": + { "code": "pf", "currency_fraction": "Centime", "currency_fraction_units": 100, "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Gambier", "Pacific/Marquesas", "Pacific/Tahiti" ] }, - "French Southern Territories": { + "French Southern Territories": + { "code": "tf", "number_format": "#,###.##" }, - "Gabon": { + "Gabon": + { "code": "ga", "currency": "XAF", "currency_name": "Central African CFA Franc", @@ -920,85 +1117,107 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Libreville" - ] + ], + "locale": "fr-GA" }, - "Gambia": { + "Gambia": + { "code": "gm", "currency": "GMD", "currency_name": "Dalasi", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Banjul" ] }, - "Georgia": { + "Georgia": + { "code": "ge", "currency_fraction": "Tetri", "currency_fraction_units": 100, - "currency_symbol": "\u10da", + "currency_symbol": "ლ", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Tbilisi" - ] + ], + "locale": "ka-GE" }, - "Germany": { + "Germany": + { "code": "de", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Berlin" - ] + ], + "locale": "de-DE" }, - "Ghana": { + "Ghana": + { "code": "gh", "currency": "GHS", "currency_fraction": "Pesewa", "currency_fraction_units": 100, - "currency_symbol": "\u20b5", + "currency_symbol": "₵", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Accra" - ] + ], + "locale": "ak-GH" }, - "Gibraltar": { + "Gibraltar": + { "code": "gi", "currency": "GIP", "currency_fraction": "Penny", "currency_fraction_units": 100, "currency_name": "Gibraltar Pound", - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Gibraltar" ] }, - "Greece": { + "Greece": + { "code": "gr", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Athens" - ] + ], + "locale": "el-GR" }, - "Greenland": { + "Greenland": + { "code": "gl", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Danmarkshavn", "America/Godthab", "America/Scoresbysund", "America/Thule" - ] + ], + "locale": "kl-GL" }, - "Grenada": { + "Grenada": + { "code": "gd", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -1006,25 +1225,33 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Grenada" ] }, - "Guadeloupe": { + "Guadeloupe": + { "code": "gp", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Guadeloupe" - ] + ], + "locale": "fr-GP" }, - "Guam": { + "Guam": + { "code": "gu", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Guam" - ] + ], + "locale": "en-GU" }, - "Guatemala": { + "Guatemala": + { "code": "gt", "currency": "GTQ", "currency_fraction": "Centavo", @@ -1032,21 +1259,26 @@ "currency_name": "Quetzal", "currency_symbol": "Q", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Guatemala" - ] + ], + "locale": "es-GT" }, - "Guernsey": { + "Guernsey": + { "code": "gg", "currency_fraction": "Penny", "currency_fraction_units": 100, - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/London" ] }, - "Guinea": { + "Guinea": + { "code": "gn", "currency": "GNF", "currency_fraction": "Centime", @@ -1054,11 +1286,14 @@ "currency_name": "Guinea Franc", "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Conakry" - ] + ], + "locale": "fr-GN" }, - "Guinea-Bissau": { + "Guinea-Bissau": + { "code": "gw", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -1066,11 +1301,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Bissau" - ] + ], + "locale": "pt-GW" }, - "Guyana": { + "Guyana": + { "code": "gy", "currency": "GYD", "currency_fraction": "Cent", @@ -1078,11 +1316,13 @@ "currency_name": "Guyana Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Guyana" ] }, - "Haiti": { + "Haiti": + { "code": "ht", "currency": "HTG", "currency_fraction": "Centime", @@ -1090,20 +1330,24 @@ "currency_name": "Gourde", "currency_symbol": "G", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Guatemala", "America/Port-au-Prince" ] }, - "Heard Island and McDonald Islands": { + "Heard Island and McDonald Islands": + { "code": "hm", "number_format": "#,###.##" }, - "Holy See (Vatican City State)": { + "Holy See (Vatican City State)": + { "code": "va", "number_format": "#,###.##" }, - "Honduras": { + "Honduras": + { "code": "hn", "currency": "HNL", "currency_fraction": "Centavo", @@ -1111,11 +1355,14 @@ "currency_name": "Lempira", "currency_symbol": "L", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Tegucigalpa" - ] + ], + "locale": "es-HN" }, - "Hong Kong": { + "Hong Kong": + { "code": "hk", "currency": "HKD", "currency_fraction": "Cent", @@ -1123,26 +1370,32 @@ "currency_name": "Hong Kong Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Hong_Kong" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "en-HK" }, - "Hungary": { + "Hungary": + { "code": "hu", "currency": "HUF", - "currency_fraction": "Fill\u00e9r", + "currency_fraction": "Fillér", "currency_fraction_units": 100, "currency_name": "Forint", "currency_symbol": "Ft", "date_format": "yyyy-MM-dd", "number_format": "#.###", - "timezones": [ + "timezones": + [ "Europe/Budapest" - ] + ], + "locale": "hu-HU" }, - "Iceland": { + "Iceland": + { "code": "is", "currency": "ISK", "currency_fraction": "Eyrir", @@ -1150,26 +1403,32 @@ "currency_name": "Iceland Krona", "currency_symbol": "kr", "number_format": "#.###", - "timezones": [ + "timezones": + [ "Atlantic/Reykjavik" - ] + ], + "locale": "is-IS" }, - "India": { + "India": + { "code": "in", "currency": "INR", "currency_fraction": "Paisa", "currency_fraction_units": 100, "currency_name": "Indian Rupee", - "currency_symbol": "\u20b9", + "currency_symbol": "₹", "date_format": "dd/MM/yyyy", "number_format": "#,##,###.##", - "timezones": [ + "timezones": + [ "Asia/Kolkata" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "en-IN" }, - "Indonesia": { + "Indonesia": + { "code": "id", "currency": "IDR", "currency_fraction": "Sen", @@ -1177,85 +1436,105 @@ "currency_name": "Rupiah", "currency_symbol": "Rp", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Asia/Jakarta", "Asia/Jayapura", "Asia/Makassar", "Asia/Pontianak" - ] + ], + "locale": "id-ID" }, - "Iran": { + "Iran": + { "code": "ir", "currency": "IRR", "currency_name": "Iranian Rial", - "currency_symbol": "\ufdfc", + "currency_symbol": "﷼", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Tehran" ], "fiscal_year_start": "06-23", - "fiscal_year_end": "06-22" + "fiscal_year_end": "06-22", + "locale": "fa-IR" }, - "Iraq": { + "Iraq": + { "code": "iq", "currency": "IQD", "currency_fraction": "Fils", "currency_fraction_units": 1000, "currency_name": "Iraqi Dinar", - "currency_symbol": "\u0639.\u062f", + "currency_symbol": "ع.د", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Asia/Baghdad" - ] + ], + "locale": "ar-IQ" }, - "Ireland": { + "Ireland": + { "code": "ie", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Dublin" - ] + ], + "locale": "en-IE" }, - "Isle of Man": { + "Isle of Man": + { "code": "im", "currency_fraction": "Penny", "currency_fraction_units": 100, - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/London" ] }, - "Israel": { + "Israel": + { "code": "il", "currency": "ILS", "currency_fraction": "Agora", "currency_fraction_units": 100, "currency_name": "New Israeli Sheqel", - "currency_symbol": "\u20aa", + "currency_symbol": "₪", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Jerusalem" - ] + ], + "locale": "en-IL" }, - "Italy": { + "Italy": + { "code": "it", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#.###,##", "date_format": "dd/MM/yyyy", - "timezones": [ + "timezones": + [ "Europe/Rome" ], "fiscal_year_start": "07-01", - "fiscal_year_end": "06-30" + "fiscal_year_end": "06-30", + "locale": "it-IT" }, - "Ivory Coast": { + "Ivory Coast": + { "code": "ci", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -1263,11 +1542,14 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timeszones": [ + "timeszones": + [ "Africa/Abidjan" - ] + ], + "locale": "fr-CI" }, - "Jamaica": { + "Jamaica": + { "code": "jm", "currency": "JMD", "currency_fraction": "Cent", @@ -1275,53 +1557,65 @@ "currency_name": "Jamaican Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Jamaica" - ] + ], + "locale": "en-JM" }, - "Japan": { + "Japan": + { "code": "jp", "currency": "JPY", "currency_fraction": "Sen[G]", "currency_fraction_units": 100, "currency_name": "Yen", - "currency_symbol": "\u00a5", + "currency_symbol": "¥", "number_format": "#,###", - "timezones": [ + "timezones": + [ "Asia/Tokyo" - ] + ], + "locale": "ja-JP" }, - "Jersey": { + "Jersey": + { "code": "je", "currency_fraction": "Penny", "currency_fraction_units": 100, - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/London" ] }, - "Jordan": { + "Jordan": + { "code": "jo", "currency": "JOD", "currency_fraction": "Piastre[H]", "currency_fraction_units": 100, "currency_name": "Jordanian Dinar", - "currency_symbol": "\u062f.\u0627", + "currency_symbol": "د.ا", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Asia/Amman" - ] + ], + "locale": "ar-JO" }, - "Kazakhstan": { + "Kazakhstan": + { "code": "kz", "currency": "KZT", - "currency_fraction": "T\u00ef\u0131n", + "currency_fraction": "Tïın", "currency_fraction_units": 100, "currency_name": "Tenge", - "currency_symbol": "\u20b8", + "currency_symbol": "₸", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Almaty", "Asia/Aqtau", "Asia/Aqtobe", @@ -1329,7 +1623,8 @@ "Asia/Qyzylorda" ] }, - "Kenya": { + "Kenya": + { "code": "ke", "currency": "KES", "currency_fraction": "Cent", @@ -1337,89 +1632,109 @@ "currency_name": "Kenyan Shilling", "currency_symbol": "Sh", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Nairobi" - ] + ], + "locale": "ebu-KE" }, - "Kiribati": { + "Kiribati": + { "code": "ki", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Enderbury", "Pacific/Kiritimati", "Pacific/Tarawa" ] }, - "Korea, Democratic Peoples Republic of": { + "Korea, Democratic Peoples Republic of": + { "code": "kp", "currency": "KPW", "currency_name": "North Korean Won", "number_format": "#,###.##" }, - "Korea, Republic of": { + "Korea, Republic of": + { "code": "kr", "currency": "KRW", "currency_name": "Won", - "number_format": "#,###" + "number_format": "#,###", + "locale": "ko-KR" }, - "Kuwait": { + "Kuwait": + { "code": "kw", "currency": "KWD", "currency_fraction": "Fils", "currency_fraction_units": 1000, "currency_name": "Kuwaiti Dinar", - "currency_symbol": "\u062f.\u0643", + "currency_symbol": "د.ك", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Asia/Kuwait" - ] + ], + "locale": "ar-KW" }, - "Kyrgyzstan": { + "Kyrgyzstan": + { "code": "kg", "currency": "KGS", "currency_fraction": "Tyiyn", "currency_fraction_units": 100, "currency_name": "Som", - "currency_symbol": "\u043b\u0432", + "currency_symbol": "лв", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Bishkek" ] }, - "Lao Peoples Democratic Republic": { + "Lao Peoples Democratic Republic": + { "code": "la", "currency": "LAK", "currency_name": "Kip", "number_format": "#,###.##" }, - "Latvia": { + "Latvia": + { "code": "lv", "currency": "LVL", - "currency_fraction": "Sant\u012bms", + "currency_fraction": "Santīms", "currency_fraction_units": 100, "currency_name": "Latvian Lats", "currency_symbol": "Ls", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Riga" - ] + ], + "locale": "lv-LV" }, - "Lebanon": { + "Lebanon": + { "code": "lb", "currency": "LBP", "currency_fraction": "Piastre", "currency_fraction_units": 100, "currency_name": "Lebanese Pound", - "currency_symbol": "\u0644.\u0644", + "currency_symbol": "ل.ل", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Beirut" - ] + ], + "locale": "ar-LB" }, - "Lesotho": { + "Lesotho": + { "code": "ls", "currency": "LSL", "currency_fraction": "Sente", @@ -1427,11 +1742,13 @@ "currency_name": "Loti", "currency_symbol": "L", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Maseru" ] }, - "Liberia": { + "Liberia": + { "code": "lr", "currency": "LRD", "currency_fraction": "Cent", @@ -1439,81 +1756,101 @@ "currency_name": "Liberian Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Monrovia" ] }, - "Libya": { + "Libya": + { "code": "ly", "currency": "LYD", "currency_fraction": "Dirham", "currency_fraction_units": 1000, "currency_name": "Libyan Dinar", - "currency_symbol": "\u0644.\u062f", + "currency_symbol": "ل.د", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Africa/Tripoli" - ] + ], + "locale": "ar-LY" }, - "Liechtenstein": { + "Liechtenstein": + { "code": "li", "currency_fraction": "Rappen", "currency_fraction_units": 100, "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Vaduz" - ] + ], + "locale": "de-LI" }, - "Lithuania": { + "Lithuania": + { "code": "lt", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "date_format": "yyyy-MM-dd", "number_format": "# ###,##", - "timezones": [ + "timezones": + [ "Europe/Vilnius" - ] + ], + "locale": "lt-LT" }, - "Luxembourg": { + "Luxembourg": + { "code": "lu", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Luxembourg" - ] + ], + "locale": "fr-LU" }, - "Macao": { + "Macao": + { "code": "mo", "currency": "MOP", "currency_name": "Pataca", "number_format": "#,###.##" }, - "Macedonia": { + "Macedonia": + { "code": "mk", "currency": "MKD", "currency_fraction": "Deni", "currency_fraction_units": 100, "currency_name": "Denar", - "currency_symbol": "\u0434\u0435\u043d", - "number_format": "#,###.##" + "currency_symbol": "ден", + "number_format": "#,###.##", + "locale": "mk-MK" }, - "Madagascar": { + "Madagascar": + { "code": "mg", "currency_fraction": "Iraimbilanja", "currency_fraction_units": 5, "currency_symbol": "Ar", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Antananarivo" - ] + ], + "locale": "fr-MG" }, - "Malawi": { + "Malawi": + { "code": "mw", "currency": "MWK", "currency_fraction": "Tambala", @@ -1521,11 +1858,13 @@ "currency_name": "Kwacha", "currency_symbol": "MK", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Blantyre" ] }, - "Malaysia": { + "Malaysia": + { "code": "my", "currency": "MYR", "currency_fraction": "Sen", @@ -1533,24 +1872,29 @@ "currency_name": "Malaysian Ringgit", "currency_symbol": "RM", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Kuala_Lumpur", "Asia/Kuching" - ] + ], + "locale": "ms-MY" }, - "Maldives": { + "Maldives": + { "code": "mv", "currency": "MVR", "currency_fraction": "Laari", "currency_fraction_units": 100, "currency_name": "Rufiyaa", - "currency_symbol": ".\u0783", + "currency_symbol": ".ރ", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Maldives" ] }, - "Mali": { + "Mali": + { "code": "ml", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -1558,41 +1902,53 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Bamako" - ] + ], + "locale": "bm-ML" }, - "Malta": { + "Malta": + { "code": "mt", "currency": "MTL", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_name": "Maltese Lira", - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Malta" - ] + ], + "locale": "en-MT" }, - "Marshall Islands": { + "Marshall Islands": + { "code": "mh", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Kwajalein", "Pacific/Majuro" - ] + ], + "locale": "en-MH" }, - "Martinique": { + "Martinique": + { "code": "mq", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Martinique" - ] + ], + "locale": "fr-MQ" }, - "Mauritania": { + "Mauritania": + { "code": "mr", "currency": "MRO", "currency_fraction": "Khoums", @@ -1600,30 +1956,37 @@ "currency_name": "Ouguiya", "currency_symbol": "UM", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Nouakchott" ] }, - "Mauritius": { + "Mauritius": + { "code": "mu", "currency": "MUR", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_name": "Mauritius Rupee", - "currency_symbol": "\u20a8", + "currency_symbol": "₨", "number_format": "#,###", - "timezones": [ + "timezones": + [ "Indian/Mauritius" - ] + ], + "locale": "en-MU" }, - "Mayotte": { + "Mayotte": + { "code": "yt", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Mayotte" ] }, - "Mexico": { + "Mexico": + { "code": "mx", "currency": "MXN", "currency_fraction": "Centavo", @@ -1631,7 +1994,8 @@ "currency_name": "Mexican Peso", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Bahia_Banderas", "America/Cancun", "America/Chihuahua", @@ -1644,56 +2008,68 @@ "America/Ojinaga", "America/Santa_Isabel", "America/Tijuana" - ] + ], + "locale": "es-MX" }, - "Micronesia, Federated States of": { + "Micronesia, Federated States of": + { "code": "fm", "number_format": "#,###.##" }, - "Moldova, Republic of": { + "Moldova, Republic of": + { "code": "md", "currency": "MDL", "currency_name": "Moldovan Leu", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "ro-MD" }, - "Monaco": { + "Monaco": + { "code": "mc", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Monaco" - ] + ], + "locale": "fr-MC" }, - "Mongolia": { + "Mongolia": + { "code": "mn", "currency": "MNT", - "currency_fraction": "M\u00f6ng\u00f6", + "currency_fraction": "Möngö", "currency_fraction_units": 100, "currency_name": "Tugrik", - "currency_symbol": "\u20ae", + "currency_symbol": "₮", "date_format": "yyyy-MM-dd", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Choibalsan", "Asia/Hovd", "Asia/Ulaanbaatar" ] }, - "Montenegro": { + "Montenegro": + { "code": "me", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Belgrade" ] }, - "Montserrat": { + "Montserrat": + { "code": "ms", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -1701,44 +2077,55 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Montserrat" ] }, - "Morocco": { + "Morocco": + { "code": "ma", "currency": "MAD", "currency_fraction": "Centime", "currency_fraction_units": 100, "currency_name": "Moroccan Dirham", - "currency_symbol": "\u062f.\u0645.", + "currency_symbol": "د.م.", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Casablanca" - ] + ], + "locale": "ar-MA" }, - "Mozambique": { + "Mozambique": + { "code": "mz", "currency_fraction": "Centavo", "currency_fraction_units": 100, "currency_symbol": "MT", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Maputo" - ] + ], + "locale": "pt-MZ" }, - "Myanmar": { + "Myanmar": + { "code": "mm", "currency": "MMK", "currency_name": "Kyat", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Rangoon" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "my-MM" }, - "Namibia": { + "Namibia": + { "code": "na", "currency": "NAD", "currency_fraction": "Cent", @@ -1746,54 +2133,67 @@ "currency_name": "Namibia Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Windhoek" - ] + ], + "locale": "en-NA" }, - "Nauru": { + "Nauru": + { "code": "nr", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Nauru" ] }, - "Nepal": { + "Nepal": + { "code": "np", "currency": "NPR", "currency_fraction": "Paisa", "currency_fraction_units": 100, "currency_name": "Nepalese Rupee", - "currency_symbol": "\u20a8", + "currency_symbol": "₨", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Kathmandu" - ] + ], + "locale": "ne-NP" }, - "Netherlands": { + "Netherlands": + { "code": "nl", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Amsterdam" - ] + ], + "locale": "nl-NL" }, - "New Caledonia": { + "New Caledonia": + { "code": "nc", "currency_fraction": "Centime", "currency_fraction_units": 100, "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Noumea" ] }, - "New Zealand": { + "New Zealand": + { "code": "nz", "currency": "NZD", "currency_fraction": "Cent", @@ -1801,14 +2201,17 @@ "currency_name": "New Zealand Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Auckland", "Pacific/Chatham" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "en-NZ" }, - "Nicaragua": { + "Nicaragua": + { "code": "ni", "currency": "NIO", "currency_fraction": "Centavo", @@ -1816,11 +2219,14 @@ "currency_name": "Cordoba Oro", "currency_symbol": "C$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Managua" - ] + ], + "locale": "es-NI" }, - "Niger": { + "Niger": + { "code": "ne", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -1828,110 +2234,138 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Niamey" - ] + ], + "locale": "fr-NE" }, - "Nigeria": { + "Nigeria": + { "code": "ng", "currency": "NGN", "currency_fraction": "Kobo", "currency_fraction_units": 100, "currency_name": "Naira", - "currency_symbol": "\u20a6", + "currency_symbol": "₦", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Lagos" - ] + ], + "locale": "ig-NG" }, - "Niue": { + "Niue": + { "code": "nu", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Niue" ] }, - "Norfolk Island": { + "Norfolk Island": + { "code": "nf", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Norfolk" ] }, - "Northern Mariana Islands": { + "Northern Mariana Islands": + { "code": "mp", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Saipan" - ] + ], + "locale": "en-MP" }, - "Norway": { + "Norway": + { "code": "no", "currency": "NOK", - "currency_fraction": "\u00d8re", + "currency_fraction": "Øre", "currency_fraction_units": 100, "currency_name": "Norwegian Krone", "currency_symbol": "kr", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Oslo" - ] + ], + "locale": "nb-NO" }, - "Oman": { + "Oman": + { "code": "om", "currency": "OMR", "currency_fraction": "Baisa", "currency_fraction_units": 1000, "currency_name": "Rial Omani", - "currency_symbol": "\u0631.\u0639.", + "currency_symbol": "ر.ع.", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Asia/Muscat" - ] + ], + "locale": "ar-OM" }, - "Pakistan": { + "Pakistan": + { "code": "pk", "currency": "PKR", "currency_fraction": "Paisa", "currency_fraction_units": 100, "currency_name": "Pakistan Rupee", - "currency_symbol": "\u20a8", + "currency_symbol": "₨", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Karachi" ], "fiscal_year_start": "07-01", - "fiscal_year_end": "06-30" + "fiscal_year_end": "06-30", + "locale": "en-PK" }, - "Palau": { + "Palau": + { "code": "pw", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "date_format": "MM-dd-yyyy", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Palau" ] }, - "Palestinian Territory, Occupied": { + "Palestinian Territory, Occupied": + { "code": "ps", "number_format": "#,###.##" }, - "Panama": { + "Panama": + { "code": "pa", - "currency_fraction": "Cent\u00e9simo", + "currency_fraction": "Centésimo", "currency_fraction_units": 100, "currency_symbol": "B/.", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Panama" - ] + ], + "locale": "es-PA" }, - "Papua New Guinea": { + "Papua New Guinea": + { "code": "pg", "currency": "PGK", "currency_fraction": "Toea", @@ -1939,98 +2373,123 @@ "currency_name": "Kina", "currency_symbol": "K", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Port_Moresby" ] }, - "Paraguay": { + "Paraguay": + { "code": "py", "currency": "PYG", - "currency_fraction": "C\u00e9ntimo", + "currency_fraction": "Céntimo", "currency_fraction_units": 100, "currency_name": "Guarani", - "currency_symbol": "\u20b2", + "currency_symbol": "₲", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Asuncion" - ] + ], + "locale": "es-PY" }, - "Peru": { + "Peru": + { "code": "pe", "currency": "PEN", - "currency_fraction": "C\u00e9ntimo", + "currency_fraction": "Céntimo", "currency_fraction_units": 100, "currency_name": "Nuevo Sol", "currency_symbol": "S/.", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Lima" - ] + ], + "locale": "es-PE" }, - "Philippines": { + "Philippines": + { "code": "ph", "currency": "PHP", "currency_fraction": "Centavo", "currency_fraction_units": 100, "currency_name": "Philippine Peso", - "currency_symbol": "\u20b1", + "currency_symbol": "₱", "date_format": "MM-dd-yyyy", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Manila" - ] + ], + "locale": "en-PH" }, - "Pitcairn": { + "Pitcairn": + { "code": "pn", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Pitcairn" ] }, - "Poland": { + "Poland": + { "code": "pl", "currency": "PLN", "currency_fraction": "Grosz", "currency_fraction_units": 100, - "currency_symbol": "z\u0142", + "currency_symbol": "zł", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Warsaw" - ] + ], + "locale": "pl-PL" }, - "Portugal": { + "Portugal": + { "code": "pt", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Atlantic/Azores", "Atlantic/Madeira", "Europe/Lisbon" - ] + ], + "locale": "pt-PT" }, - "Puerto Rico": { + "Puerto Rico": + { "code": "pr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Puerto_Rico" - ] + ], + "locale": "es-PR" }, - "Qatar": { + "Qatar": + { "code": "qa", "currency": "QAR", "currency_fraction": "Dirham", "currency_fraction_units": 100, "currency_name": "Qatari Rial", - "currency_symbol": "\u0631.\u0642", + "currency_symbol": "ر.ق", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Qatar" - ] + ], + "locale": "ar-QA" }, - "Romania": { + "Romania": + { "code": "ro", "currency": "RON", "currency_fraction": "Bani", @@ -2038,17 +2497,22 @@ "currency_name": "Romanian New Leu", "currency_symbol": "lei", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Bucharest" - ] + ], + "locale": "ro-RO" }, - "Russian Federation": { + "Russian Federation": + { "code": "ru", "currency": "RUB", "currency_name": "Russian Ruble", - "number_format": "#.###,##" + "number_format": "#.###,##", + "locale": "ru-RU" }, - "Rwanda": { + "Rwanda": + { "code": "rw", "currency": "RWF", "currency_fraction": "Centime", @@ -2056,25 +2520,33 @@ "currency_name": "Rwanda Franc", "currency_symbol": "Fr", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Kigali" - ] + ], + "locale": "fr-RW" }, - "R\u00e9union": { + "Réunion": + { "code": "re", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "fr-RE" }, - "Saint Barth\u00e9lemy": { + "Saint Barthélemy": + { "code": "bl", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "fr-BL" }, - "Saint Helena, Ascension and Tristan da Cunha": { + "Saint Helena, Ascension and Tristan da Cunha": + { "code": "sh", "currency": "SHP", "currency_name": "Saint Helena Pound", "number_format": "#,###.##" }, - "Saint Kitts and Nevis": { + "Saint Kitts and Nevis": + { "code": "kn", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -2082,11 +2554,13 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/St_Kitts" ] }, - "Saint Lucia": { + "Saint Lucia": + { "code": "lc", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -2094,19 +2568,24 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/St_Lucia" ] }, - "Saint Martin (French part)": { + "Saint Martin (French part)": + { "code": "mf", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "fr-MF" }, - "Saint Pierre and Miquelon": { + "Saint Pierre and Miquelon": + { "code": "pm", "number_format": "#,###.##" }, - "Saint Vincent and the Grenadines": { + "Saint Vincent and the Grenadines": + { "code": "vc", "currency_fraction": "Cent", "currency_fraction_units": 100, @@ -2114,11 +2593,13 @@ "currency_name": "Eastern Carribean Dollar", "currency": "XCD", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/St_Vincent" ] }, - "Samoa": { + "Samoa": + { "code": "ws", "currency": "WST", "currency_fraction": "Sene", @@ -2126,40 +2607,48 @@ "currency_name": "Tala", "currency_symbol": "T", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Apia" ] }, - "San Marino": { + "San Marino": + { "code": "sm", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Rome" ] }, - "Sao Tome and Principe": { + "Sao Tome and Principe": + { "code": "st", "currency": "STD", "currency_name": "Dobra", "number_format": "#,###.##" }, - "Saudi Arabia": { + "Saudi Arabia": + { "code": "sa", "currency": "SAR", "currency_fraction": "Halala", "currency_fraction_units": 100, "currency_name": "Saudi Riyal", - "currency_symbol": "\u0631.\u0633", + "currency_symbol": "ر.س", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Riyadh" - ] + ], + "locale": "ar-SA" }, - "Senegal": { + "Senegal": + { "code": "sn", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -2167,35 +2656,42 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Dakar" - ] + ], + "locale": "fr-SN" }, - "Serbia": { + "Serbia": + { "code": "rs", "currency": "RSD", "currency_fraction": "Para", "currency_fraction_units": 100, "currency_name": "Serbian Dinar", - "currency_symbol": "\u0434\u0438\u043d.", + "currency_symbol": "дин.", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Belgrade" ] }, - "Seychelles": { + "Seychelles": + { "code": "sc", "currency": "SCR", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_name": "Seychelles Rupee", - "currency_symbol": "\u20a8", + "currency_symbol": "₨", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Indian/Mahe" ] }, - "Sierra Leone": { + "Sierra Leone": + { "code": "sl", "currency": "SLL", "currency_fraction": "Cent", @@ -2203,11 +2699,13 @@ "currency_name": "Leone", "currency_symbol": "Le", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Freetown" ] }, - "Singapore": { + "Singapore": + { "code": "sg", "currency": "SGD", "currency_fraction": "Sen", @@ -2215,39 +2713,49 @@ "currency_name": "Singapore Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Singapore" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "en-SG" }, - "Sint Maarten (Dutch part)": { + "Sint Maarten (Dutch part)": + { "code": "sx", "number_format": "#,###.##" }, - "Slovakia": { + "Slovakia": + { "code": "sk", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Bratislava" - ] + ], + "locale": "sk-SK" }, - "Slovenia": { + "Slovenia": + { "code": "si", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Belgrade" - ] + ], + "locale": "sl-SI" }, - "Solomon Islands": { + "Solomon Islands": + { "code": "sb", "currency": "SBD", "currency_fraction": "Cent", @@ -2255,11 +2763,13 @@ "currency_name": "Solomon Islands Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Guadalcanal" ] }, - "Somalia": { + "Somalia": + { "code": "so", "currency": "SOS", "currency_fraction": "Cent", @@ -2267,11 +2777,14 @@ "currency_name": "Somali Shilling", "currency_symbol": "Sh", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Mogadishu" - ] + ], + "locale": "so-SO" }, - "South Africa": { + "South Africa": + { "code": "za", "currency": "ZAR", "currency_fraction": "Cent", @@ -2280,43 +2793,52 @@ "currency_symbol": "R", "date_format": "yyyy-MM-dd", "number_format": "# ###.##", - "timezones": [ + "timezones": + [ "Africa/Johannesburg" ], "fiscal_year_start": "03-01", - "fiscal_year_end": "02-28" + "fiscal_year_end": "02-28", + "locale": "en-ZA" }, - "South Georgia and the South Sandwich Islands": { + "South Georgia and the South Sandwich Islands": + { "code": "gs", "currency_fraction": "Penny", "currency_fraction_units": 100, - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##" }, - "South Sudan": { + "South Sudan": + { "code": "ss", "currency_fraction": "Piastre", "currency_fraction_units": 100, - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Juba" ] }, - "Spain": { + "Spain": + { "code": "es", "currency": "EUR", "currency_fraction": "Cent", "currency_fraction_units": 100, - "currency_symbol": "\u20ac", + "currency_symbol": "€", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Ceuta", "Atlantic/Canary", "Europe/Madrid" - ] + ], + "locale": "eu-ES" }, - "Sri Lanka": { + "Sri Lanka": + { "code": "lk", "currency": "LKR", "currency_fraction": "Cent", @@ -2324,35 +2846,44 @@ "currency_name": "Sri Lanka Rupee", "currency_symbol": "Rs", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Colombo" - ] + ], + "locale": "si-LK" }, - "Sudan": { + "Sudan": + { "code": "sd", "currency_fraction": "Piastre", "currency_fraction_units": 100, - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Khartoum" - ] + ], + "locale": "ar-SD" }, - "Suriname": { + "Suriname": + { "code": "sr", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Paramaribo" ] }, - "Svalbard and Jan Mayen": { + "Svalbard and Jan Mayen": + { "code": "sj", "number_format": "#,###.##" }, - "Swaziland": { + "Swaziland": + { "code": "sz", "currency": "SZL", "currency_fraction": "Cent", @@ -2360,23 +2891,28 @@ "currency_name": "Lilangeni", "currency_symbol": "L", "number_format": "#, ###.##", - "timezones": [ + "timezones": + [ "Africa/Mbabane" ] }, - "Sweden": { + "Sweden": + { "code": "se", "currency": "SEK", - "currency_fraction": "\u00d6re", + "currency_fraction": "Öre", "currency_fraction_units": 100, "currency_name": "Swedish Krona", "currency_symbol": "kr", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "Europe/Stockholm" - ] + ], + "locale": "sv-SE" }, - "Switzerland": { + "Switzerland": + { "code": "ch", "currency": "CHF", "currency_fraction": "Rappen[K]", @@ -2385,57 +2921,71 @@ "currency_name": "Swiss Franc", "currency_symbol": "Fr", "number_format": "#'###.##", - "timezones": [ + "timezones": + [ "Europe/Zurich" - ] + ], + "locale": "fr-CH" }, - "Syria": { + "Syria": + { "code": "sy", "currency": "SYP", "currency_name": "Syrian Pound", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "ar-SY" }, - "Taiwan": { + "Taiwan": + { "code": "tw", "currency": "TWD", "date_format": "yyyy-MM-dd", "number_format": "#,###.##" }, - "Tajikistan": { + "Tajikistan": + { "code": "tj", "currency_fraction": "Diram", "currency_fraction_units": 100, - "currency_symbol": "\u0405\u041c", + "currency_symbol": "ЅМ", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Dushanbe" ] }, - "Tanzania": { + "Tanzania": + { "code": "tz", "currency": "TZS", "currency_name": "Tanzanian Shilling", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "asa-TZ" }, - "Thailand": { + "Thailand": + { "code": "th", "currency": "THB", "currency_fraction": "Satang", "currency_fraction_units": 100, "currency_name": "Baht", - "currency_symbol": "\u0e3f", + "currency_symbol": "฿", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Bangkok" ], "fiscal_year_start": "10-01", - "fiscal_year_end": "09-30" + "fiscal_year_end": "09-30", + "locale": "th-TH" }, - "Timor-Leste": { + "Timor-Leste": + { "code": "tl", "number_format": "#,###.##" }, - "Togo": { + "Togo": + { "code": "tg", "currency": "XOF", "currency_name": "West African CFA Franc", @@ -2443,18 +2993,23 @@ "currency_fraction": "Centime", "currency_fraction_units": 100, "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Lome" - ] + ], + "locale": "ee-TG" }, - "Tokelau": { + "Tokelau": + { "code": "tk", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Fakaofo" ] }, - "Tonga": { + "Tonga": + { "code": "to", "currency": "TOP", "currency_fraction": "Seniti[L]", @@ -2462,11 +3017,14 @@ "currency_name": "Pa'anga", "currency_symbol": "T$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Tongatapu" - ] + ], + "locale": "to-TO" }, - "Trinidad and Tobago": { + "Trinidad and Tobago": + { "code": "tt", "currency": "TTD", "currency_fraction": "Cent", @@ -2474,34 +3032,43 @@ "currency_name": "Trinidad and Tobago Dollar", "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Port_of_Spain" - ] + ], + "locale": "en-TT" }, - "Tunisia": { + "Tunisia": + { "code": "tn", "currency": "TND", "currency_fraction": "Millime", "currency_fraction_units": 1000, "currency_name": "Tunisian Dinar", - "currency_symbol": "\u062f.\u062a", + "currency_symbol": "د.ت", "number_format": "#,###.###", - "timezones": [ + "timezones": + [ "Africa/Tunis" - ] + ], + "locale": "ar-TN" }, - "Turkey": { + "Turkey": + { "code": "tr", "currency": "TRY", - "currency_fraction": "Kuru\u015f", + "currency_fraction": "Kuruş", "currency_fraction_units": 100, - "currency_symbol": "\u20ba", + "currency_symbol": "₺", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Istanbul" - ] + ], + "locale": "tr-TR" }, - "Turkmenistan": { + "Turkmenistan": + { "code": "tm", "currency": "TMM", "currency_fraction": "Tennesi", @@ -2509,28 +3076,33 @@ "currency_name": "Manat", "currency_symbol": "m", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Ashgabat" ] }, - "Turks and Caicos Islands": { + "Turks and Caicos Islands": + { "code": "tc", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##" }, - "Tuvalu": { + "Tuvalu": + { "code": "tv", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Pacific/Funafuti" ] }, - "Uganda": { + "Uganda": + { "code": "ug", "currency": "UGX", "currency_fraction": "Cent", @@ -2538,52 +3110,64 @@ "currency_name": "Uganda Shilling", "currency_symbol": "Sh", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Kampala" - ] + ], + "locale": "cgg-UG" }, - "Ukraine": { + "Ukraine": + { "code": "ua", "currency": "UAH", "currency_fraction": "Kopiyka", "currency_fraction_units": 100, "currency_name": "Ukrainian Hryvnia", - "currency_symbol": "\u20b4", + "currency_symbol": "₴", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/Kiev", "Europe/Simferopol", "Europe/Uzhgorod", "Europe/Zaporozhye" - ] + ], + "locale": "ru-UA" }, - "United Arab Emirates": { + "United Arab Emirates": + { "code": "ae", "currency": "AED", "currency_fraction": "Fils", "currency_fraction_units": 100, "currency_name": "UAE Dirham", - "currency_symbol": "\u062f.\u0625", + "currency_symbol": "د.إ", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Dubai" - ] + ], + "locale": "ar-AE" }, - "United Kingdom": { + "United Kingdom": + { "code": "gb", "currency": "GBP", "currency_fraction": "Penny", "currency_fraction_units": 100, "currency_name": "Pound Sterling", - "currency_symbol": "\u00a3", + "currency_symbol": "£", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Europe/London" ], "fiscal_year_start": "04-01", - "fiscal_year_end": "03-31" + "fiscal_year_end": "03-31", + "locale": "en-GB" }, - "United States": { + "United States": + { "code": "us", "currency": "USD", "currency_fraction": "Cent", @@ -2593,7 +3177,8 @@ "currency_symbol": "$", "date_format": "MM-dd-yyyy", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "America/Adak", "America/Anchorage", "America/Boise", @@ -2624,38 +3209,47 @@ "America/Sitka", "America/Yakutat", "Pacific/Honolulu" - ] + ], + "locale": "en-US" }, - "United States Minor Outlying Islands": { + "United States Minor Outlying Islands": + { "code": "um", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "en-UM" }, - "Uruguay": { + "Uruguay": + { "code": "uy", "currency": "UYU", - "currency_fraction": "Cent\u00e9simo", + "currency_fraction": "Centésimo", "currency_fraction_units": 100, "currency_name": "Peso Uruguayo", "currency_symbol": "$", "number_format": "#.###,##", - "timezones": [ + "timezones": + [ "America/Montevideo" - ] + ], + "locale": "es-UY" }, - "Uzbekistan": { + "Uzbekistan": + { "code": "uz", "currency": "UZS", "currency_fraction": "Tiyin", "currency_fraction_units": 100, "currency_name": "Uzbekistan Sum", - "currency_symbol": "\u043b\u0432", + "currency_symbol": "лв", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Samarkand", "Asia/Tashkent" ] }, - "Vanuatu": { + "Vanuatu": + { "code": "vu", "currency": "VUV", "currency_fraction": "None", @@ -2663,57 +3257,72 @@ "currency_name": "Vatu", "currency_symbol": "Vt", "number_format": "#,###", - "timezones": [ + "timezones": + [ "Pacific/Efate" ] }, - "Venezuela, Bolivarian Republic of": { + "Venezuela, Bolivarian Republic of": + { "code": "ve", "number_format": "#.###,##", "currency": "VEF", "currency_symbol": "Bs.", "currency_fraction": "Centimos", - "currency_fraction_units": 100 + "currency_fraction_units": 100, + "locale": "es-VE" }, - "Vietnam": { + "Vietnam": + { "code": "vn", "currency": "VND", "currency_name": "Dong", - "number_format": "#.###" + "number_format": "#.###", + "locale": "vi-VN" }, - "Virgin Islands, British": { + "Virgin Islands, British": + { "code": "vg", "number_format": "#,###.##" }, - "Virgin Islands, U.S.": { + "Virgin Islands, U.S.": + { "code": "vi", - "number_format": "#,###.##" + "number_format": "#,###.##", + "locale": "en-VI" }, - "Wallis and Futuna": { + "Wallis and Futuna": + { "code": "wf", "currency_fraction": "Centime", "currency_fraction_units": 100, "currency_symbol": "Fr", "number_format": "#,###.##" }, - "Western Sahara": { + "Western Sahara": + { "code": "eh", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/El_Aaiun" ] }, - "Yemen": { + "Yemen": + { "code": "ye", "currency_fraction": "Fils", "currency_fraction_units": 100, - "currency_symbol": "\ufdfc", + "currency_symbol": "﷼", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Asia/Aden" - ] + ], + "locale": "ar-YE" }, - "Zambia": { + "Zambia": + { "code": "zm", "currency": "ZMW", "currency_fraction": "Ngwee", @@ -2721,11 +3330,14 @@ "currency_name": "Zambian Kwacha", "currency_symbol": "ZK", "number_format": "#,###.##", - "timezones": [ + "timezones": + [ "Africa/Lusaka" - ] + ], + "locale": "bem-ZM" }, - "Zimbabwe": { + "Zimbabwe": + { "code": "zw", "currency": "ZWD", "currency_fraction": "Thebe", @@ -2733,12 +3345,15 @@ "currency_name": "Zimbabwe Dollar", "currency_symbol": "P", "number_format": "# ###.##", - "timezones": [ + "timezones": + [ "Africa/Harare" - ] + ], + "locale": "en-ZW" }, - "\u00c5land Islands": { + "Åland Islands": + { "code": "ax", "number_format": "#,###.##" } -} +} \ No newline at end of file diff --git a/src/pages/GetStarted.vue b/src/pages/GetStarted.vue index dc6171e8..b2c54f76 100644 --- a/src/pages/GetStarted.vue +++ b/src/pages/GetStarted.vue @@ -134,7 +134,7 @@ export default { label: _('System'), icon: 'system', description: - 'Setup system defaults like date format and currency precision', + 'Setup system defaults like date format and display precision', fieldname: 'systemSetup', action() { openSettings('System'); diff --git a/src/pages/SetupWizard/setupCompany.js b/src/pages/SetupWizard/setupCompany.js index 80c8cfc7..232ab03c 100644 --- a/src/pages/SetupWizard/setupCompany.js +++ b/src/pages/SetupWizard/setupCompany.js @@ -1,5 +1,6 @@ import config from '@/config'; import frappe from 'frappejs'; +import { DEFAULT_LOCALE } from 'frappejs/utils/consts'; import countryList from '~/fixtures/countryInfo.json'; import generateTaxes from '../../../models/doctype/Tax/RegionalEntries'; import regionalModelUpdates from '../../../models/regionalModelUpdates'; @@ -19,6 +20,7 @@ export default async function setupCompany(setupWizardValues) { const accountingSettings = frappe.AccountingSettings; const currency = countryList[country]['currency']; + const locale = countryList[country]['locale'] ?? DEFAULT_LOCALE; await callInitializeMoneyMaker(currency); await accountingSettings.update({ @@ -47,6 +49,8 @@ export default async function setupCompany(setupWizardValues) { await accountingSettings.update({ setupComplete: 1 }); frappe.AccountingSettings = accountingSettings; + + (await frappe.getSingle('SystemSettings')).update({ locale }); } async function setupGlobalCurrencies(countries) { From 4385a93a7728c0dcd2835fc897ea66977484b82b Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Fri, 24 Dec 2021 16:02:04 +0530 Subject: [PATCH 05/25] fix: validate to true if no validation, parse into pesa on input --- src/components/Controls/Base.vue | 2 +- src/components/Controls/Currency.vue | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/Controls/Base.vue b/src/components/Controls/Base.vue index e27e35b9..ed371132 100644 --- a/src/components/Controls/Base.vue +++ b/src/components/Controls/Base.vue @@ -107,7 +107,7 @@ export default { }, validate(value) { if (!(typeof this.df.validate === 'function')) { - return; + return true; } try { diff --git a/src/components/Controls/Currency.vue b/src/components/Controls/Currency.vue index 47dfe7f5..9ecb0c23 100644 --- a/src/components/Controls/Currency.vue +++ b/src/components/Controls/Currency.vue @@ -13,7 +13,7 @@ :readonly="isReadOnly" @blur="onBlur" @focus="onFocus" - @input="e => $emit('input', e)" + @input="(e) => $emit('input', e)" />
{ this.focus(); }); - } + }, }, computed: { formattedValue() { return frappe.format(this.value, this.df, this.doc); - } - } + }, + }, }; From 1e6113e92f925fcaa43d182b7a23231f503303e3 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Mon, 27 Dec 2021 17:04:34 +0530 Subject: [PATCH 06/25] fix: update PurchaseInvoice to use pesa --- .../PurchaseInvoice/PurchaseInvoice.js | 11 ++-- .../PurchaseInvoiceItem.js | 14 ++--- models/doctype/TaxSummary/TaxSummary.js | 14 ++--- .../Transaction/TransactionDocument.js | 63 +++++++++---------- 4 files changed, 48 insertions(+), 54 deletions(-) diff --git a/models/doctype/PurchaseInvoice/PurchaseInvoice.js b/models/doctype/PurchaseInvoice/PurchaseInvoice.js index 957c7d64..bf1c447d 100644 --- a/models/doctype/PurchaseInvoice/PurchaseInvoice.js +++ b/models/doctype/PurchaseInvoice/PurchaseInvoice.js @@ -1,5 +1,5 @@ -import { getActions } from '../Transaction/Transaction'; import InvoiceTemplate from '../SalesInvoice/InvoiceTemplate.vue'; +import { getActions } from '../Transaction/Transaction'; import PurchaseInvoice from './PurchaseInvoiceDocument'; export default { @@ -61,7 +61,8 @@ export default { fieldname: 'exchangeRate', label: 'Exchange Rate', fieldtype: 'Float', - formula: (doc) => doc.getExchangeRate(), + default: 1, + formula: async (doc) => await doc.getExchangeRate(), required: true, }, { @@ -75,7 +76,7 @@ export default { fieldname: 'netTotal', label: 'Net Total', fieldtype: 'Currency', - formula: (doc) => doc.getSum('items', 'amount'), + formula: (doc) => doc.getSum('items', 'amount', false), readOnly: 1, getCurrency: (doc) => doc.currency, }, @@ -83,7 +84,7 @@ export default { fieldname: 'baseNetTotal', label: 'Net Total (Company Currency)', fieldtype: 'Currency', - formula: (doc) => doc.netTotal * doc.exchangeRate, + formula: (doc) => doc.netTotal.mul(doc.exchangeRate), readOnly: 1, }, { @@ -106,7 +107,7 @@ export default { fieldname: 'baseGrandTotal', label: 'Grand Total (Company Currency)', fieldtype: 'Currency', - formula: (doc) => doc.grandTotal * doc.exchangeRate, + formula: (doc) => doc.grandTotal.mul(doc.exchangeRate), readOnly: 1, }, { diff --git a/models/doctype/PurchaseInvoiceItem/PurchaseInvoiceItem.js b/models/doctype/PurchaseInvoiceItem/PurchaseInvoiceItem.js index 35f8eef0..dfa031e9 100644 --- a/models/doctype/PurchaseInvoiceItem/PurchaseInvoiceItem.js +++ b/models/doctype/PurchaseInvoiceItem/PurchaseInvoiceItem.js @@ -32,7 +32,7 @@ export default { label: 'Quantity', fieldtype: 'Float', required: 1, - formula: () => 1, + default: 1, }, { fieldname: 'rate', @@ -40,9 +40,9 @@ export default { fieldtype: 'Currency', required: 1, formula: async (row, doc) => { - const baseRate = (await doc.getFrom('Item', row.item, 'rate')) || 0; - const exchangeRate = doc.exchangeRate ?? 1; - return baseRate / exchangeRate; + const baseRate = + (await doc.getFrom('Item', row.item, 'rate')) || frappe.pesa(0); + return baseRate.div(doc.exchangeRate); }, getCurrency: (row, doc) => doc.currency, }, @@ -50,7 +50,7 @@ export default { fieldname: 'baseRate', label: 'Rate (Company Currency)', fieldtype: 'Currency', - formula: (row, doc) => row.rate * doc.exchangeRate, + formula: (row, doc) => row.rate.mul(doc.exchangeRate), readOnly: 1, }, { @@ -76,7 +76,7 @@ export default { label: 'Amount', fieldtype: 'Currency', readOnly: 1, - formula: (row) => row.quantity * row.rate, + formula: (row) => row.rate.mul(row.quantity), getCurrency: (row, doc) => doc.currency, }, { @@ -84,7 +84,7 @@ export default { label: 'Amount (Company Currency)', fieldtype: 'Currency', readOnly: 1, - formula: (row, doc) => row.amount * doc.exchangeRate, + formula: (row, doc) => row.amount.mul(doc.exchangeRate), }, ], }; diff --git a/models/doctype/TaxSummary/TaxSummary.js b/models/doctype/TaxSummary/TaxSummary.js index f5d1f7ba..dc130167 100644 --- a/models/doctype/TaxSummary/TaxSummary.js +++ b/models/doctype/TaxSummary/TaxSummary.js @@ -8,26 +8,26 @@ export default { label: 'Tax Account', fieldtype: 'Link', target: 'Account', - required: 1 + required: 1, }, { fieldname: 'rate', label: 'Rate', fieldtype: 'Float', - required: 1 + required: 1, }, { fieldname: 'amount', label: 'Amount', fieldtype: 'Currency', - required: 1 + required: 1, }, { fieldname: 'baseAmount', label: 'Amount (Company Currency)', fieldtype: 'Currency', - formula: (row, doc) => row.amount * doc.exchangeRate, - readOnly: 1 - } - ] + formula: (row, doc) => row.amount.mul(doc.exchangeRate), + readOnly: 1, + }, + ], }; diff --git a/models/doctype/Transaction/TransactionDocument.js b/models/doctype/Transaction/TransactionDocument.js index f4fa7bfa..3fc7747a 100644 --- a/models/doctype/Transaction/TransactionDocument.js +++ b/models/doctype/Transaction/TransactionDocument.js @@ -1,11 +1,10 @@ -import BaseDocument from 'frappejs/model/document'; import frappe from 'frappejs'; -import { round } from 'frappejs/utils/numberFormat'; +import BaseDocument from 'frappejs/model/document'; import { getExchangeRate } from '../../../accounting/exchangeRate'; export default class TransactionDocument extends BaseDocument { async getExchangeRate() { - if (!this.currency) return; + if (!this.currency) return 1.0; let accountingSettings = await frappe.getSingle('AccountingSettings'); const companyCurrency = accountingSettings.currency; @@ -14,7 +13,7 @@ export default class TransactionDocument extends BaseDocument { } return await getExchangeRate({ fromCurrency: this.currency, - toCurrency: companyCurrency + toCurrency: companyCurrency, }); } @@ -22,31 +21,30 @@ export default class TransactionDocument extends BaseDocument { let taxes = {}; for (let row of this.items) { - if (row.tax) { - let tax = await this.getTax(row.tax); - for (let d of tax.details) { - let amount = (row.amount * d.rate) / 100; - taxes[d.account] = taxes[d.account] || { - account: d.account, - rate: d.rate, - amount: 0 - }; - // collect amount - taxes[d.account].amount += amount; - } + if (!row.tax) { + continue; + } + + const tax = await this.getTax(row.tax); + for (let d of tax.details) { + taxes[d.account] = taxes[d.account] || { + account: d.account, + rate: d.rate, + amount: frappe.pesa(0), + }; + + const amount = row.amount.mul(d.rate).div(100); + taxes[d.account].amount = taxes[d.account].amount.add(amount); } } - return ( - Object.keys(taxes) - .map(account => { - let tax = taxes[account]; - tax.baseAmount = round(tax.amount * this.exchangeRate, 2); - return tax; - }) - // clear rows with 0 amount - .filter(tax => tax.amount) - ); + return Object.keys(taxes) + .map((account) => { + const tax = taxes[account]; + tax.baseAmount = tax.amount.mul(this.exchangeRate); + return tax; + }) + .filter((tax) => !tax.amount.isZero()); } async getTax(tax) { @@ -56,13 +54,8 @@ export default class TransactionDocument extends BaseDocument { } async getGrandTotal() { - let grandTotal = this.netTotal; - if (this.taxes) { - for (let row of this.taxes) { - grandTotal += row.amount; - } - } - - return grandTotal; + return (this.taxes || []) + .map(({ amount }) => amount) + .reduce((a, b) => a.add(b), this.netTotal); } -}; +} From 5c6ac0e16149b078d557ddd7b1e6febf62a6222c Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 28 Dec 2021 12:01:42 +0530 Subject: [PATCH 07/25] fix: currency field display (PI) --- models/doctype/PurchaseInvoice/PurchaseInvoice.js | 4 +++- src/components/Controls/Currency.vue | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/models/doctype/PurchaseInvoice/PurchaseInvoice.js b/models/doctype/PurchaseInvoice/PurchaseInvoice.js index bf1c447d..1405eaf9 100644 --- a/models/doctype/PurchaseInvoice/PurchaseInvoice.js +++ b/models/doctype/PurchaseInvoice/PurchaseInvoice.js @@ -54,7 +54,9 @@ export default { fieldtype: 'Link', target: 'Currency', hidden: 1, - formula: (doc) => doc.getFrom('Party', doc.supplier, 'currency'), + formula: (doc) => + doc.getFrom('Party', doc.supplier, 'currency') || + frappe.AccountingSettings.currency, formulaDependsOn: ['supplier'], }, { diff --git a/src/components/Controls/Currency.vue b/src/components/Controls/Currency.vue index 9ecb0c23..67e68dfc 100644 --- a/src/components/Controls/Currency.vue +++ b/src/components/Controls/Currency.vue @@ -8,7 +8,7 @@ ref="input" :class="inputClasses" :type="inputType" - :value="value" + :value="value.round()" :placeholder="inputPlaceholder" :readonly="isReadOnly" @blur="onBlur" @@ -49,8 +49,13 @@ export default { return frappe.pesa(value); }, onBlur(e) { + let { value } = e.target; + if (value === '') { + value = frappe.pesa(0).round(); + } + this.showInput = false; - this.triggerChange(e.target.value); + this.triggerChange(value); }, activateInput() { this.showInput = true; From c9349b0570db0884eb401039741c1e2eae126665 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 28 Dec 2021 13:35:53 +0530 Subject: [PATCH 08/25] fix: update ledger posting calculations --- accounting/ledgerPosting.js | 60 ++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/accounting/ledgerPosting.js b/accounting/ledgerPosting.js index 965fe9d0..2febe251 100644 --- a/accounting/ledgerPosting.js +++ b/accounting/ledgerPosting.js @@ -1,5 +1,4 @@ import frappe from 'frappejs'; -import { round } from 'frappejs/utils/numberFormat'; export default class LedgerPosting { constructor({ reference, party, date, description }) { @@ -16,13 +15,13 @@ export default class LedgerPosting { async debit(account, amount, referenceType, referenceName) { const entry = this.getEntry(account, referenceType, referenceName); - entry.debit += amount; + entry.debit = entry.debit.add(amount); await this.setAccountBalanceChange(account, 'debit', amount); } async credit(account, amount, referenceType, referenceName) { const entry = this.getEntry(account, referenceType, referenceName); - entry.credit += amount; + entry.credit = entry.credit.add(amount); await this.setAccountBalanceChange(account, 'credit', amount); } @@ -30,16 +29,16 @@ export default class LedgerPosting { const debitAccounts = ['Asset', 'Expense']; const { rootType } = await frappe.getDoc('Account', accountName); if (debitAccounts.indexOf(rootType) === -1) { - const change = type == 'credit' ? amount : -1 * amount; + const change = type == 'credit' ? amount : amount.mul(-1); this.accountEntries.push({ name: accountName, - balanceChange: change + balanceChange: change, }); } else { - const change = type == 'debit' ? amount : -1 * amount; + const change = type == 'debit' ? amount : amount.mul(-1); this.accountEntries.push({ name: accountName, - balanceChange: change + balanceChange: change, }); } } @@ -54,8 +53,8 @@ export default class LedgerPosting { referenceName: referenceName || this.reference.name, description: this.description, reverted: this.reverted, - debit: 0, - credit: 0 + debit: frappe.pesa(0), + credit: frappe.pesa(0), }; this.entries.push(entry); @@ -78,8 +77,8 @@ export default class LedgerPosting { fields: ['name'], filters: { referenceName: this.reference.name, - reverted: 0 - } + reverted: 0, + }, }); for (let entry of data) { @@ -96,24 +95,23 @@ export default class LedgerPosting { entry.reverted = 1; } for (let entry of this.accountEntries) { - entry.balanceChange = -1 * entry.balanceChange; + entry.balanceChange = entry.balanceChange.mul(-1); } await this.insertEntries(); } makeRoundOffEntry() { let { debit, credit } = this.getTotalDebitAndCredit(); - let precision = this.getPrecision(); - let difference = round(debit - credit, precision); - let absoluteValue = Math.abs(difference); + let difference = debit.sub(credit); + let absoluteValue = difference.abs(); let allowance = 0.5; - if (absoluteValue === 0) { + if (absoluteValue.eq(0)) { return; } let roundOffAccount = this.getRoundOffAccount(); - if (absoluteValue <= allowance) { - if (difference > 0) { + if (absoluteValue.lte(allowance)) { + if (difference.gt(0)) { this.credit(roundOffAccount, absoluteValue); } else { this.debit(roundOffAccount, absoluteValue); @@ -123,49 +121,41 @@ export default class LedgerPosting { validateEntries() { let { debit, credit } = this.getTotalDebitAndCredit(); - if (debit !== credit) { + if (!debit.eq(credit)) { throw new Error( - `Total Debit (${debit}) must be equal to Total Credit (${credit})` + `Total Debit (${debit.round()}) must be equal to Total Credit (${credit.round()})` ); } } getTotalDebitAndCredit() { - let debit = 0; - let credit = 0; + let debit = frappe.pesa(0); + let credit = frappe.pesa(0); for (let entry of this.entries) { - debit += entry.debit; - credit += entry.credit; + debit = debit.add(entry.debit); + credit = credit.add(entry.credit); } - let precision = this.getPrecision(); - debit = round(debit, precision); - credit = round(credit, precision); - return { debit, credit }; } async insertEntries() { for (let entry of this.entries) { let entryDoc = frappe.newDoc({ - doctype: 'AccountingLedgerEntry' + doctype: 'AccountingLedgerEntry', }); Object.assign(entryDoc, entry); await entryDoc.insert(); } for (let entry of this.accountEntries) { let entryDoc = await frappe.getDoc('Account', entry.name); - entryDoc.balance += entry.balanceChange; + entryDoc.balance = entryDoc.balance.add(entry.balanceChange); await entryDoc.update(); } } - getPrecision() { - return frappe.SystemSettings.internalPrecision; - } - getRoundOffAccount() { return frappe.AccountingSettings.roundOffAccount; } -}; +} From 5f4a9ceeb12165ed79972941e71524023e74e670 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 28 Dec 2021 13:45:19 +0530 Subject: [PATCH 09/25] fix: update SalesInvoice --- models/doctype/SalesInvoice/SalesInvoice.js | 11 +++++++---- .../doctype/SalesInvoiceItem/SalesInvoiceItem.js | 14 +++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/models/doctype/SalesInvoice/SalesInvoice.js b/models/doctype/SalesInvoice/SalesInvoice.js index 3612b795..c7631549 100644 --- a/models/doctype/SalesInvoice/SalesInvoice.js +++ b/models/doctype/SalesInvoice/SalesInvoice.js @@ -53,13 +53,16 @@ export default { label: 'Customer Currency', fieldtype: 'Link', target: 'Currency', - formula: (doc) => doc.getFrom('Party', doc.customer, 'currency'), + formula: (doc) => + doc.getFrom('Party', doc.customer, 'currency') || + frappe.AccountingSettings.currency, formulaDependsOn: ['customer'], }, { fieldname: 'exchangeRate', label: 'Exchange Rate', fieldtype: 'Float', + default: 1, formula: (doc) => doc.getExchangeRate(), readOnly: true, }, @@ -74,7 +77,7 @@ export default { fieldname: 'netTotal', label: 'Net Total', fieldtype: 'Currency', - formula: (doc) => doc.getSum('items', 'amount'), + formula: (doc) => doc.getSum('items', 'amount', false), readOnly: 1, getCurrency: (doc) => doc.currency, }, @@ -82,7 +85,7 @@ export default { fieldname: 'baseNetTotal', label: 'Net Total (Company Currency)', fieldtype: 'Currency', - formula: (doc) => doc.netTotal * doc.exchangeRate, + formula: (doc) => doc.netTotal.mul(doc.exchangeRate), readOnly: 1, }, { @@ -105,7 +108,7 @@ export default { fieldname: 'baseGrandTotal', label: 'Grand Total (Company Currency)', fieldtype: 'Currency', - formula: (doc) => doc.grandTotal * doc.exchangeRate, + formula: (doc) => doc.grandTotal.mul(doc.exchangeRate), readOnly: 1, }, { diff --git a/models/doctype/SalesInvoiceItem/SalesInvoiceItem.js b/models/doctype/SalesInvoiceItem/SalesInvoiceItem.js index 98a36a72..08f2adac 100644 --- a/models/doctype/SalesInvoiceItem/SalesInvoiceItem.js +++ b/models/doctype/SalesInvoiceItem/SalesInvoiceItem.js @@ -34,7 +34,7 @@ export default { label: 'Quantity', fieldtype: 'Float', required: 1, - formula: (row) => row.quantity || 1, + default: 1, }, { fieldname: 'rate', @@ -42,9 +42,9 @@ export default { fieldtype: 'Currency', required: 1, formula: async (row, doc) => { - const baseRate = (await doc.getFrom('Item', row.item, 'rate')) || 0; - const exchangeRate = doc.exchangeRate ?? 1; - return baseRate / exchangeRate; + const baseRate = + (await doc.getFrom('Item', row.item, 'rate')) || frappe.pesa(0); + return baseRate.div(doc.exchangeRate); }, getCurrency: (row, doc) => doc.currency, formulaDependsOn: ['item'], @@ -53,7 +53,7 @@ export default { fieldname: 'baseRate', label: 'Rate (Company Currency)', fieldtype: 'Currency', - formula: (row, doc) => row.rate * doc.exchangeRate, + formula: (row, doc) => row.rate.mul(doc.exchangeRate), readOnly: 1, }, { @@ -78,7 +78,7 @@ export default { label: 'Amount', fieldtype: 'Currency', readOnly: 1, - formula: (row) => row.quantity * row.rate, + formula: (row) => row.rate.mul(row.quantity), getCurrency: (row, doc) => doc.currency, }, { @@ -86,7 +86,7 @@ export default { label: 'Amount (Company Currency)', fieldtype: 'Currency', readOnly: 1, - formula: (row, doc) => row.amount * doc.exchangeRate, + formula: (row, doc) => row.amount.mul(doc.exchangeRate), }, ], }; From ed16c47b421cee6aa5475bce591305e1c36e9d58 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 29 Dec 2021 11:31:29 +0530 Subject: [PATCH 10/25] fix: patch 0 for null currency values --- patches/0.0.4/convertCurrencyToStrings.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/patches/0.0.4/convertCurrencyToStrings.js b/patches/0.0.4/convertCurrencyToStrings.js index a4a72ca7..84bcd8ac 100644 --- a/patches/0.0.4/convertCurrencyToStrings.js +++ b/patches/0.0.4/convertCurrencyToStrings.js @@ -29,10 +29,7 @@ export default async function execute() { const rows = await frappe.db.knex(name); const convertedRows = rows.map((row) => { for (let field of fields) { - if (row[field] === null) { - continue; - } - row[field] = frappe.pesa(row[field]).store; + row[field] = frappe.pesa(row[field] ?? 0).store; } return row; }); From 8583db75d6f257254391b69a64695d55e196dca0 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 29 Dec 2021 11:59:26 +0530 Subject: [PATCH 11/25] fix: update payments to use pesa --- models/doctype/Payment/Payment.js | 11 ++++--- models/doctype/Payment/PaymentServer.js | 39 ++++++++++++++++--------- models/doctype/PaymentFor/PaymentFor.js | 13 +++++---- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/models/doctype/Payment/Payment.js b/models/doctype/Payment/Payment.js index 00ca943d..d58b060c 100644 --- a/models/doctype/Payment/Payment.js +++ b/models/doctype/Payment/Payment.js @@ -109,9 +109,9 @@ export default { label: 'Amount', fieldtype: 'Currency', required: 1, - formula: (doc) => doc.getSum('for', 'amount'), + formula: (doc) => doc.getSum('for', 'amount', false), validate(value, doc) { - if (value < 0) { + if (value.isNegative()) { throw new frappe.errors.ValidationError( frappe._( `Payment amount cannot be less than zero. Amount has been reset.` @@ -120,9 +120,9 @@ export default { } if (doc.for.length === 0) return; - const amount = doc.getSum('for', 'amount'); + const amount = doc.getSum('for', 'amount', false); - if (value > amount) { + if (value.gt(amount)) { throw new frappe.errors.ValidationError( frappe._( `Payment amount cannot exceed ${frappe.format( @@ -131,7 +131,7 @@ export default { )}. Amount has been reset.` ) ); - } else if (value === 0) { + } else if (value.isZero()) { throw new frappe.errors.ValidationError( frappe._( `Payment amount cannot be ${frappe.format( @@ -147,7 +147,6 @@ export default { fieldname: 'writeoff', label: 'Write Off / Refund', fieldtype: 'Currency', - default: 0, }, { fieldname: 'for', diff --git a/models/doctype/Payment/PaymentServer.js b/models/doctype/Payment/PaymentServer.js index 32931f64..d5660c32 100644 --- a/models/doctype/Payment/PaymentServer.js +++ b/models/doctype/Payment/PaymentServer.js @@ -46,9 +46,9 @@ export default class PaymentServer extends BaseDocument { } updateAmountOnReferenceUpdate() { - this.amount = 0; + this.amount = frappe.pesa(0); for (let paymentReference of this.for) { - this.amount += paymentReference.amount; + this.amount = this.amount.add(paymentReference.amount); } } @@ -73,18 +73,19 @@ export default class PaymentServer extends BaseDocument { if (!this.for?.length) return; const referenceAmountTotal = this.for .map(({ amount }) => amount) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a.add(b), frappe.pesa(0)); - if (this.amount + (this.writeoff ?? 0) < referenceAmountTotal) { + if (this.amount.add(this.writeoff ?? 0).lt(referenceAmountTotal)) { const writeoff = frappe.format(this.writeoff, 'Currency'); const payment = frappe.format(this.amount, 'Currency'); const refAmount = frappe.format(referenceAmountTotal, 'Currency'); - const writeoffString = - this.writeoff > 0 ? `and writeoff: ${writeoff} ` : ''; + const writeoffString = this.writeoff.gt(0) + ? `and writeoff: ${writeoff} ` + : ''; throw new Error( frappe._( - `Amount: ${payment} ${writeoffString}is less than the total amount allocated to references: ${refAmount}` + `Amount: ${payment} ${writeoffString}is less than the total amount allocated to references: ${refAmount}.` ) ); } @@ -113,18 +114,28 @@ export default class PaymentServer extends BaseDocument { if (outstandingAmount == null) { outstandingAmount = baseGrandTotal; } - if (this.amount <= 0 || this.amount > outstandingAmount) { + if (this.amount.lte(0) || this.amount.gt(outstandingAmount)) { let message = frappe._( - `Payment amount (${this.amount}) should be less than Outstanding amount (${outstandingAmount}).` + `Payment amount: ${frappe.format( + this.amount, + 'Currency' + )} should be less than Outstanding amount: ${frappe.format( + outstandingAmount, + 'Currency' + )}.` ); - if (this.amount <= 0) { - const amt = this.amount < 0 ? ` (${this.amount})` : ''; + + if (this.amount.lte(0)) { + const amt = this.amount.lt(0) + ? `: ${frappe.format(this.amount, 'Currency')}` + : ''; message = frappe._(`Payment amount${amt} should be greater than 0.`); } + throw new frappe.errors.ValidationError(message); } else { // update outstanding amounts in invoice and party - let newOutstanding = outstandingAmount - this.amount; + let newOutstanding = outstandingAmount.sub(this.amount); await referenceDoc.set('outstandingAmount', newOutstanding); await referenceDoc.update(); let party = await frappe.getDoc('Party', this.party); @@ -147,7 +158,9 @@ export default class PaymentServer extends BaseDocument { async updateReferenceOutstandingAmount() { await this.for.forEach(async ({ amount, referenceType, referenceName }) => { const refDoc = await frappe.getDoc(referenceType, referenceName); - refDoc.update({ outstandingAmount: refDoc.outstandingAmount + amount }); + refDoc.update({ + outstandingAmount: refDoc.outstandingAmount.add(amount), + }); }); } } diff --git a/models/doctype/PaymentFor/PaymentFor.js b/models/doctype/PaymentFor/PaymentFor.js index 7fd4153f..cee513df 100644 --- a/models/doctype/PaymentFor/PaymentFor.js +++ b/models/doctype/PaymentFor/PaymentFor.js @@ -1,4 +1,6 @@ +import frappe from 'frappejs'; import { _ } from 'frappejs/utils'; + const referenceTypeMap = { SalesInvoice: _('Invoice'), PurchaseInvoice: _('Bill'), @@ -38,12 +40,13 @@ export default { fieldname: 'amount', label: 'Amount', fieldtype: 'Currency', - placeholder: '0.00', formula: (row, doc) => { - return doc.getFrom( - row.referenceType, - row.referenceName, - 'outstandingAmount' + return ( + doc.getFrom( + row.referenceType, + row.referenceName, + 'outstandingAmount' + ) || frappe.pesa(0) ); }, required: 1, From b4957c3a644c2928a7a6401cf75b3f674943512f Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 29 Dec 2021 13:00:15 +0530 Subject: [PATCH 12/25] fix: update JE, fix validation message --- accounting/ledgerPosting.js | 5 +++- .../JournalEntry/JournalEntryServer.js | 6 ++--- .../JournalEntryAccount.js | 27 ++++++++++--------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/accounting/ledgerPosting.js b/accounting/ledgerPosting.js index 2febe251..57583eff 100644 --- a/accounting/ledgerPosting.js +++ b/accounting/ledgerPosting.js @@ -123,7 +123,10 @@ export default class LedgerPosting { let { debit, credit } = this.getTotalDebitAndCredit(); if (!debit.eq(credit)) { throw new Error( - `Total Debit (${debit.round()}) must be equal to Total Credit (${credit.round()})` + `Total Debit: ${frappe.format( + debit, + 'Currency' + )} must be equal to Total Credit: ${frappe.format(credit, 'Currency')}` ); } } diff --git a/models/doctype/JournalEntry/JournalEntryServer.js b/models/doctype/JournalEntry/JournalEntryServer.js index 69a24fc7..f9a271ed 100644 --- a/models/doctype/JournalEntry/JournalEntryServer.js +++ b/models/doctype/JournalEntry/JournalEntryServer.js @@ -6,9 +6,9 @@ export default class JournalEntryServer extends BaseDocument { let entries = new LedgerPosting({ reference: this }); for (let row of this.accounts) { - if (row.debit) { + if (!row.debit.isZero()) { entries.debit(row.account, row.debit); - } else if (row.credit) { + } else if (!row.credit.isZero()) { entries.credit(row.account, row.credit); } } @@ -31,4 +31,4 @@ export default class JournalEntryServer extends BaseDocument { async afterRevert() { await this.getPosting().postReverse(); } -}; +} diff --git a/models/doctype/JournalEntryAccount/JournalEntryAccount.js b/models/doctype/JournalEntryAccount/JournalEntryAccount.js index 75b5b611..dc6e601c 100644 --- a/models/doctype/JournalEntryAccount/JournalEntryAccount.js +++ b/models/doctype/JournalEntryAccount/JournalEntryAccount.js @@ -10,34 +10,35 @@ export default { target: 'Account', required: 1, groupBy: 'rootType', - getFilters: () => ({ isGroup: 0 }) + getFilters: () => ({ isGroup: 0 }), }, { fieldname: 'debit', label: 'Debit', fieldtype: 'Currency', - formula: autoDebitCredit('debit') + formula: autoDebitCredit('debit'), }, { fieldname: 'credit', label: 'Credit', fieldtype: 'Currency', - formula: autoDebitCredit('credit') - } + formula: autoDebitCredit('credit'), + }, ], - tableFields: ['account', 'debit', 'credit'] + tableFields: ['account', 'debit', 'credit'], }; -function autoDebitCredit(type = 'debit') { +function autoDebitCredit(type) { let otherType = type === 'debit' ? 'credit' : 'debit'; - return (row, doc) => { - if (row[type] == 0) return null; - if (row[otherType]) return null; - let totalType = doc.getSum('accounts', type); - let totalOtherType = doc.getSum('accounts', otherType); - if (totalType < totalOtherType) { - return totalOtherType - totalType; + return (row, doc) => { + if (!row[otherType].isZero()) return frappe.pesa(0); + + let totalType = doc.getSum('accounts', type, false); + let totalOtherType = doc.getSum('accounts', otherType, false); + + if (totalType.lt(totalOtherType)) { + return totalOtherType.sub(totalType); } }; } From 373684aab728786c7f576429a99a5127574d6f8d Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 29 Dec 2021 13:12:21 +0530 Subject: [PATCH 13/25] fix: update Account, Item models Currency fields --- models/doctype/Account/Account.js | 1 - models/doctype/Item/Item.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/models/doctype/Account/Account.js b/models/doctype/Account/Account.js index 61ddf4f7..f859f8d3 100644 --- a/models/doctype/Account/Account.js +++ b/models/doctype/Account/Account.js @@ -68,7 +68,6 @@ export default { fieldname: 'balance', label: 'Balance', fieldtype: 'Currency', - default: '0', readOnly: 1, }, { diff --git a/models/doctype/Item/Item.js b/models/doctype/Item/Item.js index 324df387..3a096093 100644 --- a/models/doctype/Item/Item.js +++ b/models/doctype/Item/Item.js @@ -104,9 +104,8 @@ export default { fieldname: 'rate', label: 'Rate', fieldtype: 'Currency', - placeholder: '0.00', validate(value) { - if (!value) { + if (value.lte(0)) { throw new frappe.errors.ValidationError( 'Rate must be greater than 0' ); From de17463bd21fb3d23bc7bb81c5c58e6edeaee1ca Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 29 Dec 2021 17:03:58 +0530 Subject: [PATCH 14/25] fix: use neg, neq, update reports GL, PnL, BS, TB --- accounting/ledgerPosting.js | 8 +- .../FinancialStatements.js | 115 +++++++++++------- reports/GeneralLedger/GeneralLedger.js | 9 +- 3 files changed, 81 insertions(+), 51 deletions(-) diff --git a/accounting/ledgerPosting.js b/accounting/ledgerPosting.js index 57583eff..4bd9c603 100644 --- a/accounting/ledgerPosting.js +++ b/accounting/ledgerPosting.js @@ -29,13 +29,13 @@ export default class LedgerPosting { const debitAccounts = ['Asset', 'Expense']; const { rootType } = await frappe.getDoc('Account', accountName); if (debitAccounts.indexOf(rootType) === -1) { - const change = type == 'credit' ? amount : amount.mul(-1); + const change = type == 'credit' ? amount : amount.neg(); this.accountEntries.push({ name: accountName, balanceChange: change, }); } else { - const change = type == 'debit' ? amount : amount.mul(-1); + const change = type == 'debit' ? amount : amount.neg(); this.accountEntries.push({ name: accountName, balanceChange: change, @@ -95,7 +95,7 @@ export default class LedgerPosting { entry.reverted = 1; } for (let entry of this.accountEntries) { - entry.balanceChange = entry.balanceChange.mul(-1); + entry.balanceChange = entry.balanceChange.neg(); } await this.insertEntries(); } @@ -121,7 +121,7 @@ export default class LedgerPosting { validateEntries() { let { debit, credit } = this.getTotalDebitAndCredit(); - if (!debit.eq(credit)) { + if (debit.neq(credit)) { throw new Error( `Total Debit: ${frappe.format( debit, diff --git a/reports/FinancialStatements/FinancialStatements.js b/reports/FinancialStatements/FinancialStatements.js index d9aaf1b7..7747ad14 100644 --- a/reports/FinancialStatements/FinancialStatements.js +++ b/reports/FinancialStatements/FinancialStatements.js @@ -1,6 +1,6 @@ import frappe from 'frappejs'; +import { isPesa } from 'frappejs/utils'; import { DateTime } from 'luxon'; -import { unique } from 'frappejs/utils'; export async function getData({ rootType, @@ -8,7 +8,7 @@ export async function getData({ fromDate, toDate, periodicity = 'Monthly', - accumulateValues = false + accumulateValues = false, }) { let accounts = await getAccounts(rootType); let fiscalYear = await getFiscalYear(); @@ -17,19 +17,19 @@ export async function getData({ for (let account of accounts) { const entries = ledgerEntries.filter( - entry => entry.account === account.name + (entry) => entry.account === account.name ); for (let entry of entries) { let periodKey = getPeriodKey(entry.date, periodicity); if (!account[periodKey]) { - account[periodKey] = 0.0; + account[periodKey] = frappe.pesa(0.0); } const multiplier = balanceMustBe === 'Debit' ? 1 : -1; - const value = (entry.debit - entry.credit) * multiplier; - account[periodKey] += value; + const value = entry.debit.sub(entry.credit).mul(multiplier); + account[periodKey] = value.add(account[periodKey]); } } @@ -40,28 +40,34 @@ export async function getData({ for (let account of accounts) { if (!account[periodKey]) { - account[periodKey] = 0.0; + account[periodKey] = frappe.pesa(0.0); } - account[periodKey] += account[previousPeriodKey] || 0.0; + + account[periodKey] = account[periodKey].add( + account[previousPeriodKey] ?? 0 + ); } }); } // calculate totalRow let totalRow = { - account: `Total ${rootType} (${balanceMustBe})` + account: `Total ${rootType} (${balanceMustBe})`, }; - periodList.forEach(periodKey => { + periodList.forEach((periodKey) => { if (!totalRow[periodKey]) { - totalRow[periodKey] = 0.0; + totalRow[periodKey] = frappe.pesa(0.0); } for (let account of accounts) { - totalRow[periodKey] += account[periodKey] || 0.0; + totalRow[periodKey] = totalRow[periodKey].add(account[periodKey] ?? 0.0); } }); + convertToFloat(totalRow); + accounts.forEach(convertToFloat); + return { accounts, totalRow, periodList }; } @@ -71,42 +77,50 @@ export async function getTrialBalance({ rootType, fromDate, toDate }) { for (let account of accounts) { const accountEntries = ledgerEntries.filter( - entry => entry.account === account.name + (entry) => entry.account === account.name ); // opening const beforePeriodEntries = accountEntries.filter( - entry => entry.date < fromDate + (entry) => entry.date < fromDate + ); + account.opening = beforePeriodEntries.reduce( + (acc, entry) => acc.add(entry.debit).sub(entry.credit), + frappe.pesa(0) ); - account.opening = beforePeriodEntries.reduce((acc, entry) => { - return acc + (entry.debit - entry.credit); - }, 0); - if (account.opening >= 0) { + if (account.opening.gte(0)) { account.openingDebit = account.opening; + account.openingCredit = frappe.pesa(0); } else { - account.openingCredit = -account.opening; + account.openingCredit = account.opening.neg(); + account.openingDebit = frappe.pesa(0); } // debit / credit const periodEntries = accountEntries.filter( - entry => entry.date >= fromDate && entry.date < toDate + (entry) => entry.date >= fromDate && entry.date < toDate + ); + account.debit = periodEntries.reduce( + (acc, entry) => acc.add(entry.debit), + frappe.pesa(0) ); - account.debit = periodEntries.reduce((acc, entry) => acc + entry.debit, 0); account.credit = periodEntries.reduce( - (acc, entry) => acc + entry.credit, - 0 + (acc, entry) => acc.add(entry.credit), + frappe.pesa(0) ); // closing - account.closing = account.opening + account.debit - account.credit; + account.closing = account.opening.add(account.debit).sub(account.credit); - if (account.closing >= 0) { + if (account.closing.gte(0)) { account.closingDebit = account.closing; + account.closingCredit = frappe.pesa(0); } else { - account.closingCredit = -account.closing; + account.closingCredit = account.closing.neg(); + account.closingDebit = frappe.pesa(0); } - if (account.debit != 0 || account.credit != 0) { + if (account.debit.neq(0) || account.credit.neq(0)) { setParentEntry(account, account.parentAccount); } } @@ -114,13 +128,13 @@ export async function getTrialBalance({ rootType, fromDate, toDate }) { function setParentEntry(leafAccount, parentName) { for (let acc of accounts) { if (acc.name === parentName) { - acc.debit += leafAccount.debit; - acc.credit += leafAccount.credit; - acc.closing = acc.opening + acc.debit - acc.credit; - if (acc.closing >= 0) { + acc.debit = acc.debit.add(leafAccount.debit); + acc.credit = acc.credit.add(leafAccount.credit); + acc.closing = acc.opening.add(acc.debit).sub(acc.credit); + if (acc.closing.gte(0)) { acc.closingDebit = acc.closing; } else { - acc.closingCredit = -acc.closing; + acc.closingCredit = acc.closing.neg(); } if (acc.parentAccount) { setParentEntry(leafAccount, acc.parentAccount); @@ -131,6 +145,7 @@ export async function getTrialBalance({ rootType, fromDate, toDate }) { } } + accounts.forEach(convertToFloat); return accounts; } @@ -143,7 +158,7 @@ export function getPeriodList(fromDate, toDate, periodicity, fiscalYear) { Monthly: 1, Quarterly: 3, 'Half Yearly': 6, - Yearly: 12 + Yearly: 12, }[periodicity]; let startDate = DateTime.fromISO(fromDate).startOf('month'); @@ -173,13 +188,13 @@ function getPeriodKey(date, periodicity) { 1: `Jan ${year} - Mar ${year}`, 2: `Apr ${year} - Jun ${year}`, 3: `Jun ${year} - Sep ${year}`, - 4: `Oct ${year} - Dec ${year}` + 4: `Oct ${year} - Dec ${year}`, }[quarter]; }, 'Half Yearly': () => { return { 1: `Apr ${year} - Sep ${year}`, - 2: `Oct ${year} - Mar ${year}` + 2: `Oct ${year} - Mar ${year}`, }[[2, 3].includes(quarter) ? 1 : 2]; }, Yearly: () => { @@ -187,7 +202,7 @@ function getPeriodKey(date, periodicity) { return `${year} - ${year + 1}`; } return `${year - 1} - ${year}`; - } + }, }[periodicity]; return getKey(); @@ -200,7 +215,7 @@ function setIndentLevel(accounts, parentAccount, level) { level = 0; } - accounts.forEach(account => { + accounts.forEach((account) => { if ( account.parentAccount === parentAccount && account.indent === undefined @@ -220,7 +235,7 @@ function sortAccounts(accounts) { pushToOut(null); function pushToOut(parentAccount) { - accounts.forEach(account => { + accounts.forEach((account) => { if (account.parentAccount === parentAccount && !pushed[account.name]) { out.push(account); pushed[account.name] = 1; @@ -247,9 +262,9 @@ async function getLedgerEntries(fromDate, toDate, accounts) { doctype: 'AccountingLedgerEntry', fields: ['account', 'debit', 'credit', 'date'], filters: { - account: ['in', accounts.map(d => d.name)], - date: dateFilter() - } + account: ['in', accounts.map((d) => d.name)], + date: dateFilter(), + }, }); return ledgerEntries; @@ -260,14 +275,14 @@ async function getAccounts(rootType) { doctype: 'Account', fields: ['name', 'parentAccount', 'isGroup'], filters: { - rootType - } + rootType, + }, }); accounts = setIndentLevel(accounts); accounts = sortAccounts(accounts); - accounts.forEach(account => { + accounts.forEach((account) => { account.account = account.name; }); @@ -280,12 +295,20 @@ async function getFiscalYear() { ); return { start: fiscalYearStart, - end: fiscalYearEnd + end: fiscalYearEnd, }; } +function convertToFloat(obj) { + Object.keys(obj).forEach((key) => { + if (!isPesa(obj[key])) return; + + obj[key] = obj[key].float; + }); +} + export default { getData, getTrialBalance, - getPeriodList + getPeriodList, }; diff --git a/reports/GeneralLedger/GeneralLedger.js b/reports/GeneralLedger/GeneralLedger.js index 9c6b919d..11885ff9 100644 --- a/reports/GeneralLedger/GeneralLedger.js +++ b/reports/GeneralLedger/GeneralLedger.js @@ -29,7 +29,14 @@ class GeneralLedger { ], filters: filters, }) - ).filter((d) => !d.reverted || (d.reverted && params.reverted)); + ) + .filter((d) => !d.reverted || (d.reverted && params.reverted)) + .map((row) => { + row.debit = row.debit.float; + row.credit = row.credit.float; + + return row; + }); return this.appendOpeningEntry(data); } From b69505bdbb7b1479ddf656fabffc1fd44f93e67e Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 29 Dec 2021 17:22:38 +0530 Subject: [PATCH 15/25] fix: minor fixes to dashboard --- src/pages/Dashboard/ProfitAndLoss.vue | 26 +++++++++++----------- src/pages/Dashboard/UnpaidInvoices.vue | 30 +++++++++++++------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/pages/Dashboard/ProfitAndLoss.vue b/src/pages/Dashboard/ProfitAndLoss.vue index 28686cec..33e273fa 100644 --- a/src/pages/Dashboard/ProfitAndLoss.vue +++ b/src/pages/Dashboard/ProfitAndLoss.vue @@ -5,7 +5,7 @@
@@ -28,14 +28,14 @@ export default { name: 'ProfitAndLoss', components: { PeriodSelector, - SectionHeader + SectionHeader, }, data: () => ({ period: 'This Year', hasData: false }), activated() { this.render(); }, watch: { - period: 'render' + period: 'render', }, methods: { async render() { @@ -47,11 +47,11 @@ export default { let res = await pl.run({ fromDate, toDate, - periodicity + periodicity, }); let totalRow = res.rows[res.rows.length - 1]; - this.hasData = res.columns.some(key => totalRow[key] !== 0); + this.hasData = res.columns.some((key) => totalRow[key] !== 0); if (!this.hasData) return; this.$nextTick(() => this.renderChart(res)); }, @@ -66,10 +66,10 @@ export default { axisOptions: { xAxisMode: 'tick', shortenYAxisNumbers: true, - xIsSeries: true + xIsSeries: true, }, tooltipOptions: { - formatTooltipY: value => frappe.format(value, 'Currency') + formatTooltipY: (value) => frappe.format(value ?? 0, 'Currency'), }, data: { labels: res.columns, @@ -77,12 +77,12 @@ export default { { name: 'Income', chartType: 'bar', - values: res.columns.map(key => totalRow[key]) - } - ] - } + values: res.columns.map((key) => totalRow[key]), + }, + ], + }, }); - } - } + }, + }, }; diff --git a/src/pages/Dashboard/UnpaidInvoices.vue b/src/pages/Dashboard/UnpaidInvoices.vue index 2c85586a..327124b6 100644 --- a/src/pages/Dashboard/UnpaidInvoices.vue +++ b/src/pages/Dashboard/UnpaidInvoices.vue @@ -11,7 +11,7 @@ v-if="invoice.hasData" slot="action" :value="$data[invoice.periodKey]" - @change="value => ($data[invoice.periodKey] = value)" + @change="(value) => ($data[invoice.periodKey] = value)" />