-
Notifications
You must be signed in to change notification settings - Fork 121
[POS Settings] Store section and PointOfSaleSettingsService
#16034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
iamgabrielma
merged 30 commits into
trunk
from
task/WOOMOB-1040-POSSettings-store-section
Aug 27, 2025
Merged
Changes from 12 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
059bcd9
make PointOfSaleSettingsService
iamgabrielma 433a5d8
update init
iamgabrielma 4713200
move version check to service
iamgabrielma af3b76e
make settingValueView
iamgabrielma 4201416
early return if version not supported
iamgabrielma 7b66d8f
cleanup
iamgabrielma 46035e4
update NSLocalizedStrings
iamgabrielma e49dad7
lint and POS fonts
iamgabrielma 4bb9542
move setting retrieval to the parent view
iamgabrielma 03834df
update imports and localization
iamgabrielma 8a02151
make setting view create its own service
iamgabrielma fe32ce4
Revert "make setting view create its own service"
iamgabrielma e19018b
split settings service into controller-service
iamgabrielma c3c2ca0
extract controller init to posmodel
iamgabrielma 8f91b68
make protocol. DI settings controller into POS aggregate
iamgabrielma a626d12
make test target compile
iamgabrielma b102193
DI storage into settings service
iamgabrielma f3de3be
DI default values for store name and address
iamgabrielma 9bedfa1
add PointOfSaleSettingsServiceTests
iamgabrielma 50c3efe
make PointOfSaleSettingsServiceProtocol and add tests
iamgabrielma e2e84b2
clean up unused storage
iamgabrielma 72bed3b
restore commented out preview
iamgabrielma ae533c5
Merge branch 'trunk' into task/WOOMOB-1040-POSSettings-store-section
iamgabrielma 3b82a84
remove unnecessary test
iamgabrielma 61728b2
adjust access control
iamgabrielma 0398758
update var name
iamgabrielma 2e5c028
merge tests
iamgabrielma d036798
make mock and wrap preview in debug flag
iamgabrielma b7b3bee
update preview
iamgabrielma cf78712
remove unnecessary imports
iamgabrielma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
WooCommerce/Classes/POS/Models/PointOfSaleSettingsService.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| import Foundation | ||
| import struct Yosemite.SiteSetting | ||
| import enum Yosemite.SettingAction | ||
| import enum Yosemite.Plugin | ||
| import class Yosemite.PluginsService | ||
| import Observation | ||
|
|
||
| @Observable final class PointOfSaleSettingsService { | ||
| private(set) var receiptStoreName: String? | ||
| private(set) var receiptStoreAddress: String? | ||
| private(set) var receiptStorePhone: String? | ||
| private(set) var receiptStoreEmail: String? | ||
| private(set) var receiptRefundReturnsPolicy: String? | ||
| private(set) var isLoading: Bool = false | ||
| private(set) var shouldShowReceiptInformation: Bool = false | ||
|
|
||
| private var siteID: Int64 { | ||
| ServiceLocator.stores.sessionManager.defaultSite?.siteID ?? 0 | ||
| } | ||
|
|
||
| var storeName: String { | ||
| guard let site = ServiceLocator.stores.sessionManager.defaultSite else { | ||
| return Localization.storeNotSet | ||
| } | ||
| return site.name | ||
| } | ||
iamgabrielma marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| var storeAddress: String { | ||
| SiteAddress().address | ||
iamgabrielma marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| @MainActor | ||
| func retrievePOSReceiptSettings() async { | ||
| isLoading = true | ||
|
|
||
| shouldShowReceiptInformation = await isPluginSupported(.wooCommerce, minimumVersion: "10.0") | ||
|
|
||
| guard shouldShowReceiptInformation else { | ||
| isLoading = false | ||
| return | ||
| } | ||
|
|
||
| await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in | ||
| let action = SettingAction.retrievePointOfSaleSettings(siteID: siteID) { [weak self] result in | ||
| guard let self else { return } | ||
| switch result { | ||
| case .success(let siteSettings): | ||
| updateReceiptSettings(from: siteSettings) | ||
| case .failure(let error): | ||
| DDLogError("Failed to load POS settings: \(error)") | ||
| } | ||
| isLoading = false | ||
| continuation.resume() | ||
| } | ||
| ServiceLocator.stores.dispatch(action) | ||
iamgabrielma marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| @MainActor | ||
| private func isPluginSupported(_ plugin: Plugin, minimumVersion: String) async -> Bool { | ||
| let storageManager = ServiceLocator.storageManager | ||
iamgabrielma marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| let pluginsService = PluginsService(storageManager: storageManager) | ||
| guard let systemPlugin = pluginsService.loadPluginInStorage(siteID: siteID, plugin: plugin, isActive: true), | ||
| systemPlugin.active else { | ||
| return false | ||
| } | ||
|
|
||
| let isSupported = VersionHelpers.isVersionSupported(version: systemPlugin.version, | ||
| minimumRequired: minimumVersion) | ||
| return isSupported | ||
| } | ||
|
|
||
| private func updateReceiptSettings(from siteSettings: [SiteSetting]) { | ||
| receiptStoreName = settingValue(from: siteSettings, settingID: "woocommerce_pos_store_name") | ||
| receiptStoreAddress = settingValue(from: siteSettings, settingID: "woocommerce_pos_store_address") | ||
| receiptStorePhone = settingValue(from: siteSettings, settingID: "woocommerce_pos_store_phone") | ||
| receiptStoreEmail = settingValue(from: siteSettings, settingID: "woocommerce_pos_store_email") | ||
| receiptRefundReturnsPolicy = settingValue(from: siteSettings, settingID: "woocommerce_pos_refund_returns_policy") | ||
| } | ||
|
|
||
| private func settingValue(from siteSettings: [SiteSetting], settingID: String) -> String? { | ||
| let value = siteSettings.first { $0.settingID == settingID }?.value | ||
| return value?.isEmpty == true ? nil : value | ||
| } | ||
| } | ||
|
|
||
| private extension PointOfSaleSettingsService { | ||
| enum Localization { | ||
| static let storeNotSet = NSLocalizedString( | ||
| "pointOfSaleSettingsService.storeNotSet", | ||
| value: "Not set", | ||
| comment: "Text displayed on Point of Sale settings when store has not been provided." | ||
| ) | ||
| } | ||
| } | ||
123 changes: 118 additions & 5 deletions
123
WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,129 @@ | ||
| import SwiftUI | ||
|
|
||
| struct PointOfSaleSettingsStoreDetailView: View { | ||
| let posSettingsService: PointOfSaleSettingsService | ||
|
|
||
| var body: some View { | ||
| NavigationStack { | ||
| VStack(alignment: .leading) { | ||
| Text("Store Settings") | ||
| .font(.title2) | ||
| Text("Store-related configuration") | ||
| .font(.caption) | ||
| .foregroundStyle(.secondary) | ||
| Group { | ||
| Text(Localization.storeInformation) | ||
| .font(.posBodyLargeRegular()) | ||
|
|
||
| Text(Localization.storeName) | ||
| Text(posSettingsService.storeName) | ||
| .font(.posBodyMediumRegular()) | ||
| .foregroundStyle(.secondary) | ||
|
|
||
| Text(Localization.address) | ||
| Text(posSettingsService.storeAddress) | ||
| .font(.posBodyMediumRegular()) | ||
| .foregroundStyle(.secondary) | ||
| } | ||
|
|
||
| Group { | ||
| Spacer() | ||
| Text(Localization.receiptInformation) | ||
| .font(.posBodyLargeRegular()) | ||
| Text(Localization.receiptStoreName) | ||
| settingValueView(for: posSettingsService.receiptStoreName) | ||
|
|
||
| Text(Localization.physicalAddress) | ||
| settingValueView(for: posSettingsService.receiptStoreAddress) | ||
|
|
||
| Text(Localization.phoneNumber) | ||
| settingValueView(for: posSettingsService.receiptStorePhone) | ||
|
|
||
| Text(Localization.email) | ||
| settingValueView(for: posSettingsService.receiptStoreEmail) | ||
|
|
||
| Text(Localization.refundReturnsPolicy) | ||
| settingValueView(for: posSettingsService.receiptRefundReturnsPolicy) | ||
|
|
||
| } | ||
| .renderedIf(posSettingsService.shouldShowReceiptInformation) | ||
| } | ||
| .padding() | ||
| } | ||
| } | ||
|
|
||
| @ViewBuilder | ||
| private func settingValueView(for value: String?) -> some View { | ||
| if posSettingsService.isLoading { | ||
| ProgressView() | ||
| .font(.posBodyLargeRegular()) | ||
| } else { | ||
| Text(value ?? Localization.notSet) | ||
| .font(.posBodyMediumRegular()) | ||
| .foregroundStyle(.secondary) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private extension PointOfSaleSettingsStoreDetailView { | ||
| enum Localization { | ||
| static let notSet = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.notSet", | ||
| value: "Not set", | ||
| comment: "Text displayed on Point of Sale settings when any setting has not been provided." | ||
| ) | ||
|
|
||
| static let storeInformation = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.storeInformation", | ||
| value: "Store Information", | ||
| comment: "Section title for store information in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let storeName = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.storeName", | ||
| value: "Store name", | ||
| comment: "Label for store name field in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let address = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.address", | ||
| value: "Address", | ||
| comment: "Label for address field in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let receiptInformation = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.receiptInformation", | ||
| value: "Receipt Information", | ||
| comment: "Section title for receipt information in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let receiptStoreName = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.receiptStoreName", | ||
| value: "Store name", | ||
| comment: "Label for receipt store name field in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let physicalAddress = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.physicalAddress", | ||
| value: "Physical address", | ||
| comment: "Label for physical address field in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let phoneNumber = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.phoneNumber", | ||
| value: "Phone number", | ||
| comment: "Label for phone number field in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let email = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.email", | ||
| value: "Email", | ||
| comment: "Label for email field in Point of Sale settings." | ||
| ) | ||
|
|
||
| static let refundReturnsPolicy = NSLocalizedString( | ||
| "pointOfSaleSettingsStoreDetailView.refundReturnsPolicy", | ||
| value: "Refund & Returns Policy", | ||
| comment: "Label for refund and returns policy field in Point of Sale settings." | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| #Preview { | ||
| PointOfSaleSettingsStoreDetailView(posSettingsService: PointOfSaleSettingsService()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.