Coupon.swift
20.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
//
// Coupon.swift
// SwiftWarplyFramework
//
// Created by Warply on 06/06/2025.
// Copyright © 2025 Warply. All rights reserved.
//
import Foundation
// MARK: - Coupon Models
public class ShopAvailabilityItemModel: Codable {
private var merchant_uuid: String?
private var product_url: String?
init() {
self.merchant_uuid = ""
self.product_url = ""
}
public init(dictionary: [String: Any]) {
self.merchant_uuid = dictionary["merchant_uuid"] as? String? ?? ""
self.product_url = dictionary["product_url"] as? String? ?? ""
}
public var _merchant_uuid: String {
get { return self.merchant_uuid ?? "" }
set(newValue) { self.merchant_uuid = newValue }
}
public var _product_url: String {
get { return self.product_url ?? "" }
set(newValue) { self.product_url = newValue }
}
}
public class CouponSetItemModel {
// Existing fields
private var uuid: String?
private var admin_name: String?
private var name: String?
private var img: [String]?
private var img_preview: String?
private var expiration: String? // Now stores raw date string like "2026-06-30 11:59"
private var description: String?
private var short_description: String?
private var discount: String?
private var sorting: Int?
private var inner_text: String?
private var buyable: Bool?
private var visible: Bool?
private var terms: String?
private var merchant_uuid: String?
private var discount_type: String? // "value" / "percentage" / "plus_one"
private var final_price: Float?
// Universal Coupons
private var couponset_type: String?
// PopupMerchantsViewController List
private var shop_availability: Array<ShopAvailabilityItemModel>?
// New fields from API response
private var eligibilities: [String: Any]?
private var created: String?
private var updated: String?
private var app_uuid: String?
private var active: Bool?
private var is_new: Bool?
private var start_date: String?
private var end_date: String?
private var user_generated: Bool?
private var limits: [String: Any]?
private var points: Int?
private var promoted: Bool?
private var points_cause: String?
private var third_party_service: String?
private var category: String?
public init(dictionary: [String: Any]) {
// Existing fields
self.uuid = dictionary["uuid"] as? String? ?? ""
self.admin_name = dictionary["admin_name"] as? String? ?? ""
self.name = dictionary["name"] as? String? ?? ""
self.img_preview = dictionary["img_preview"] as? String? ?? ""
self.description = dictionary["description"] as? String? ?? ""
self.short_description = dictionary["short_description"] as? String? ?? ""
self.discount = dictionary["discount"] as? String? ?? ""
self.sorting = dictionary["sorting"] as? Int? ?? 0
let htmlText = dictionary["inner_text"] as? String? ?? ""
self.inner_text = htmlText?.htmlToString ?? ""
self.buyable = dictionary["buyable"] as? Bool? ?? false
self.visible = dictionary["visible"] as? Bool? ?? false
self.terms = dictionary["terms"] as? String? ?? ""
self.merchant_uuid = dictionary["merchant_uuid"] as? String? ?? ""
self.discount_type = dictionary["discount_type"] as? String? ?? ""
// Universal Coupons
self.couponset_type = dictionary["couponset_type"] as? String? ?? ""
if let double_final_price = dictionary["final_price"] as? Double {
self.final_price = Float(double_final_price)
}
else if let float_final_price = dictionary["final_price"] as? Float {
self.final_price = float_final_price
}
else if let string_final_price = dictionary["final_price"] as? String {
self.final_price = Float(string_final_price) ?? 0.0
}
else {
self.final_price = 0.0
}
// NEW FIELDS from API response
self.eligibilities = dictionary["eligibilities"] as? [String: Any]
self.created = dictionary["created"] as? String? ?? ""
self.updated = dictionary["updated"] as? String? ?? ""
self.app_uuid = dictionary["app_uuid"] as? String? ?? ""
self.active = dictionary["active"] as? Bool? ?? false
self.is_new = dictionary["is_new"] as? Bool? ?? false
self.start_date = dictionary["start_date"] as? String? ?? ""
self.end_date = dictionary["end_date"] as? String? ?? ""
self.user_generated = dictionary["user_generated"] as? Bool? ?? false
self.limits = dictionary["limits"] as? [String: Any]
self.points = dictionary["points"] as? Int? ?? 0
self.promoted = dictionary["promoted"] as? Bool? ?? false
self.points_cause = dictionary["points_cause"] as? String? ?? ""
self.third_party_service = dictionary["third_party_service"] as? String? ?? ""
self.category = dictionary["category"] as? String? ?? ""
// UPDATED EXPIRATION HANDLING - store raw date string
if let expirationObject = dictionary["expiration"] as? [String: Any],
let expirationValue = expirationObject["value"] as? String {
self.expiration = expirationValue // Store "2026-06-30 11:59"
} else {
self.expiration = ""
}
// img Example
// img = "[\"https://warply.s3.amazonaws.com/applications/f83dfde1145e4c2da69793abb2f579af/couponset/00833266674d4a95b21dc4bf06995548/logo.png\"]";
if let imgString = dictionary["img"] as? String {
// Convert the cleaned string to JSON data
if let imgData = imgString.data(using: .utf8) {
do {
// Parse JSON data as an array of dictionaries
if let imgArray = try JSONSerialization.jsonObject(with: imgData, options: []) as? [String] {
self.img = imgArray
} else {
self.img = []
}
} catch {
self.img = []
print("Error parsing img: \(error)")
}
} else {
self.img = []
}
} else {
self.img = []
}
// shop_availability Example
// {"shop_availability":"[{\"merchant_uuid\": \"9742752bcf904a269707c40b286e66de\", \"product_url\": \"https://www.ab.gr/el/eshop/Galaktokomika-Fytika-Rofimata-and-Eidi-Psygeioy/Gala-and-Fytika-Rofimata/Fytika-Rofimata/Fytiko-Rofima-Amygdalo-Choris-Prosthiki-Zacharis-1lt/p/7438640\"}]"}
if let extra_fields = dictionary["extra_fields"] as? [String: Any] {
if let shopAvailabilityString = extra_fields["shop_availability"] as? String {
// Convert the cleaned string to JSON data
if let shopData = shopAvailabilityString.data(using: .utf8) {
do {
// Parse JSON data as an array of dictionaries
if let shopArray = try JSONSerialization.jsonObject(with: shopData, options: []) as? [[String: Any]] {
var shopItems: Array<ShopAvailabilityItemModel> = []
// Iterate through the shopArray and populate ShopAvailabilityItemModel objects
for shopDict in shopArray {
let tempShop = ShopAvailabilityItemModel(dictionary: shopDict)
shopItems.append(tempShop)
}
self.shop_availability = shopItems
} else {
self.shop_availability = []
}
} catch {
self.shop_availability = []
print("Error parsing shop availability: \(error)")
}
} else {
self.shop_availability = []
}
} else {
self.shop_availability = []
}
} else {
self.shop_availability = []
}
}
// MARK: - Public Accessors (Following ProfileModel Pattern)
// Existing field accessors
public var _uuid: String { get { return self.uuid ?? "" } }
public var _admin_name: String { get { return self.admin_name ?? "" } }
public var _name: String { get { return self.name ?? "" } }
public var _img: [String]? { get { return self.img } }
public var _img_preview: String { get { return self.img_preview ?? "" } }
public var _expiration: String { get { return self.expiration ?? "" } }
public var _description: String { get { return self.description ?? "" } }
public var _short_description: String { get { return self.short_description ?? "" } }
public var _discount: String { get { return self.discount ?? "" } }
public var _sorting: Int { get { return self.sorting ?? 0 } }
public var _inner_text: String { get { return self.inner_text ?? "" } }
public var _buyable: Bool { get { return self.buyable ?? false } }
public var _visible: Bool { get { return self.visible ?? false } }
public var _terms: String { get { return self.terms ?? "" } }
public var _merchant_uuid: String { get { return self.merchant_uuid ?? "" } }
public var _discount_type: String { get { return self.discount_type ?? "" } }
public var _final_price: Float { get { return self.final_price ?? 0.0 } }
public var _couponset_type: String { get { return self.couponset_type ?? "" } }
public var _shop_availability: Array<ShopAvailabilityItemModel>? { get { return self.shop_availability } }
// New field accessors
public var _eligibilities: [String: Any]? { get { return self.eligibilities } }
public var _created: String { get { return self.created ?? "" } }
public var _updated: String { get { return self.updated ?? "" } }
public var _app_uuid: String { get { return self.app_uuid ?? "" } }
public var _active: Bool { get { return self.active ?? false } }
public var _is_new: Bool { get { return self.is_new ?? false } }
public var _start_date: String { get { return self.start_date ?? "" } }
public var _end_date: String { get { return self.end_date ?? "" } }
public var _user_generated: Bool { get { return self.user_generated ?? false } }
public var _limits: [String: Any]? { get { return self.limits } }
public var _points: Int { get { return self.points ?? 0 } }
public var _promoted: Bool { get { return self.promoted ?? false } }
public var _points_cause: String { get { return self.points_cause ?? "" } }
public var _third_party_service: String { get { return self.third_party_service ?? "" } }
public var _category: String { get { return self.category ?? "" } }
// Formatted expiration date for display
public var _expiration_formatted: String {
guard let expiration = self.expiration, !expiration.isEmpty else {
return ""
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
if let date = dateFormatter.date(from: expiration) {
dateFormatter.dateFormat = "dd/MM/yyyy"
return dateFormatter.string(from: date)
}
return ""
}
/// Format expiration date with custom format
/// - Parameter format: DateFormatter format string (e.g., "dd-MM", "dd/MM/yyyy")
/// - Returns: Formatted date string or empty string if invalid
public func formattedExpiration(format: String) -> String {
guard let expiration = self.expiration, !expiration.isEmpty else {
return ""
}
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yyyy-MM-dd HH:mm"
if let date = inputFormatter.date(from: expiration) {
let outputFormatter = DateFormatter()
outputFormatter.dateFormat = format
return outputFormatter.string(from: date)
}
return ""
}
}
public class RedeemedMerchantDetailsModel: Codable {
private var img_preview: String?
private var name: String?
private var uuid: String?
private var redeemed_date: Date?
private var redeemed_date_string: String?
public init() {
self.img_preview = ""
self.name = ""
self.uuid = ""
self.redeemed_date = Date()
self.redeemed_date_string = ""
}
public init(dictionary: [String: Any]) {
self.img_preview = dictionary["img_preview"] as? String? ?? ""
self.name = dictionary["name"] as? String? ?? ""
self.uuid = dictionary["uuid"] as? String? ?? ""
if let redeemedString = dictionary["redeemed_date"] as? String {
// Example "redeemed_date" = "2024-07-02T10:50:03.04416";
let dateFormatter4 = DateFormatter()
dateFormatter4.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSS"
if let date = dateFormatter4.date(from: redeemedString ?? "") {
self.redeemed_date = date
dateFormatter4.dateFormat = "dd/MM/yyyy"
let resultString = dateFormatter4.string(from: date)
self.redeemed_date_string = resultString
} else {
self.redeemed_date = Date()
self.redeemed_date_string = ""
}
} else {
self.redeemed_date = Date()
self.redeemed_date_string = ""
}
}
public var _img_preview: String {
get { return self.img_preview ?? "" }
set(newValue) { self.img_preview = newValue }
}
public var _name: String {
get { return self.name ?? "" }
set(newValue) { self.name = newValue }
}
public var _uuid: String {
get { return self.uuid ?? "" }
set(newValue) { self.uuid = newValue }
}
public var _redeemed_date: Date {
get { return self.redeemed_date ?? Date() }
set(newValue) { self.redeemed_date = newValue }
}
public var _redeemed_date_string: String {
get { return self.redeemed_date_string ?? "" }
set(newValue) { self.redeemed_date_string = newValue }
}
}
public class CouponItemModel {
public let couponset_uuid: String?
public let name: String?
public let image: String?
public let expiration: String?
public let created: String?
public let description: String?
public let discount: String?
public let coupon: String?
public let category: String?
public let barcode: String?
public var status: Int?
public let transaction_uuid: String?
public let redeemed: String?
public let redeemed_date: Date?
public var couponset_data: CouponSetItemModel?
// Market Coupon
public let inner_text: String?
public let merchant_uuid: String?
public let short_description: String?
public let terms: String?
// Universal Coupons
public var merchant_details: MerchantModel?
public var redeemed_merchant_details: RedeemedMerchantDetailsModel?
public init(dictionary: [String: Any]) {
self.couponset_uuid = dictionary["couponset_uuid"] as? String? ?? ""
self.name = dictionary["name"] as? String? ?? ""
self.image = dictionary["image"] as? String? ?? ""
self.description = dictionary["description"] as? String? ?? ""
self.coupon = dictionary["coupon"] as? String? ?? ""
self.category = dictionary["category"] as? String? ?? ""
self.barcode = dictionary["barcode"] as? String? ?? ""
self.status = dictionary["status"] as? Int? ?? nil
if let tranIdString = dictionary["transaction_uuid"] as? String? ?? "", tranIdString != "" {
self.transaction_uuid = tranIdString
} else if let tranIdInt = dictionary["transaction_uuid"] as? Int? ?? 0, tranIdInt != 0 {
self.transaction_uuid = String(tranIdInt)
} else {
self.transaction_uuid = ""
}
if let tempDiscount = dictionary["discount"] as? String? ?? "" {
if tempDiscount.contains(",") {
let formattedDiscount = tempDiscount.replacingOccurrences(of: ",", with: ".")
self.discount = formattedDiscount
} else {
self.discount = dictionary["discount"] as? String? ?? ""
}
} else {
self.discount = ""
}
// Market Coupon
self.inner_text = dictionary["inner_text"] as? String? ?? ""
self.merchant_uuid = dictionary["merchant_uuid"] as? String? ?? ""
self.short_description = dictionary["short_description"] as? String? ?? ""
self.terms = dictionary["terms"] as? String? ?? ""
if let couponSetData = dictionary["couponset_data"] as? [String: Any] {
let tempCouponset = CouponSetItemModel(dictionary: couponSetData)
self.couponset_data = tempCouponset
// Universal Coupons ==>
} else if let couponSetDetails = dictionary["couponset_details"] as? [String: Any] {
let tempCouponset = CouponSetItemModel(dictionary: couponSetDetails)
self.couponset_data = tempCouponset
} else {
self.couponset_data = nil
}
if let merchantDetails = dictionary["merchant_details"] as? [String: Any] {
let tempMerchantDetails = MerchantModel(dictionary: merchantDetails)
self.merchant_details = tempMerchantDetails
} else {
self.merchant_details = nil
}
if let redeemedMerchantDetails = dictionary["redeemed_merchant_details"] as? [String: Any] {
let tempRedeemedMerchantDetails = RedeemedMerchantDetailsModel(dictionary: redeemedMerchantDetails)
self.redeemed_merchant_details = tempRedeemedMerchantDetails
} else {
self.redeemed_merchant_details = nil
}
// <==
let expirationString = dictionary["expiration"] as? String? ?? ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
if let date = dateFormatter.date(from: expirationString ?? "") {
dateFormatter.dateFormat = "dd/MM/yyyy"
let resultString = dateFormatter.string(from: date)
self.expiration = resultString
} else {
self.expiration = ""
}
let createdString = dictionary["created"] as? String? ?? ""
let dateFormatter2 = DateFormatter()
dateFormatter2.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSSSS"
if let date = dateFormatter2.date(from: createdString ?? "") {
dateFormatter2.dateFormat = "dd/MM/yyyy"
let resultString = dateFormatter2.string(from: date)
self.created = resultString
} else {
self.created = ""
}
if let changes_dates = dictionary["changes_dates"] as? [String: Any] {
let redeemedString = changes_dates["redeemed"] as? String? ?? ""
// Example redeemedString: "2022-11-03 17:08:21.285355";
let dateFormatter3 = DateFormatter()
dateFormatter3.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSSSS"
if let date = dateFormatter3.date(from: redeemedString ?? "") {
self.redeemed_date = date
dateFormatter3.dateFormat = "dd/MM/yyyy"
let resultString = dateFormatter3.string(from: date)
self.redeemed = resultString
} else {
self.redeemed = ""
self.redeemed_date = Date()
}
} else {
self.redeemed = ""
self.redeemed_date = Date()
}
}
public func setCouponSetData(_ couponSet: CouponSetItemModel) {
self.couponset_data = couponSet
}
}
public class RedeemedSMHistoryModel {
private var totalRedeemedValue: Float
private var redeemedCouponList: Array<CouponItemModel>
init() {
self.totalRedeemedValue = 0.0
self.redeemedCouponList = []
}
public var _totalRedeemedValue: Float {
get { return self.totalRedeemedValue }
set(newValue) { self.totalRedeemedValue = newValue }
}
public var _redeemedCouponList: Array<CouponItemModel> {
get { return self.redeemedCouponList }
set(newValue) { self.redeemedCouponList = newValue }
}
}
// MARK: - String Extension for HTML
// extension String {
// var htmlToString: String {
// guard let data = self.data(using: .utf8) else { return self }
// do {
// return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil).string
// } catch {
// return self
// }
// }
// }