Skip to content

Commit 09d35bb

Browse files
authored
Merge pull request #545 from woocommerce/issue/312-custom-currency-mark-2
Custom Currency Formatting - Mark II
2 parents cfe11f7 + a74b2ea commit 09d35bb

File tree

5 files changed

+235
-35
lines changed

5 files changed

+235
-35
lines changed

WooCommerce/Classes/Tools/Currency/Money.swift renamed to WooCommerce/Classes/Tools/Currency/Currency.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
import Foundation
22

3-
struct Money {
4-
enum Currency: String {
3+
struct Currency {
4+
enum Code: String {
55
case AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTC, BTN, BWP, BYR, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CUC, CUP, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GGP, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, IMP, INR, IQD, IRR, IRT, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KMF, KPW, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRO, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PRB, PYG, QAR, RMB, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STD, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, UYU, UZS, VEF, VND, VUV, WST, XAF, XCD, XOF, XPF, YER, ZAR, ZMW
66
}
77

8-
var amount: NSDecimalNumber
8+
enum Position: String {
9+
case left = "left"
10+
case right = "right"
11+
case leftSpace = "left_space"
12+
case rightSpace = "right_space"
13+
}
14+
15+
var amount: String?
16+
17+
let code: Code
918

10-
let currency: Currency
19+
let position: Position
1120

1221
var symbol: String {
1322
// HTML entities and currency codes pulled from WC:
1423
// https://docs.woocommerce.com/wc-apidocs/source-function-get_woocommerce_currency.html#473
15-
switch currency {
24+
switch code {
1625
case .AED:
1726
return "د.إ".strippedHTML
1827
case .AFN:

WooCommerce/Classes/Tools/Currency/MoneyFormatter.swift

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,27 +91,79 @@ extension MoneyFormatter {
9191
return decimalValue
9292
}
9393

94-
/// Return a string formatted with the specified decimal separator
95-
///
96-
func localizeDecimal(_ decimal: NSDecimalNumber, with separator: String) -> String {
97-
let stringValue = decimal.stringValue
98-
let formattedString = stringValue.replacingOccurrences(of: ".", with: separator)
99-
100-
return formattedString
101-
}
102-
103-
/// Return a string formatted with the specified thousand separator
94+
/// Returns a formatted string for the amount. Does not contain currency symbol.
95+
/// - Parameters:
96+
/// - decimal: a valid NSDecimalNumber, preferably converted using `convertToDecimal()`
97+
/// - decimalSeparator: a string representing the user's preferred decimal symbol
98+
/// - decimalPosition: an int for positioning the decimal symbol
99+
/// - thousandSeparator: a string representing the user's preferred thousand symbol*
100+
/// *Assumes thousands grouped by 3, because a user can't indicate a preference and it's a majority default.
101+
/// Note this assumption will be wrong for India.
104102
///
105-
func localizeThousand(_ decimal: NSDecimalNumber, with separator: String) -> String? {
103+
func localizeAmount(decimal: NSDecimalNumber, decimalSeparator: String? = ".", decimalPosition: Int = 2, thousandSeparator: String? = ",") -> String? {
106104
let numberFormatter = NumberFormatter()
107105
numberFormatter.usesGroupingSeparator = true
108-
numberFormatter.groupingSeparator = separator
106+
numberFormatter.groupingSeparator = thousandSeparator
107+
numberFormatter.decimalSeparator = decimalSeparator
109108
numberFormatter.groupingSize = 3
110109
numberFormatter.formatterBehavior = .behavior10_4
111110
numberFormatter.numberStyle = .decimal
111+
numberFormatter.generatesDecimalNumbers = true
112+
numberFormatter.minimumFractionDigits = decimalPosition
113+
numberFormatter.maximumFractionDigits = decimalPosition
112114

113115
let stringResult = numberFormatter.string(from: decimal)
114116

115117
return stringResult
116118
}
119+
120+
/// Returns a string that displays the amount using all of the specified currency settings
121+
/// - Parameters:
122+
/// - localizedAmount: a formatted string returned from `localizeAmount()`
123+
/// - currencyPosition: the currency position, either right, left, right_space, or left_space.
124+
/// - currencyCode: the three-letter country code used for a currency, e.g. CAD.
125+
func formatCurrency(using amount: String,
126+
at position: Currency.Position,
127+
with code: Currency.Code) -> String? {
128+
let currency = Currency(amount: amount, code: code, position: position)
129+
let symbol = currency.symbol
130+
131+
switch position {
132+
case .left:
133+
return symbol + amount
134+
case .right:
135+
return amount + symbol
136+
case .leftSpace:
137+
return symbol + "\u{00a0}" + amount
138+
case .rightSpace:
139+
return amount + "\u{00a0}" + symbol
140+
}
141+
}
142+
143+
144+
// MARK: - Helper methods
145+
146+
func stringFormatIsValid(_ stringValue: String, for decimalPlaces: Int = 2) -> Bool {
147+
guard stringValue.characterCount >= 4 else {
148+
DDLogError("Error: this method expects a string with a minimum of 4 characters.")
149+
return false
150+
}
151+
152+
let decimalIndex = stringValue.characterCount - decimalPlaces
153+
var containsDecimal = false
154+
155+
for (index, char) in stringValue.enumerated() {
156+
if index == decimalIndex && char == "." {
157+
containsDecimal = true
158+
break
159+
}
160+
}
161+
162+
guard containsDecimal else {
163+
DDLogError("Error: this method expects a decimal notation from the string parameter.")
164+
return false
165+
}
166+
167+
return true
168+
}
117169
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@
254254
CE583A082107849F00D73C1C /* SwitchTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE583A062107849F00D73C1C /* SwitchTableViewCell.xib */; };
255255
CE583A0B2107937F00D73C1C /* TextViewTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE583A092107937F00D73C1C /* TextViewTableViewCell.swift */; };
256256
CE583A0C2107937F00D73C1C /* TextViewTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE583A0A2107937F00D73C1C /* TextViewTableViewCell.xib */; };
257-
CE5CD1A521CB052200F260EC /* MoneyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5CD1A421CB052200F260EC /* MoneyTests.swift */; };
257+
CE5CD1A521CB052200F260EC /* CurrencyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5CD1A421CB052200F260EC /* CurrencyTests.swift */; };
258258
CE85535D209B5BB700938BDC /* OrderDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE85535C209B5BB700938BDC /* OrderDetailsViewModel.swift */; };
259259
CE855364209BA6A700938BDC /* ShowHideSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE855360209BA6A700938BDC /* ShowHideSectionFooter.swift */; };
260260
CE855365209BA6A700938BDC /* CustomerInfoTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE855361209BA6A700938BDC /* CustomerInfoTableViewCell.xib */; };
@@ -263,7 +263,7 @@
263263
CE85FD5320F677770080B73E /* Dashboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE85FD5220F677770080B73E /* Dashboard.storyboard */; };
264264
CE85FD5A20F7A7640080B73E /* TableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE85FD5920F7A7640080B73E /* TableFooterView.swift */; };
265265
CE85FD5C20F7A7740080B73E /* TableFooterView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE85FD5B20F7A7740080B73E /* TableFooterView.xib */; };
266-
CE9B7E3221C949D2000F971C /* Money.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9B7E3121C949D2000F971C /* Money.swift */; };
266+
CE9B7E3221C949D2000F971C /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9B7E3121C949D2000F971C /* Currency.swift */; };
267267
CEA16F3A20FD0C8C0061B4E1 /* WooAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA16F3920FD0C8C0061B4E1 /* WooAnalytics.swift */; };
268268
CEE005F62076C4040079161F /* Orders.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CEE005F52076C4040079161F /* Orders.storyboard */; };
269269
CEE006052077D1280079161F /* SummaryTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE006032077D1280079161F /* SummaryTableViewCell.swift */; };
@@ -567,7 +567,7 @@
567567
CE583A062107849F00D73C1C /* SwitchTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SwitchTableViewCell.xib; sourceTree = "<group>"; };
568568
CE583A092107937F00D73C1C /* TextViewTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewTableViewCell.swift; sourceTree = "<group>"; };
569569
CE583A0A2107937F00D73C1C /* TextViewTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextViewTableViewCell.xib; sourceTree = "<group>"; };
570-
CE5CD1A421CB052200F260EC /* MoneyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoneyTests.swift; sourceTree = "<group>"; };
570+
CE5CD1A421CB052200F260EC /* CurrencyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyTests.swift; sourceTree = "<group>"; };
571571
CE85535C209B5BB700938BDC /* OrderDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderDetailsViewModel.swift; sourceTree = "<group>"; };
572572
CE855360209BA6A700938BDC /* ShowHideSectionFooter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShowHideSectionFooter.swift; sourceTree = "<group>"; };
573573
CE855361209BA6A700938BDC /* CustomerInfoTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CustomerInfoTableViewCell.xib; sourceTree = "<group>"; };
@@ -576,7 +576,7 @@
576576
CE85FD5220F677770080B73E /* Dashboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Dashboard.storyboard; sourceTree = "<group>"; };
577577
CE85FD5920F7A7640080B73E /* TableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableFooterView.swift; sourceTree = "<group>"; };
578578
CE85FD5B20F7A7740080B73E /* TableFooterView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TableFooterView.xib; sourceTree = "<group>"; };
579-
CE9B7E3121C949D2000F971C /* Money.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Money.swift; sourceTree = "<group>"; };
579+
CE9B7E3121C949D2000F971C /* Currency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = "<group>"; };
580580
CEA16F3920FD0C8C0061B4E1 /* WooAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooAnalytics.swift; sourceTree = "<group>"; };
581581
CECA64B020D9990E005A44C4 /* WooCommerce-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WooCommerce-Bridging-Header.h"; sourceTree = "<group>"; };
582582
CEE005F52076C4040079161F /* Orders.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Orders.storyboard; sourceTree = "<group>"; };
@@ -713,7 +713,7 @@
713713
B517EA19218B2D2600730EC4 /* StringFormatterTests.swift */,
714714
B56BBD15214820A70053A32D /* SyncCoordinatorTests.swift */,
715715
CE50345621B1F26C007573C6 /* ZendeskManagerTests.swift */,
716-
CE5CD1A421CB052200F260EC /* MoneyTests.swift */,
716+
CE5CD1A421CB052200F260EC /* CurrencyTests.swift */,
717717
);
718718
path = Tools;
719719
sourceTree = "<group>";
@@ -1223,7 +1223,7 @@
12231223
isa = PBXGroup;
12241224
children = (
12251225
CEFE5873214AE0E0007B9808 /* MoneyFormatter.swift */,
1226-
CE9B7E3121C949D2000F971C /* Money.swift */,
1226+
CE9B7E3121C949D2000F971C /* Currency.swift */,
12271227
);
12281228
path = Currency;
12291229
sourceTree = "<group>";
@@ -1720,7 +1720,7 @@
17201720
B58B4AC02108FF6100076FDD /* Array+Helpers.swift in Sources */,
17211721
B5A56BF0219F2CE90065A902 /* VerticalButton.swift in Sources */,
17221722
748C7780211E18A600814F2C /* OrderStats+Woo.swift in Sources */,
1723-
CE9B7E3221C949D2000F971C /* Money.swift in Sources */,
1723+
CE9B7E3221C949D2000F971C /* Currency.swift in Sources */,
17241724
B59C09D92188CBB100AB41D6 /* Array+Notes.swift in Sources */,
17251725
CE4DDB7B20DD312400D32EC8 /* DateFormatter+Helpers.swift in Sources */,
17261726
B50911322049E27A007D25DC /* SettingsViewController.swift in Sources */,
@@ -1842,7 +1842,7 @@
18421842
B555531321B57E8800449E71 /* MockupUserNotificationsCenterAdapter.swift in Sources */,
18431843
B555531121B57E6F00449E71 /* MockupApplicationAdapter.swift in Sources */,
18441844
B57C745120F56EE900EEFC87 /* UITableViewCellHelpersTests.swift in Sources */,
1845-
CE5CD1A521CB052200F260EC /* MoneyTests.swift in Sources */,
1845+
CE5CD1A521CB052200F260EC /* CurrencyTests.swift in Sources */,
18461846
B53A569D21123EEB000776C9 /* MockupStorage.swift in Sources */,
18471847
B57C5C9E21B80E8300FF82B2 /* SessionManager+Internal.swift in Sources */,
18481848
B55BC1F321A8790F0011A0C0 /* StringHTMLTests.swift in Sources */,

WooCommerce/WooCommerceTests/Tools/MoneyTests.swift renamed to WooCommerce/WooCommerceTests/Tools/CurrencyTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import XCTest
44

55
/// Money Tests
66
///
7-
class MoneyTests: XCTestCase {
7+
class CurrencyTests: XCTestCase {
88

99
/// Test currency symbol lookup returns correctly encoded symbol.
1010
///
1111
func testCurrencySymbol() {
12-
let money = Money(amount: 0.00, currency: .AED)
13-
let symbol = money.symbol
12+
let currency = Currency(amount: "0.00", code: .AED, position: .left)
13+
let symbol = currency.symbol
1414
XCTAssertEqual("د.إ", symbol)
1515
}
1616
}

0 commit comments

Comments
 (0)