Skip to content

Commit 4a886ae

Browse files
committed
add support for reference and encoding units
1 parent 4d66e93 commit 4a886ae

File tree

8 files changed

+149
-7
lines changed

8 files changed

+149
-7
lines changed
88 KB
Binary file not shown.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.snabble.sdk;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
6+
import java.io.IOException;
7+
import java.math.BigDecimal;
8+
import java.math.RoundingMode;
9+
10+
public class UnitTest extends SnabbleSdkTest {
11+
@Test
12+
public void testUnitPrices() throws IOException, Snabble.SnabbleException {
13+
withDb("testDb_1_16_encodingUnits.sqlite3");
14+
15+
ProductDatabase productDatabase = project.getProductDatabase();
16+
final Product test_ml_1 = productDatabase.findBySku("test-ml-1");
17+
final Product test_g_1 = productDatabase.findBySku("test-g-1");
18+
final Product test_cm_1 = productDatabase.findBySku("test-cm-1");
19+
20+
Assert.assertEquals(139, test_ml_1.getPrice());
21+
Assert.assertEquals(139, test_ml_1.getPriceForQuantity(1000, RoundingMode.HALF_UP));
22+
Assert.assertEquals(60, test_ml_1.getPriceForQuantity(431, RoundingMode.HALF_UP));
23+
24+
Assert.assertEquals(299, test_g_1.getPrice());
25+
Assert.assertEquals(299, test_g_1.getPriceForQuantity(1000, RoundingMode.HALF_UP));
26+
Assert.assertEquals(150, test_g_1.getPriceForQuantity(500, RoundingMode.HALF_UP));
27+
28+
Assert.assertEquals(199, test_cm_1.getPrice());
29+
Assert.assertEquals(1990, test_cm_1.getPriceForQuantity(1000, RoundingMode.HALF_UP));
30+
Assert.assertEquals(498, test_cm_1.getPriceForQuantity(250, RoundingMode.HALF_UP));
31+
}
32+
33+
public void testUnits() {
34+
testConvert(100, Unit.CENTIMETER, Unit.METER, 1);
35+
testConvert(1, Unit.METER, Unit.CENTIMETER, 100);
36+
testConvert(100, Unit.MILLILITER, Unit.LITER, 0.1);
37+
testConvert(2, Unit.SQUARE_METER, Unit.SQUARE_CENTIMETER, 20_000);
38+
testConvert(2.5, Unit.SQUARE_METER, Unit.SQUARE_CENTIMETER, 25_000);
39+
testConvert(3000, Unit.KILOGRAM, Unit.TONNE, 3);
40+
testConvert(3, Unit.TONNE, Unit.KILOGRAM, 3000);
41+
testConvert(2, Unit.PRICE, Unit.PRICE, 2);
42+
testConvert(42, Unit.CENTIMETER, Unit.LITER, 42);
43+
}
44+
45+
private void testConvert(double value, Unit from, Unit to, double expected) {
46+
Assert.assertEquals(Unit.convert(new BigDecimal(value), from, to, 16, RoundingMode.HALF_UP), new BigDecimal(expected));
47+
}
48+
}

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public static SaleRestriction fromDatabaseField(long dbType, long value) {
114114
private String basePrice;
115115
private SaleRestriction saleRestriction = SaleRestriction.NONE;
116116
private Unit referenceUnit;
117+
private Unit encodingUnit;
117118
private Map<String, String> transmissionCodes;
118119
private boolean saleStop;
119120

@@ -228,6 +229,10 @@ public Unit getReferenceUnit() {
228229
return referenceUnit;
229230
}
230231

232+
public Unit getEncodingUnit() {
233+
return encodingUnit;
234+
}
235+
231236
/**
232237
* @return returns true if this product should not be available for sale anymore.
233238
*/
@@ -237,8 +242,20 @@ public boolean getSaleStop() {
237242

238243
public int getPriceForQuantity(int quantity, RoundingMode roundingMode) {
239244
if (type == Product.Type.UserWeighed || type == Product.Type.PreWeighed) {
240-
BigDecimal pricePerUnit = new BigDecimal(getDiscountedPrice())
241-
.divide(new BigDecimal(1000));
245+
Unit referenceUnit = this.referenceUnit;
246+
Unit encodingUnit = this.encodingUnit;
247+
248+
if (referenceUnit == null) {
249+
referenceUnit = Unit.KILOGRAM;
250+
}
251+
252+
if (encodingUnit == null) {
253+
encodingUnit = Unit.GRAM;
254+
}
255+
256+
BigDecimal pricePerReferenceUnit = new BigDecimal(getDiscountedPrice());
257+
BigDecimal pricePerUnit = Unit.convert(pricePerReferenceUnit,
258+
referenceUnit, encodingUnit, 16, roundingMode);
242259

243260
return pricePerUnit.multiply(new BigDecimal(quantity))
244261
.setScale(0, roundingMode)
@@ -411,6 +428,11 @@ public Builder setReferenceUnit(Unit referenceUnit) {
411428
return this;
412429
}
413430

431+
public Builder setEncodingUnit(Unit encodingUnit) {
432+
product.encodingUnit = encodingUnit;
433+
return this;
434+
}
435+
414436
public Builder addTransmissionCode(String fromCode, String transmissionCode) {
415437
if (product.transmissionCodes == null) {
416438
product.transmissionCodes = new HashMap<>();

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,9 @@ private Product toProduct(ApiProduct apiProduct, Product depositProduct, Product
479479
Unit referenceUnit = Unit.fromString(apiProduct.weighing.referenceUnit);
480480
builder.setReferenceUnit(referenceUnit);
481481

482+
Unit encodingUnit = Unit.fromString(apiProduct.weighing.encodingUnit);
483+
builder.setEncodingUnit(encodingUnit);
484+
482485
if (apiProduct.weighing.weighByCustomer) {
483486
builder.setType(Product.Type.UserWeighed);
484487
} else {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,12 @@ public Product productAtCursor(Cursor cursor) {
804804
builder.setType(Product.Type.PreWeighed);
805805
}
806806
}
807+
808+
String encodingUnit = cursor.getString(14);
809+
if (encodingUnit != null) {
810+
Unit unit = Unit.fromString(encodingUnit);
811+
builder.setEncodingUnit(unit);
812+
}
807813
}
808814

809815
Shop shop = project.getCheckedInShop();
@@ -894,6 +900,7 @@ private String productSqlString(String appendSql, boolean distinct) {
894900

895901
if (schemaVersionMajor >= 1 && schemaVersionMinor >= 16) {
896902
sql += ",p.referenceUnit";
903+
sql += ",p.encodingUnit";
897904
}
898905

899906
sql += " FROM products p ";

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package io.snabble.sdk;
22

3+
import java.math.BigDecimal;
4+
import java.math.RoundingMode;
5+
6+
import io.snabble.sdk.utils.Logger;
7+
38
public enum Unit {
49
MILLILITER("ml"),
510
DECILITER("dl"),
@@ -45,6 +50,47 @@ public static Unit fromString(String value) {
4550
return null;
4651
}
4752

53+
public static BigDecimal convert(BigDecimal value, Unit from, Unit to, int scale, RoundingMode rm) {
54+
value = value.setScale(scale, rm);
55+
56+
if (from == LITER && to == DECILITER) return value.divide(new BigDecimal(10), rm);
57+
if (from == DECILITER && to == LITER) return value.multiply(new BigDecimal(10));
58+
59+
if (from == LITER && to == MILLILITER) return value.divide(new BigDecimal(1000), rm);
60+
if (from == MILLILITER && to == LITER) return value.multiply(new BigDecimal(1000));
61+
62+
if (from == DECILITER && to == MILLILITER) return value.divide(new BigDecimal(100), rm);
63+
if (from == MILLILITER && to == DECILITER) return value.multiply(new BigDecimal(100));
64+
65+
if (from == CUBIC_METER && to == CUBIC_CENTIMETER) return value.divide(new BigDecimal(1_000_000), rm);
66+
if (from == CUBIC_CENTIMETER && to == CUBIC_METER) return value.multiply(new BigDecimal(1_000_000));
67+
68+
if (from == SQUARE_METER && to == SQUARE_CENTIMETER) return value.divide(new BigDecimal(10_000), rm);
69+
if (from == SQUARE_CENTIMETER && to == SQUARE_METER) return value.multiply(new BigDecimal(10_000));
70+
71+
if (from == METER && to == CENTIMETER) return value.divide(new BigDecimal(100), rm);
72+
if (from == CENTIMETER && to == METER) return value.multiply(new BigDecimal(100));
73+
74+
if (from == METER && to == MILLIMETER) return value.divide(new BigDecimal(1000), rm);
75+
if (from == MILLIMETER && to == METER) return value.multiply(new BigDecimal(1000));
76+
77+
if (from == CENTIMETER && to == MILLIMETER) return value.divide(new BigDecimal(10), rm);
78+
if (from == MILLIMETER && to == CENTIMETER) return value.multiply(new BigDecimal(10));
79+
80+
if (from == TONNE && to == KILOGRAM) return value.divide(new BigDecimal(1000), rm);
81+
if (from == KILOGRAM && to == TONNE) return value.multiply(new BigDecimal(1000));
82+
83+
if (from == TONNE && to == GRAM) return value.divide(new BigDecimal(1_000_000), rm);
84+
if (from == GRAM && to == TONNE) return value.multiply(new BigDecimal(1_000_000));
85+
86+
if (from == KILOGRAM && to == GRAM) return value.divide(new BigDecimal(1000), rm);
87+
if (from == GRAM && to == KILOGRAM) return value.multiply(new BigDecimal(1000));
88+
89+
Logger.d("Unsupported conversion: %s -> %s", from.toString(), to.toString());
90+
91+
return value;
92+
}
93+
4894
public String getDisplayValue() {
4995
return displayValue;
5096
}

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import io.snabble.sdk.Product;
4242
import io.snabble.sdk.Project;
4343
import io.snabble.sdk.ShoppingCart;
44+
import io.snabble.sdk.Unit;
4445
import io.snabble.sdk.codes.EAN13;
4546
import io.snabble.sdk.codes.ScannableCode;
4647
import io.snabble.sdk.PriceFormatter;
@@ -421,6 +422,7 @@ private class ViewHolder extends RecyclerView.ViewHolder {
421422
View controlsUserWeighed;
422423
View controlsDefault;
423424
View quantityEditApply;
425+
TextView quantityAnnotation;
424426

425427
TextWatcher textWatcher;
426428

@@ -438,6 +440,7 @@ public ViewHolder(View itemView) {
438440
controlsDefault = itemView.findViewById(R.id.controls_default);
439441
quantityEdit = itemView.findViewById(R.id.quantity_edit);
440442
quantityEditApply = itemView.findViewById(R.id.quantity_edit_apply);
443+
quantityAnnotation = itemView.findViewById(R.id.quantity_annotation);
441444
}
442445

443446
@SuppressLint("SetTextI18n")
@@ -452,7 +455,14 @@ public void bindTo(final int position) {
452455
if (product != null) {
453456
Product.Type type = product.getType();
454457

458+
Unit encodingUnit = product.getEncodingUnit();
459+
String encodingDisplayValue = "g";
460+
if (encodingUnit != null) {
461+
encodingDisplayValue = encodingUnit.getDisplayValue();
462+
}
463+
455464
name.setText(product.getName());
465+
quantityAnnotation.setText(encodingDisplayValue);
456466

457467
String price = priceFormatter.format(product);
458468

@@ -473,11 +483,11 @@ public void bindTo(final int position) {
473483
}
474484

475485
if (embeddedWeight != null) {
476-
quantityTextView.setText(String.format("%s g", String.valueOf(embeddedWeight)));
486+
quantityTextView.setText(String.format("%s %s", String.valueOf(embeddedWeight), encodingDisplayValue));
477487
} else if (embeddedAmount != null) {
478488
quantityTextView.setText(String.valueOf(embeddedAmount));
479489
} else if (type == Product.Type.UserWeighed) {
480-
quantityTextView.setText(String.format("%s g", String.valueOf(quantity)));
490+
quantityTextView.setText(String.format("%s %s", String.valueOf(quantity), encodingDisplayValue));
481491
} else {
482492
quantityTextView.setText(String.valueOf(quantity));
483493
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public void show(Product newProduct, ScannableCode scannedCode) {
114114

115115
if (scannedCode.hasEmbeddedData()) {
116116
if (scannedCode.hasWeighData()) {
117-
quantityAnnotation.setText("g");
117+
quantityAnnotation.setText(product.getEncodingUnit().getDisplayValue());
118118
plus.setVisibility(View.GONE);
119119
minus.setVisibility(View.GONE);
120120
quantityAnnotation.setVisibility(View.VISIBLE);
@@ -151,7 +151,7 @@ public void show(Product newProduct, ScannableCode scannedCode) {
151151
}
152152
} else if (type == Product.Type.UserWeighed) {
153153
quantityAnnotation.setVisibility(View.VISIBLE);
154-
quantityAnnotation.setText("g");
154+
quantityAnnotation.setText(product.getEncodingUnit().getDisplayValue());
155155
plus.setVisibility(View.GONE);
156156
minus.setVisibility(View.GONE);
157157
quantity.setText("");
@@ -281,9 +281,15 @@ private void updatePrice() {
281281
String singlePrice = priceFormatter.format(product);
282282

283283
int q = getQuantity();
284+
Unit encodingUnit = product.getEncodingUnit();
285+
286+
String encodingDisplayValue = "g";
287+
if (encodingUnit != null) {
288+
encodingDisplayValue = encodingUnit.getDisplayValue();
289+
}
284290

285291
if (q > 0 && (scannedCode.hasWeighData() || product.getType() == Product.Type.UserWeighed)) {
286-
price.setText(String.format("%sg * %s = %s", String.valueOf(q), singlePrice, priceText));
292+
price.setText(String.format("%s%s * %s = %s", String.valueOf(q), encodingDisplayValue, singlePrice, priceText));
287293
} else if (q > 1) {
288294
if (scannedCode.hasUnitData()) {
289295
price.setText(String.format("%s * %s = %s",

0 commit comments

Comments
 (0)