taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit 7f6d54cd27edeee4dfd8b637e176302692376324
parent c114ddab3cf316cef105af1567170990f3bca999
Author: Marc Stibane <marc@taler.net>
Date:   Mon,  5 Oct 2026 08:08:15 +0200

ProductSold

Diffstat:
MTalerWallet1/Backend/WalletBackendRequest.swift | 57++++++++++++++++++++++++++++++++++++++++++++-------------
MTalerWallet1/Model/Model+Payment.swift | 2+-
MTalerWallet1/Views/Sheets/Payment/PaymentScan.swift | 2+-
MTalerWallet1/Views/Transactions/PaymentTransactionView.swift | 5+++--
MTalerWallet1/Views/Transactions/ThreeAmountsSection.swift | 6++++--
MTalerWallet1/Views/Transactions/TransactionPayDetailV.swift | 11++++++++---
MTalerWallet1/Views/Transactions/TransactionRowView.swift | 3++-
7 files changed, 63 insertions(+), 23 deletions(-)

diff --git a/TalerWallet1/Backend/WalletBackendRequest.swift b/TalerWallet1/Backend/WalletBackendRequest.swift @@ -139,27 +139,58 @@ struct Tax: Codable { /// A product being purchased from a merchant. /// https://docs.taler.net/core/api-merchant.html#the-contract-terms -struct Product: Codable, Identifiable { - var product_id: String? - var description: String -// var description_i18n: ? - var quantity: Int? - var unit: String? - var price: Amount? - var image: String? // product image 128x128 encoded - var taxes: [Tax]? - var delivery_date: Timestamp? - - var id: String { product_id ?? "unknown" } +struct ProductSold: Codable, Identifiable { + let productId: String? + let productName: String? +// let productGroupId: Int? + let description: String + let descriptionI18n: I18nDict? + let quantity: Int? + let unitQuantity: String? // float with max 6 fractional digits + let unit: String? // name of merchantUnit + let price: Amount? // deprecated - use prices + let prices: [Amount]? + let pricesAreNet: Bool? + let image: String? // product image 128x128 encoded + let taxes: [Tax]? + let deliveryDate: Timestamp? + let productMoneyPot: Int? + + var id: String { productId ?? "unknown" } + + var locDescription: String { + self.descriptionI18n?.localized ?? self.description + } + + enum CodingKeys: String, CodingKey { + case productId = "product_id" + case productName = "product_name" +// case productGroupId = "product_group_id" + case description + case descriptionI18n = "description_i18n" + case quantity + case unitQuantity = "unit_quantity" +// case unitAllowFraction = "unit_allow_fraction" + case unit + case price +// case unitPrice = "unit_price" + case prices + case pricesAreNet = "prices_are_net" + case image + case taxes + case deliveryDate = "delivery_date" + case productMoneyPot = "product_money_pot" + } } + /// Brief information about an order. struct OrderShortInfo: Codable { var orderId: String var merchant: MerchantInfo var summary: String var summary_i18n: I18nDict? - var products: [Product]? +// var products: [Product]? // MerchantContractTerms has [ProductSold] var fulfillmentUrl: String? var fulfillmentMessage: String? var fulfillmentMessage_i18n: I18nDict? diff --git a/TalerWallet1/Model/Model+Payment.swift b/TalerWallet1/Model/Model+Payment.swift @@ -218,7 +218,7 @@ struct MerchantContractTerms: Codable { let fulfillmentURL: String? // Fulfillment URL to view the product or delivery status let fulfillmentMessage: String? // Plain text fulfillment message in the merchant's default language let fulfillmentMessageI18n: I18nDict?// " localized ", keyed by BCP-47 tag - let products: [Product]? // Products that are sold in this contract + let products: [ProductSold]? // Products that are sold in this contract let timestamp: Timestamp // Time when the contract was generated by the merchant let refundDeadline: Timestamp? // Deadline for refunds let payDeadline: Timestamp // Deadline to pay for the contract diff --git a/TalerWallet1/Views/Sheets/Payment/PaymentScan.swift b/TalerWallet1/Views/Sheets/Payment/PaymentScan.swift @@ -164,7 +164,7 @@ struct PaymentView2: View, Sendable { let baseURL: String? // let terms: MerchantContractTerms let summary: String? - let products: [Product]? + let products: [ProductSold]? let balanceDetails: PaymentInsufficientBalanceDetails? func computeFee(raw: Amount?, eff: Amount?) -> Amount? { diff --git a/TalerWallet1/Views/Transactions/PaymentTransactionView.swift b/TalerWallet1/Views/Transactions/PaymentTransactionView.swift @@ -126,6 +126,7 @@ struct PaymentTransactionView: View { let choicesTuple = controller.choicesTuple if let txId = choicesTuple.0, let choicesForPayment = choicesTuple.1 { + let terms = choicesForPayment.contractTerms if txId == common.transactionId { if let (choices, showHeader) = choicesForPayment.choiceTriple() { let hasAutomatic = choicesForPayment.automaticExecution ?? false @@ -165,7 +166,7 @@ struct PaymentTransactionView: View { firstScope: scope, baseURL: nil, summary: summary, - products: details.info?.products ?? [], + products: terms.products ?? [], balanceDetails: selectionDetail.balanceDetails) } else if let choice = choices.first { let selectionDetail: ChoiceSelectionDetail = choice.0 @@ -177,7 +178,7 @@ struct PaymentTransactionView: View { firstScope: scope, baseURL: nil, summary: summary, - products: details.info?.products ?? [], + products: terms.products ?? [], balanceDetails: selectionDetail.balanceDetails) } } else { // should never happen... diff --git a/TalerWallet1/Views/Transactions/ThreeAmountsSection.swift b/TalerWallet1/Views/Transactions/ThreeAmountsSection.swift @@ -107,7 +107,7 @@ struct ThreeAmountsSection: View { let baseURL: String? let txStateLcl: String? // localizedState let summary: String? - let products: [Product]? + let products: [ProductSold]? @EnvironmentObject private var controller: Controller @Environment(\.colorScheme) private var colorScheme @@ -123,7 +123,9 @@ struct ThreeAmountsSection: View { if let products { for product in products { if let imageBase64 = product.image { - let productImage = ProductImage(imageBase64, product.description, product.price) + // TODO: choose price for scope + let price = product.prices?.first ?? product.price + let productImage = ProductImage(imageBase64, product.description, price) temp.append(productImage) } } diff --git a/TalerWallet1/Views/Transactions/TransactionPayDetailV.swift b/TalerWallet1/Views/Transactions/TransactionPayDetailV.swift @@ -22,6 +22,7 @@ struct TransactionPayDetailV: View { var body: some View { let common = paymentTx.common let details = paymentTx.details + let terms = details.contractTerms let info = details.info Section { if let posConfirmation = details.posConfirmation { @@ -95,12 +96,16 @@ struct TransactionPayDetailV: View { } } } - if let products = info?.products { + if let products = terms?.products { ForEach(products) { product in - if let product_id = product.product_id { + if let productId = product.productId { Section { - Text(product_id) + Text(productId) .talerFont(.body) + if let productName = product.productName { + Text(productName) + .talerFont(.body) + } } } } diff --git a/TalerWallet1/Views/Transactions/TransactionRowView.swift b/TalerWallet1/Views/Transactions/TransactionRowView.swift @@ -449,7 +449,8 @@ extension TalerTransaction { // for PreViews let info = OrderShortInfo(orderId: "some order ID", merchant: merchant, summary: "some product summary", - products: []) +// products: [] + ) let pDetails = PaymentTransactionDetails(info: info, totalRefundRaw: Amount(currency: LONGCURRENCY, cent: 300), totalRefundEffective: Amount(currency: LONGCURRENCY, cent: 280),