Skip to content

Commit 7d8c034

Browse files
committed
Added support for product bundles
1 parent 9805ee5 commit 7d8c034

File tree

10 files changed

+246
-24
lines changed

10 files changed

+246
-24
lines changed

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

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ public static SaleRestriction fromDatabaseField(long dbType, long value){
9090
private int price;
9191
private int discountedPrice;
9292
private String imageUrl;
93-
private String depositProductSku;
9493
private Product depositProduct;
94+
private Product[] bundleProducts;
9595
private Type type;
9696
private boolean isDeposit;
9797
private int boost;
@@ -157,23 +157,17 @@ public String getImageUrl() {
157157
return imageUrl;
158158
}
159159

160-
/**
161-
* Deprecated: use getDepositProduct instead.
162-
*
163-
* @return The sku of the deposit product.
164-
*/
165-
@Deprecated
166-
public String getDepositProductSku() {
167-
return depositProductSku;
168-
}
169-
170160
/**
171161
* Returns the deposit product, or null if the product has no deposit product
172162
*/
173163
public Product getDepositProduct() {
174164
return depositProduct;
175165
}
176166

167+
public Product[] getBundleProducts() {
168+
return bundleProducts;
169+
}
170+
177171
/**
178172
* Indicates if this product is a deposit product.
179173
*
@@ -293,13 +287,13 @@ public Builder setImageUrl(String imageUrl) {
293287
return this;
294288
}
295289

296-
public Builder setDepositProductSku(String sku) {
297-
product.depositProductSku = sku;
290+
public Builder setDepositProduct(Product depositProduct) {
291+
product.depositProduct = depositProduct;
298292
return this;
299293
}
300294

301-
public Builder setDepositProduct(Product depositProduct) {
302-
product.depositProduct = depositProduct;
295+
public Builder setBundleProducts(Product[] bundleProducts) {
296+
product.bundleProducts = bundleProducts;
303297
return this;
304298
}
305299

@@ -347,6 +341,10 @@ public Product build() {
347341
product.weighedItemIds = new String[0];
348342
}
349343

344+
if (product.bundleProducts == null) {
345+
product.bundleProducts = new Product[0];
346+
}
347+
350348
return product;
351349
}
352350
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ private Product toProduct(ApiProduct apiProduct, Product depositProduct) {
235235
.setDescription(apiProduct.description)
236236
.setSubtitle(apiProduct.subtitle)
237237
.setBoost(apiProduct.boost)
238-
.setDepositProductSku(apiProduct.depositProduct)
239238
.setDepositProduct(depositProduct)
240239
.setIsDeposit("deposit".equals(apiProduct.productType))
241240
.setImageUrl(apiProduct.imageUrl)

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

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -758,9 +758,8 @@ public Product productAtCursor(Cursor cursor) {
758758

759759
String depositSku = anyToString(cursor, 4);
760760

761-
builder.setDepositProductSku(anyToString(cursor, 4))
762-
.setIsDeposit(cursor.getInt(5) != 0)
763-
.setType(productTypes[cursor.getInt(6)]);
761+
builder.setIsDeposit(cursor.getInt(5) != 0)
762+
.setType(productTypes[cursor.getInt(6)]);
764763

765764
builder.setDepositProduct(findBySku(depositSku));
766765

@@ -786,6 +785,10 @@ public Product productAtCursor(Cursor cursor) {
786785
builder.setSaleStop(cursor.getInt(15) != 0);
787786
}
788787

788+
if(schemaVersionMajor >= 1 && schemaVersionMinor >= 9) {
789+
builder.setBundleProducts(findBundlesOfProduct(builder.build()));
790+
}
791+
789792
return builder.build();
790793
}
791794

@@ -1153,6 +1156,30 @@ public void findByWeighItemIdOnline(String weighItemId,
11531156
}
11541157
}
11551158

1159+
private Product[] findBundlesOfProduct(Product product) {
1160+
if (product != null && schemaVersionMajor >= 1 && schemaVersionMinor >= 9) {
1161+
Cursor cursor = productQuery("WHERE p.bundledSku = ?", new String[]{
1162+
product.getSku()
1163+
}, false);
1164+
1165+
if (cursor != null) {
1166+
Product[] products = new Product[cursor.getCount()];
1167+
1168+
int i = 0;
1169+
while (cursor.moveToNext()) {
1170+
products[i] = productAtCursor(cursor);
1171+
i++;
1172+
}
1173+
1174+
cursor.close();
1175+
1176+
return products;
1177+
}
1178+
}
1179+
1180+
return new Product[0];
1181+
}
1182+
11561183
/**
11571184
* This function is deprecated and will be removed from the SDK in the future. There will be no
11581185
* alternative function to search for products.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package io.snabble.sdk.ui.scanner;
2+
3+
import android.app.AlertDialog;
4+
import android.content.Context;
5+
import android.content.DialogInterface;
6+
import android.view.Gravity;
7+
import android.view.View;
8+
import android.view.ViewGroup;
9+
import android.view.Window;
10+
import android.widget.TextView;
11+
12+
import io.snabble.sdk.Product;
13+
import io.snabble.sdk.ui.R;
14+
import io.snabble.sdk.ui.utils.OneShotClickListener;
15+
import io.snabble.sdk.utils.Logger;
16+
17+
class SelectBundleDialog {
18+
public static void show(Context context, Product product, final Callback callback) {
19+
if(callback == null) {
20+
Logger.e("No callback provided");
21+
return;
22+
}
23+
24+
View view = View.inflate(context, R.layout.dialog_bundle_select, null);
25+
26+
final AlertDialog alertDialog = new AlertDialog.Builder(context)
27+
.setView(view)
28+
.setCancelable(true)
29+
.create();
30+
31+
alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
32+
@Override
33+
public void onDismiss(DialogInterface dialogInterface) {
34+
callback.onDismissed();
35+
}
36+
});
37+
38+
View close = view.findViewById(R.id.close);
39+
close.setOnClickListener(new OneShotClickListener() {
40+
@Override
41+
public void click() {
42+
alertDialog.dismiss();
43+
}
44+
});
45+
46+
ViewGroup container = view.findViewById(R.id.container);
47+
48+
Product[] bundles = product.getBundleProducts();
49+
final Product[] products = new Product[bundles.length + 1];
50+
products[0] = product;
51+
int i=1;
52+
for(Product p : bundles) {
53+
products[i] = p;
54+
i++;
55+
}
56+
57+
for(final Product p : products) {
58+
View itemView = View.inflate(context, R.layout.item_bundle_select, null);
59+
TextView name = itemView.findViewById(R.id.name);
60+
name.setText(p.getName());
61+
itemView.setOnClickListener(new OneShotClickListener() {
62+
@Override
63+
public void click() {
64+
alertDialog.dismiss();
65+
callback.onProductSelected(p);
66+
}
67+
});
68+
69+
itemView.setLayoutParams(new ViewGroup.LayoutParams(
70+
ViewGroup.LayoutParams.MATCH_PARENT,
71+
ViewGroup.LayoutParams.WRAP_CONTENT));
72+
73+
container.addView(itemView);
74+
}
75+
76+
Window window = alertDialog.getWindow();
77+
if (window == null) {
78+
return;
79+
}
80+
81+
window.setGravity(Gravity.BOTTOM);
82+
alertDialog.show();
83+
}
84+
85+
public interface Callback {
86+
void onProductSelected(Product product);
87+
void onDismissed();
88+
}
89+
}

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

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,17 @@ private void handleProductAvailable(Product product, boolean wasOnlineProduct, S
227227
}
228228

229229
progressDialog.dismiss();
230-
showProduct(product, scannedCode);
231230

232-
if (wasOnlineProduct) {
233-
Telemetry.event(Telemetry.Event.ScannedOnlineProduct, product);
231+
if(product.getBundleProducts().length > 0){
232+
showBundleDialog(product);
234233
} else {
235-
Telemetry.event(Telemetry.Event.ScannedProduct, product);
234+
showProduct(product, scannedCode);
235+
236+
if (wasOnlineProduct) {
237+
Telemetry.event(Telemetry.Event.ScannedOnlineProduct, product);
238+
} else {
239+
Telemetry.event(Telemetry.Event.ScannedProduct, product);
240+
}
236241
}
237242
}
238243

@@ -311,6 +316,28 @@ private void resumeBarcodeScanner() {
311316
}
312317
}
313318

319+
private void showBundleDialog(Product product) {
320+
pauseBarcodeScanner();
321+
allowScan = false;
322+
323+
SelectBundleDialog.show(getContext(), product, new SelectBundleDialog.Callback() {
324+
@Override
325+
public void onProductSelected(Product product) {
326+
Telemetry.event(Telemetry.Event.SelectedBundleProduct, product);
327+
328+
String[] codes = product.getScannableCodes();
329+
if(codes.length > 0) {
330+
showProduct(product, ScannableCode.parse(SnabbleUI.getSdkInstance(), codes[0]));
331+
}
332+
}
333+
334+
@Override
335+
public void onDismissed() {
336+
resumeBarcodeScanner();
337+
}
338+
});
339+
}
340+
314341
private void showProduct(Product product, ScannableCode scannedCode) {
315342
pauseBarcodeScanner();
316343
allowScan = false;

ui/src/main/java/io/snabble/sdk/ui/telemetry/Telemetry.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public enum Event {
1818
ToggleTorch,
1919
DeletedFromCart,
2020
UndoDeleteFromCart,
21+
SelectedBundleProduct,
2122
}
2223

2324
private static OnEventListener onEventListener;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="wrap_content"
7+
android:layout_gravity="center_horizontal"
8+
android:focusable="true"
9+
android:focusableInTouchMode="true"
10+
android:orientation="vertical"
11+
tools:ignore="SmallSp,HardcodedText">
12+
13+
<android.support.v4.widget.NestedScrollView
14+
android:layout_width="match_parent"
15+
android:layout_height="wrap_content"
16+
android:scrollbars="none"
17+
android:id="@+id/scroller">
18+
<LinearLayout
19+
android:layout_width="match_parent"
20+
android:layout_height="wrap_content"
21+
android:orientation="vertical">
22+
<ImageView
23+
android:layout_width="wrap_content"
24+
android:layout_height="wrap_content"
25+
android:layout_gravity="center_horizontal"
26+
android:id="@+id/close"
27+
android:padding="12dp"
28+
android:background="?android:attr/selectableItemBackground"
29+
android:src="@drawable/ic_close" />
30+
31+
<TextView
32+
android:layout_width="wrap_content"
33+
android:layout_height="wrap_content"
34+
android:layout_gravity="center_horizontal"
35+
android:gravity="center"
36+
android:textSize="15sp"
37+
android:layout_marginBottom="16dp"
38+
android:text="@string/Snabble.Scanner.BundleDialog.headline"/>
39+
40+
<LinearLayout
41+
android:layout_width="match_parent"
42+
android:layout_height="wrap_content"
43+
android:orientation="vertical"
44+
android:id="@+id/container" />
45+
</LinearLayout>
46+
</android.support.v4.widget.NestedScrollView>
47+
48+
<!-- invisible view as a margin, marginBottom does not work on API 16-18 -->
49+
<View
50+
android:layout_width="match_parent"
51+
android:layout_height="24dp"
52+
android:layout_below="@id/scroller"
53+
android:visibility="invisible" />
54+
</RelativeLayout>

ui/src/main/res/layout/dialog_product_confirmation.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
android:layout_height="wrap_content"
1717
android:layout_centerHorizontal="true"
1818
android:padding="12dp"
19-
android:textSize="14sp"
2019
android:background="?android:attr/selectableItemBackground"
2120
app:srcCompat="@drawable/ic_close" />
2221

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/card"
6+
android:layout_width="match_parent"
7+
android:layout_height="wrap_content"
8+
android:gravity="center"
9+
10+
android:orientation="vertical"
11+
android:background="?android:attr/selectableItemBackground">
12+
<View
13+
android:layout_width="match_parent"
14+
android:layout_height="1px"
15+
android:background="@color/snabble_dividerColor" />
16+
17+
<TextView
18+
android:layout_width="wrap_content"
19+
android:layout_height="wrap_content"
20+
android:id="@+id/name"
21+
android:gravity="center"
22+
android:padding="16dp"
23+
android:textSize="17sp"
24+
android:textStyle="bold"
25+
android:textColor="@color/snabble_textColorDark"
26+
tools:text="Coca Cola 1,0 l Mehrweg" />
27+
</LinearLayout>

ui/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<string name="Snabble.Scanner.unknownBarcode">Price information is not available for this product</string>
3939
<string name="Snabble.Scanner.updateCart">Update Cart</string>
4040
<string name="Snabble.Scanner.addToCart">Add to Cart</string>
41+
<string name="Snabble.Scanner.BundleDialog.headline">Please select an item</string>
4142
<string name="Snabble.Scanner.plusDeposit">+ %s deposit</string>
4243
<string name="Snabble.Scanner.introText">Scan barcodes on products and place them in your shopping cart.</string>
4344
<string name="Snabble.Scanner.start">Start scanner</string>

0 commit comments

Comments
 (0)