import Foundation struct CreateOrderPayload: Encodable { let customer: CreateOrderCustomerPayload let items: [CreateOrderItemPayload] let total: Double let paymentMethod: String let deliveryType: String let address: CreateOrderAddressPayload? // Cartão salvo let savedCardId: String? // Novo cartão (checkout transparente) let clientCpfCnpj: String? let creditCard: CreditCardOrderPayload? let creditCardHolderInfo: SaveCardHolderInfoPayload? } struct CreateOrderCustomerPayload: Encodable { let name: String let phone: String let email: String let asaasId: String? } struct CreateOrderItemPayload: Codable { let productId: String let name: String let qty: Int let price: Double let addons: [CreateOrderAddonPayload] } struct CreateOrderAddonPayload: Codable { let addonId: String let name: String let qty: Int let price: Double } struct CreateOrderAddressPayload: Encodable { let street: String let number: String let neighborhood: String let city: String? let state: String? let zip: String? let complement: String? } struct CreateOrderResult: Decodable { let id: String? let shortId: String? let status: String? let paymentStatus: String? let paymentConfirmed: Bool? let paymentMethod: String? let paymentPayload: CreateOrderPaymentPayload? let payment: CreateOrderPaymentInfo? enum CodingKeys: String, CodingKey { case id case shortId case status case paymentStatus case paymentConfirmed case paymentMethod case paymentPayload case payment } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = ApiService.decodeFlexibleString(from: container, keys: [.id]) shortId = ApiService.decodeFlexibleString(from: container, keys: [.shortId]) status = ApiService.decodeFlexibleString(from: container, keys: [.status]) paymentStatus = ApiService.decodeFlexibleString(from: container, keys: [.paymentStatus]) paymentConfirmed = try? container.decode(Bool.self, forKey: .paymentConfirmed) paymentMethod = ApiService.decodeFlexibleString(from: container, keys: [.paymentMethod]) payment = try? container.decode(CreateOrderPaymentInfo.self, forKey: .payment) if let objectPayload = try? container.decode(CreateOrderPaymentPayload.self, forKey: .paymentPayload) { paymentPayload = objectPayload } else if let stringPayload = try? container.decode(String.self, forKey: .paymentPayload) { paymentPayload = CreateOrderPaymentPayload( copyPaste: stringPayload, qrCodeImage: nil, expirationDate: nil ) } else { paymentPayload = nil } } } struct CreateOrderPaymentInfo: Codable { let method: String? let status: String? let pix: CreateOrderPaymentPayload? } struct CreateOrderPaymentPayload: Codable { let copyPaste: String? let qrCodeImage: String? let expirationDate: String? enum CodingKeys: String, CodingKey { case copyPaste case payload case qrCodeImage case encodedImage case expirationDate } init(copyPaste: String?, qrCodeImage: String?, expirationDate: String?) { self.copyPaste = copyPaste self.qrCodeImage = qrCodeImage self.expirationDate = expirationDate } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) copyPaste = (try? container.decode(String.self, forKey: .copyPaste)) ?? (try? container.decode(String.self, forKey: .payload)) qrCodeImage = (try? container.decode(String.self, forKey: .qrCodeImage)) ?? (try? container.decode(String.self, forKey: .encodedImage)) expirationDate = try? container.decode(String.self, forKey: .expirationDate) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(copyPaste, forKey: .copyPaste) try container.encodeIfPresent(qrCodeImage, forKey: .qrCodeImage) try container.encodeIfPresent(expirationDate, forKey: .expirationDate) } } struct ValidateDeliveryAddressPayload: Encodable { let address: ValidateDeliveryAddressDataPayload } struct ValidateDeliveryAddressDataPayload: Encodable { let street: String? let number: String? let neighborhood: String? let city: String? let state: String? let zip: String? let lat: Double? let lng: Double? } struct ValidateDeliveryAddressResult: Decodable { let deliveryAllowed: Bool? let reasonCode: String? let reasonMessage: String? let deliveryMode: String? let distance: Double? let deliveryFee: Double? let deliveryTime: String? let sameCity: Bool? enum CodingKeys: String, CodingKey { case deliveryAllowed case delivery_allowed case reasonCode case reason_code case reasonMessage case reason_message case deliveryMode case delivery_mode case distance case deliveryFee case delivery_fee case fee case taxa case deliveryTime case delivery_time case sameCity case same_city } init(from decoder: Decoder) throws { let c = try decoder.container(keyedBy: CodingKeys.self) deliveryAllowed = (try? c.decode(Bool.self, forKey: .deliveryAllowed)) ?? (try? c.decode(Bool.self, forKey: .delivery_allowed)) reasonCode = ApiService.decodeFlexibleString(from: c, keys: [.reasonCode, .reason_code]) reasonMessage = ApiService.decodeFlexibleString(from: c, keys: [.reasonMessage, .reason_message]) deliveryMode = ApiService.decodeFlexibleString(from: c, keys: [.deliveryMode, .delivery_mode]) distance = ApiService.decodeFlexibleDouble(from: c, keys: [.distance]) deliveryFee = ApiService.decodeFlexibleDouble(from: c, keys: [.deliveryFee, .delivery_fee, .fee, .taxa]) deliveryTime = ApiService.decodeFlexibleString(from: c, keys: [.deliveryTime, .delivery_time]) sameCity = (try? c.decode(Bool.self, forKey: .sameCity)) ?? (try? c.decode(Bool.self, forKey: .same_city)) } }