Skip to content

Commit cd375ec

Browse files
committed
Add coupon violations dialog
1 parent f979483 commit cd375ec

File tree

6 files changed

+117
-25
lines changed

6 files changed

+117
-25
lines changed

core/src/main/java/io/snabble/sdk/ShoppingCart.java

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public String getValue() {
6060
private long lastModificationTime;
6161
private List<Item> oldItems;
6262
private List<Item> items = new ArrayList<>();
63+
private final List<ViolationNotification> violationNotifications = new ArrayList<>();
6364
private int modCount = 0;
6465
private int addCount = 0;
6566
private Integer onlineTotalPrice;
@@ -599,7 +600,8 @@ public static class Item {
599600
private transient ShoppingCart cart;
600601
private boolean isManualCouponApplied;
601602
private Coupon coupon;
602-
private String couponId;
603+
// The local generated UUID of a coupon which which will be used by the backend
604+
private String backendCouponId;
603605

604606
protected Item() {
605607
// for gson
@@ -610,7 +612,7 @@ private Item(ShoppingCart cart, Coupon coupon, ScannedCode scannedCode) {
610612
this.cart = cart;
611613
this.scannedCode = scannedCode;
612614
this.coupon = coupon;
613-
this.couponId = UUID.randomUUID().toString();
615+
this.backendCouponId = UUID.randomUUID().toString();
614616
}
615617

616618
private Item(ShoppingCart cart, Product product, ScannedCode scannedCode) {
@@ -1174,7 +1176,7 @@ public BackendCart toBackendCart() {
11741176
}
11751177
} else if (cartItem.getType() == ItemType.COUPON) {
11761178
BackendCartItem item = new BackendCartItem();
1177-
item.id = cartItem.couponId;
1179+
item.id = cartItem.backendCouponId;
11781180
item.amount = 1;
11791181

11801182
ScannedCode scannedCode = cartItem.getScannedCode();
@@ -1192,6 +1194,47 @@ public BackendCart toBackendCart() {
11921194
return backendCart;
11931195
}
11941196

1197+
@RestrictTo(RestrictTo.Scope.LIBRARY)
1198+
void resolveViolations(List<Violation> violations) {
1199+
for (Violation violation : violations) {
1200+
for (int i = items.size() - 1; i >= 0; i--) {
1201+
if (items.get(i).coupon != null && items.get(i).backendCouponId.equals(violation.getRefersTo())) {
1202+
Item item = items.get(i);
1203+
items.remove(item);
1204+
boolean found = false;
1205+
for(ViolationNotification notification: violationNotifications) {
1206+
if(notification.getRefersTo().equals(violation.getRefersTo())) {
1207+
found = true;
1208+
break;
1209+
}
1210+
}
1211+
if(!found) {
1212+
violationNotifications.add(new ViolationNotification(
1213+
item.coupon.getName(),
1214+
violation.getRefersTo(),
1215+
violation.getType(),
1216+
violation.getMessage()
1217+
));
1218+
}
1219+
}
1220+
}
1221+
}
1222+
notifyViolations();
1223+
}
1224+
1225+
/**
1226+
* Remove the handled ViolationNotifications.
1227+
* @param violations the handled ViolationNotifications.
1228+
*/
1229+
public void removeViolationNotification(List<ViolationNotification> violations) {
1230+
violationNotifications.removeAll(violations);
1231+
}
1232+
1233+
@NonNull
1234+
public List<ViolationNotification> getViolationNotifications() {
1235+
return violationNotifications;
1236+
}
1237+
11951238
/**
11961239
* Adds a {@link ShoppingCartListener} to the list of listeners if it does not already exist.
11971240
*
@@ -1201,6 +1244,9 @@ public void addListener(ShoppingCartListener listener) {
12011244
if (!listeners.contains(listener)) {
12021245
listeners.add(listener);
12031246
}
1247+
if (!violationNotifications.isEmpty()) {
1248+
listener.onViolationDetected(violationNotifications);
1249+
}
12041250
}
12051251

12061252
/**
@@ -1234,7 +1280,7 @@ public interface ShoppingCartListener {
12341280

12351281
void onTaxationChanged(ShoppingCart list, Taxation taxation);
12361282

1237-
void onViolationDetected(@NonNull List<Violation> violations);
1283+
void onViolationDetected(@NonNull List<ViolationNotification> violations);
12381284
}
12391285

12401286
public static abstract class SimpleShoppingCartListener implements ShoppingCartListener {
@@ -1282,7 +1328,7 @@ public void onCheckoutLimitReached(ShoppingCart list) {}
12821328
public void onOnlinePaymentLimitReached(ShoppingCart list) {}
12831329

12841330
@Override
1285-
public void onViolationDetected(List<Violation> violations) {}
1331+
public void onViolationDetected(List<ViolationNotification> violations) {}
12861332
}
12871333

12881334
private void notifyItemAdded(final ShoppingCart list, final Item item) {
@@ -1361,31 +1407,14 @@ void notifyOnlinePaymentLimitReached(final ShoppingCart list) {
13611407
});
13621408
}
13631409

1364-
public void notifyViolations(@NonNull List<Violation> violations) {
1410+
public void notifyViolations() {
13651411
Dispatch.mainThread(() -> {
13661412
for (ShoppingCartListener listener : listeners) {
1367-
listener.onViolationDetected(violations);
1368-
}
1369-
for (Violation violation : violations) {
1370-
for (int i = items.size() - 1; i >= 0; i--) {
1371-
if (items.get(i).coupon != null && items.get(i).couponId.equals(violation.getRefersTo())) {
1372-
items.remove(items.get(i));
1373-
}
1374-
}
1413+
listener.onViolationDetected(violationNotifications);
13751414
}
13761415
});
13771416
}
13781417

1379-
@Nullable
1380-
public Coupon getCouponByCartId(String id) {
1381-
for (int i = items.size() - 1; i >= 0; i--) {
1382-
if (items.get(i).coupon != null && items.get(i).couponId.equals(id)) {
1383-
return items.get(i).coupon;
1384-
}
1385-
}
1386-
return null;
1387-
}
1388-
13891418
/**
13901419
* Notifies all {@link #listeners} that the shopping list was cleared of all entries.
13911420
*

core/src/main/java/io/snabble/sdk/ShoppingCartUpdater.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private void commitCartUpdate(int modCount, SignedCheckoutInfo signedCheckoutInf
143143
CheckoutInfo checkoutInfo = GsonHolder.get().fromJson(signedCheckoutInfo.getCheckoutInfo(), CheckoutInfo.class);
144144

145145
if (checkoutInfo.getViolations().size() > 0) {
146-
cart.notifyViolations(checkoutInfo.getViolations());
146+
cart.resolveViolations(checkoutInfo.getViolations());
147147
}
148148

149149
Set<String> referrerIds = new HashSet<>();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.snabble.sdk
2+
3+
/**
4+
* A notification that a violation accrued.
5+
*/
6+
data class ViolationNotification(
7+
val name: String?,
8+
val refersTo: String?,
9+
val type: String? = null,
10+
val fallbackMessage: String? = null,
11+
)

ui/src/main/java/io/snabble/sdk/ui/cart/ShoppingCartView.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
import io.snabble.sdk.ShoppingCart;
3636
import io.snabble.sdk.Snabble;
3737
import io.snabble.sdk.Unit;
38+
import io.snabble.sdk.ViolationNotification;
3839
import io.snabble.sdk.ui.GestureHandler;
3940
import io.snabble.sdk.ui.R;
4041
import io.snabble.sdk.ui.SnabbleUI;
42+
import io.snabble.sdk.ui.checkout.ViolationNotificationUtils;
4143
import io.snabble.sdk.ui.telemetry.Telemetry;
4244
import io.snabble.sdk.ui.utils.I18nUtils;
4345
import io.snabble.sdk.ui.utils.SnackbarUtils;
@@ -102,6 +104,11 @@ public void onOnlinePaymentLimitReached(ShoppingCart list) {
102104
.create();
103105
alertDialog.show();
104106
}
107+
108+
@Override
109+
public void onViolationDetected(@NonNull List<ViolationNotification> violations) {
110+
ViolationNotificationUtils.showNotificationOnce(violations, getContext(), cart);
111+
}
105112
};
106113

107114
public ShoppingCartView(Context context) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@file:JvmName("ViolationNotificationUtils")
2+
package io.snabble.sdk.ui.checkout
3+
4+
import android.content.Context
5+
import androidx.appcompat.app.AlertDialog
6+
import io.snabble.sdk.ShoppingCart
7+
import io.snabble.sdk.ViolationNotification
8+
import io.snabble.sdk.ui.R
9+
import io.snabble.sdk.ui.utils.I18nUtils
10+
11+
/**
12+
* Build a localized error message from a list of `ViolationNotification`.
13+
*/
14+
fun List<ViolationNotification>.getMessage(context: Context) = joinToString("\n") {
15+
val res = context.resources
16+
when (it.type) {
17+
"coupon_invalid" -> res.getString(I18nUtils.getIdentifier(res, R.string.Snabble_Violations_couponInvalid), it.name)
18+
"coupon_currently_not_valid" -> res.getString(I18nUtils.getIdentifier(res, R.string.Snabble_Violations_couponCurrentlyNotValid), it.name)
19+
"coupon_already_voided" -> res.getString(I18nUtils.getIdentifier(res, R.string.Snabble_Violations_couponAlreadyVoided), it.name)
20+
else -> it.fallbackMessage.orEmpty()
21+
}
22+
}
23+
24+
/**
25+
* Show a dialog with all current violations. The implementation will make sure that the dialog won't be shown twice.
26+
*/
27+
fun List<ViolationNotification>.showNotificationOnce(context: Context, cart: ShoppingCart) {
28+
val message: String = getMessage(context)
29+
cart.removeViolationNotification(this)
30+
if (cart.violationNotifications.isNotEmpty()){
31+
AlertDialog.Builder(context)
32+
.setTitle(R.string.Snabble_Violations_title)
33+
.setMessage(message)
34+
.setPositiveButton(R.string.Snabble_OK, null)
35+
.show()
36+
}
37+
}

ui/src/main/java/io/snabble/sdk/ui/scanner/SelfScanningView.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import android.widget.FrameLayout;
2323
import android.widget.LinearLayout;
2424

25+
import androidx.annotation.NonNull;
2526
import androidx.appcompat.app.AlertDialog;
2627
import androidx.core.app.ActivityCompat;
2728
import androidx.core.content.res.ResourcesCompat;
@@ -40,9 +41,11 @@
4041
import io.snabble.sdk.Shop;
4142
import io.snabble.sdk.ShoppingCart;
4243
import io.snabble.sdk.Snabble;
44+
import io.snabble.sdk.ViolationNotification;
4345
import io.snabble.sdk.codes.ScannedCode;
4446
import io.snabble.sdk.ui.R;
4547
import io.snabble.sdk.ui.SnabbleUI;
48+
import io.snabble.sdk.ui.checkout.ViolationNotificationUtils;
4649
import io.snabble.sdk.ui.telemetry.Telemetry;
4750
import io.snabble.sdk.ui.utils.DelayedProgressDialog;
4851
import io.snabble.sdk.ui.utils.I18nUtils;
@@ -549,6 +552,11 @@ public void onOnlinePaymentLimitReached(ShoppingCart list) {
549552
project.getPriceFormatter().format(project.getMaxOnlinePaymentLimit())));
550553

551554
}
555+
556+
@Override
557+
public void onViolationDetected(@NonNull List<ViolationNotification> violations) {
558+
ViolationNotificationUtils.showNotificationOnce(violations, getContext(), shoppingCart);
559+
}
552560
};
553561

554562
private final Application.ActivityLifecycleCallbacks activityLifecycleCallbacks =

0 commit comments

Comments
 (0)