Skip to content

[Woo POS] Coupons: Disallow adding duplicate coupons to cart #15551

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

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion WooCommerce/Classes/POS/Models/Cart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ extension Cart {
case .variableParentProduct:
return
case .coupon(let coupon):
let couponItem = Cart.CouponItem(id: UUID(), code: coupon.code, summary: coupon.summary)
guard !coupons.contains(where: { $0.id == coupon.id }) else { return }

let couponItem = Cart.CouponItem(id: coupon.id, code: coupon.code, summary: coupon.summary)
coupons.insert(couponItem, at: coupons.startIndex)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,28 @@ final class StandardPOSItemActionHandler: POSItemActionHandler {
}
}

@available(iOS 17.0, *)
final class CouponsItemActionHandler: POSItemActionHandler {
private let posModel: PointOfSaleAggregateModelProtocol
private let analytics: Analytics
private let itemListType: ItemListType

init(posModel: PointOfSaleAggregateModelProtocol, itemListType: ItemListType, analytics: Analytics = ServiceLocator.analytics) {
self.posModel = posModel
self.itemListType = itemListType
self.analytics = analytics
}

func handleTap(_ item: POSItem) {
let alreadyExists = posModel.cart.coupons.contains(where: { $0.id == item.id })
if alreadyExists {
return
}
posModel.addToCart(item)
trackTapAnalytics(for: item, itemListType: itemListType, using: analytics)
}
}

/// Handler for handling taps on search result items, saving the search term
@available(iOS 17.0, *)
final class SearchResultItemActionHandler: POSItemActionHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,7 @@ struct PointOfSaleAggregateModelTests {
}

@available(iOS 17.0, *)
@Test(.disabled(
"""
This test doesn't currently work; analytics extensions are not thread-safe,
and using the MainActor means the assert happens too early. I don't think
we want the addToCart to be async, but that would be one way to fix it.
"""))
func addToCart_tracks_analytics_event() async throws {
// Given
@Test func addToCart_when_attempt_to_add_duplicated_coupon_then_does_not_add_it_to_cart() {
let sut = PointOfSaleAggregateModel(itemsController: MockPointOfSaleItemsController(),
purchasableItemsSearchController: MockPointOfSalePurchasableItemsSearchController(),
couponsController: MockPointOfSaleCouponsController(),
Expand All @@ -261,14 +254,14 @@ struct PointOfSaleAggregateModelTests {
collectOrderPaymentAnalyticsTracker: MockPOSCollectOrderPaymentAnalyticsTracker(),
searchHistoryService: MockPOSSearchHistoryService(),
popularItemsController: MockPointOfSalePopularItemsController())
let item = makePurchasableItem()
let coupon = makeCouponItem(code: "DISCOUNT!")

// When
sut.addToCart(item)
sut.addToCart(coupon)
sut.addToCart(coupon)

// Then
let event = try #require(analyticsProvider.receivedEvents.first)
#expect(event == "item_added_to_cart")
#expect(sut.cart.coupons.count == 1)
}
}

Expand Down