@@ -22,33 +22,38 @@ final class StoreStatsPeriodViewModel {
2222 private( set) lazy var orderStatsText : AnyPublisher < String , Never > =
2323 Publishers . CombineLatest ( $orderStatsData. eraseToAnyPublisher ( ) , $selectedIntervalIndex. eraseToAnyPublisher ( ) )
2424 . compactMap { [ weak self] orderStatsData, selectedIntervalIndex in
25- return self ? . createOrderStatsText ( orderStatsData : orderStatsData, selectedIntervalIndex: selectedIntervalIndex)
25+ StatsDataTextFormatter . createOrderCountText ( orderStats : orderStatsData. stats , selectedIntervalIndex: selectedIntervalIndex)
2626 }
2727 . removeDuplicates ( )
2828 . eraseToAnyPublisher ( )
2929
3030 /// Emits revenue stats text values based on order stats, selected time interval, and currency code.
3131 private( set) lazy var revenueStatsText : AnyPublisher < String , Never > = $orderStatsData. combineLatest ( $selectedIntervalIndex, currencySettings. $currencyCode)
3232 . compactMap { [ weak self] orderStatsData, selectedIntervalIndex, currencyCode in
33- self ? . createRevenueStats ( orderStatsData: orderStatsData, selectedIntervalIndex: selectedIntervalIndex, currencyCode: currencyCode. rawValue)
33+ StatsDataTextFormatter . createTotalRevenueText ( orderStats: orderStatsData. stats,
34+ selectedIntervalIndex: selectedIntervalIndex,
35+ currencyFormatter: self ? . currencyFormatter,
36+ currencyCode: currencyCode. rawValue)
3437 }
3538 . removeDuplicates ( )
3639 . eraseToAnyPublisher ( )
3740
3841 /// Emits visitor stats text values based on site visit stats and selected time interval.
3942 private( set) lazy var visitorStatsText : AnyPublisher < String , Never > =
4043 Publishers . CombineLatest ( $siteStats. eraseToAnyPublisher ( ) , $selectedIntervalIndex. eraseToAnyPublisher ( ) )
41- . compactMap { [ weak self ] siteStats, selectedIntervalIndex in
42- self ? . createVisitorStatsText ( siteStats: siteStats, selectedIntervalIndex: selectedIntervalIndex)
44+ . compactMap { siteStats, selectedIntervalIndex in
45+ StatsDataTextFormatter . createVisitorCountText ( siteStats: siteStats, selectedIntervalIndex: selectedIntervalIndex)
4346 }
4447 . removeDuplicates ( )
4548 . eraseToAnyPublisher ( )
4649
4750 /// Emits conversion stats text values based on order stats, site visit stats, and selected time interval.
4851 private( set) lazy var conversionStatsText : AnyPublisher < String , Never > =
4952 Publishers . CombineLatest3 ( $orderStatsData. eraseToAnyPublisher ( ) , $siteStats. eraseToAnyPublisher ( ) , $selectedIntervalIndex. eraseToAnyPublisher ( ) )
50- . compactMap { [ weak self] orderStatsData, siteStats, selectedIntervalIndex in
51- self ? . createConversionStats ( orderStatsData: orderStatsData, siteStats: siteStats, selectedIntervalIndex: selectedIntervalIndex)
53+ . compactMap { orderStatsData, siteStats, selectedIntervalIndex in
54+ StatsDataTextFormatter . createConversionRateText ( orderStats: orderStatsData. stats,
55+ siteStats: siteStats,
56+ selectedIntervalIndex: selectedIntervalIndex)
5257 }
5358 . removeDuplicates ( )
5459 . eraseToAnyPublisher ( )
@@ -176,51 +181,6 @@ private extension StoreStatsPeriodViewModel {
176181 timezone: siteTimezone)
177182 }
178183
179- func createOrderStatsText( orderStatsData: OrderStatsData , selectedIntervalIndex: Int ? ) -> String {
180- if let count = orderCount ( at: selectedIntervalIndex, orderStats: orderStatsData. stats, orderStatsIntervals: orderStatsData. intervals) {
181- return Double ( count) . humanReadableString ( )
182- } else {
183- return Constants . placeholderText
184- }
185- }
186-
187- func createRevenueStats( orderStatsData: OrderStatsData , selectedIntervalIndex: Int ? , currencyCode: String ) -> String {
188- if let revenue = revenue ( at: selectedIntervalIndex, orderStats: orderStatsData. stats, orderStatsIntervals: orderStatsData. intervals) {
189- // If revenue is an integer, no decimal points are shown.
190- let numberOfDecimals : Int ? = revenue. isInteger ? 0 : nil
191- return currencyFormatter. formatAmount ( revenue, with: currencyCode, numberOfDecimals: numberOfDecimals) ?? String ( )
192- } else {
193- return Constants . placeholderText
194- }
195- }
196-
197- func createVisitorStatsText( siteStats: SiteVisitStats ? , selectedIntervalIndex: Int ? ) -> String {
198- if let visitorCount = visitorCount ( at: selectedIntervalIndex, siteStats: siteStats) {
199- return Double ( visitorCount) . humanReadableString ( )
200- } else {
201- return Constants . placeholderText
202- }
203- }
204-
205- func createConversionStats( orderStatsData: OrderStatsData , siteStats: SiteVisitStats ? , selectedIntervalIndex: Int ? ) -> String {
206- let visitors = visitorCount ( at: selectedIntervalIndex, siteStats: siteStats)
207- let orders = orderCount ( at: selectedIntervalIndex, orderStats: orderStatsData. stats, orderStatsIntervals: orderStatsData. intervals)
208-
209- let numberFormatter = NumberFormatter ( )
210- numberFormatter. numberStyle = . percent
211- numberFormatter. minimumFractionDigits = 1
212-
213- if let visitors = visitors, let orders = orders {
214- // Maximum conversion rate is 100%.
215- let conversionRate = visitors > 0 ? min ( orders/ visitors, 1 ) : 0
216- let minimumFractionDigits = floor ( conversionRate * 100.0 ) == conversionRate * 100.0 ? 0 : 1
217- numberFormatter. minimumFractionDigits = minimumFractionDigits
218- return numberFormatter. string ( from: conversionRate as NSNumber ) ?? Constants . placeholderText
219- } else {
220- return Constants . placeholderText
221- }
222- }
223-
224184 func visitorStatsViewState( siteVisitStatsMode: SiteVisitStatsMode , selectedIntervalIndex: Int ? ) -> StoreStatsDataOrRedactedView . State {
225185 switch siteVisitStatsMode {
226186 case . default:
@@ -272,51 +232,6 @@ private extension StoreStatsPeriodViewModel {
272232 }
273233}
274234
275- // MARK: - Private data helpers
276- //
277- private extension StoreStatsPeriodViewModel {
278- func visitorCount( at selectedIndex: Int ? , siteStats: SiteVisitStats ? ) -> Double ? {
279- let siteStatsItems = siteStats? . items? . sorted ( by: { ( lhs, rhs) -> Bool in
280- return lhs. period < rhs. period
281- } ) ?? [ ]
282- if let selectedIndex = selectedIndex, selectedIndex < siteStatsItems. count {
283- return Double ( siteStatsItems [ selectedIndex] . visitors)
284- } else if let siteStats = siteStats {
285- return Double ( siteStats. totalVisitors)
286- } else {
287- return nil
288- }
289- }
290-
291- func orderCount( at selectedIndex: Int ? , orderStats: OrderStatsV4 ? , orderStatsIntervals: [ OrderStatsV4Interval ] ) -> Double ? {
292- if let selectedIndex = selectedIndex, selectedIndex < orderStatsIntervals. count {
293- let orderStats = orderStatsIntervals [ selectedIndex]
294- return Double ( orderStats. subtotals. totalOrders)
295- } else if let orderStats = orderStats {
296- return Double ( orderStats. totals. totalOrders)
297- } else {
298- return nil
299- }
300- }
301-
302- func revenue( at selectedIndex: Int ? , orderStats: OrderStatsV4 ? , orderStatsIntervals: [ OrderStatsV4Interval ] ) -> Decimal ? {
303- if let selectedIndex = selectedIndex, selectedIndex < orderStatsIntervals. count {
304- let orderStats = orderStatsIntervals [ selectedIndex]
305- return orderStats. subtotals. grossRevenue
306- } else if let orderStats = orderStats {
307- return orderStats. totals. grossRevenue
308- } else {
309- return nil
310- }
311- }
312-
313- func orderStatsIntervals( from orderStats: OrderStatsV4 ? ) -> [ OrderStatsV4Interval ] {
314- return orderStats? . intervals. sorted ( by: { ( lhs, rhs) -> Bool in
315- return lhs. dateStart ( timeZone: siteTimezone) < rhs. dateStart ( timeZone: siteTimezone)
316- } ) ?? [ ]
317- }
318- }
319-
320235// MARK: - Results controller
321236//
322237private extension StoreStatsPeriodViewModel {
@@ -355,14 +270,13 @@ private extension StoreStatsPeriodViewModel {
355270
356271 func updateOrderDataIfNeeded( ) {
357272 let orderStats = orderStatsResultsController. fetchedObjects. first
358- let intervals = orderStatsIntervals ( from: orderStats)
273+ let intervals = StatsDataTextFormatter . sortOrderStatsIntervals ( from: orderStats)
359274 orderStatsData = ( stats: orderStats, intervals: intervals)
360275 }
361276}
362277
363278private extension StoreStatsPeriodViewModel {
364279 enum Constants {
365- static let placeholderText = " - "
366280 static let yAxisMaximumValueWithoutRevenue : Double = 1
367281 static let yAxisMinimumValueWithoutRevenue : Double = - 1
368282 }
0 commit comments