diff --git a/README.md b/README.md
index 1b6f45e..c480605 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@
Перечень поддерживаемых товарных групп:
+### version 1.0
* Обувь ([ППР №860 от 05.07.2019](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/860.pdf))
* Товары лёгкой промышленности ([ППР №1956 от 31.12.2019](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/1956.pdf))
* Духи и туалетная вода ([ППР №1957 от 31.12.2019](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/%D0%9F%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%B0_%D0%A0%D0%A4_%D0%BE%D1%82_31_12_2019_N_1957_%D1%80%D0%B5%D0%B4_%D0%BE%D1%82_20_11.pdf))
@@ -15,6 +16,16 @@
* Пиво и слабоалкогольные напитки ([ППР №2173 от 30.11.2022](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/%D0%9F%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%B0%20%E2%84%962173.pdf))
* Упакованная вода ([ППР №841 от 31.05.2021](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/%D0%9F%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%B0_%D0%A0%D0%A4_%D0%BE%D1%82_31_05_2021_N_841_%D1%80%D0%B5%D0%B4_%D0%BE%D1%82_26_03.pdf))
+### version 1.1
+* Одежда ([ППР № 1956 от 31.12.2019г.](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/%D0%9F%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%B0_%D0%A0%D0%A4_%D0%BE%D1%82_31_05_2021_N_841_%D1%80%D0%B5%D0%B4_%D0%BE%D1%82_26_03.pdf))
+* Шины ([ППР № 1958 от 31.12.2019г.](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/%D0%9F%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%B0_%D0%A0%D0%A4_%D0%BE%D1%82_31_05_2021_N_841_%D1%80%D0%B5%D0%B4_%D0%BE%D1%82_26_03.pdf))
+* Велосипеды ([Метод рекомен от 05.11.2019г.](https://честныйзнак.рф/upload/iblock/a1e/Metodicheskie_rekomendatsii_dlya_TG_Velosipedy.pdf))
+* Мед.изделия ([Метод.рекомен от 27.11.2019г.](https://честныйзнак.рф/upload/iblock/4f6/Методические%20рекомендации.pdf))
+* Фотоаппараты ([ППР № 1953 от 21.12.2019г.](https://xn--80ajghhoc2aj1c8b.xn--p1ai/upload/%D0%9F%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%B0_%D0%A0%D0%A4_%D0%BE%D1%82_31_05_2021_N_841_%D1%80%D0%B5%D0%B4_%D0%BE%D1%82_26_03.pdf))
+* БАД ([Проект ППР](https://regulation.gov.ru/projects#npa=130322))
+* Антисептики ([Проект ППР](https://regulation.gov.ru/projects#npa=130584))
+* Табак,АТП*, НСП* ([ППР № 224 от 28.02.2019г.](https://base.garant.ru/72189916/))
+
# Даматарикс код можно валидировать
* **с указанием конкретной товарной группы**
diff --git a/pom.xml b/pom.xml
index 4a3a9c5..9219513 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
ru.lamoda.datamatrix
datamatrix-validator
- 1.0
+ 1.1
8
diff --git a/src/main/java/ru/lamoda/datamatrix/model/AI.java b/src/main/java/ru/lamoda/datamatrix/model/AI.java
index bce7025..fba2d98 100644
--- a/src/main/java/ru/lamoda/datamatrix/model/AI.java
+++ b/src/main/java/ru/lamoda/datamatrix/model/AI.java
@@ -21,6 +21,9 @@ public ValidationResult getValidationResult(TradeGroup type, String value) {
@Override
public int getSize(TradeGroup type) {
+ if (type == NICOTINE) {
+ return getCode().length() + 12;
+ }
return getCode().length() + 14;
}
},
@@ -40,7 +43,10 @@ public int getSize(TradeGroup type) {
case MILK:
return getCode().length() + 6;
case BEER:
+ case NICOTINE:
return getCode().length() + 7;
+ case CAMERAS:
+ return getCode().length() + 20;
default:
return getCode().length() + 13;
}
@@ -51,7 +57,7 @@ public int getSize(TradeGroup type) {
@Override
public ValidationResult getValidationResult(TradeGroup type, String value) {
return notBlank
- .and(checkTradeGroup(type, SHOES, LP, PERFUMERY))
+ .and(checkTradeGroup(type, ANTISEPTIC, BICYCLES, CAMERAS, CLOTHES, DS, LP, MP, PERFUMERY, SHOES, TIRES))
.and(fixedSize(getSize(type)))
.and(checkRegex(GS1_ISO_SUBSET_FOR_CONTROL_NUMBER))
.test(value);
@@ -60,9 +66,16 @@ public ValidationResult getValidationResult(TradeGroup type, String value) {
@Override
public int getSize(TradeGroup type) {
switch (type) {
- case SHOES:
+ case ANTISEPTIC:
+ case BICYCLES:
+ case CAMERAS:
+ case CLOTHES:
+ case DS:
case LP:
+ case MP:
case PERFUMERY:
+ case SHOES:
+ case TIRES:
return getCode().length() + 4;
default:
return 0;
@@ -74,7 +87,7 @@ public int getSize(TradeGroup type) {
@Override
public ValidationResult getValidationResult(TradeGroup type, String value) {
return notBlank
- .and(checkTradeGroup(type, BEER, WATER, MILK))
+ .and(checkTradeGroup(type, ANTISEPTIC, BEER, DS, WATER, MILK))
.and(fixedSize(getSize(type)))
.and(checkRegex(GS1_ISO_SUBSET_FOR_CONTROL_NUMBER))
.test(value);
@@ -83,9 +96,11 @@ public ValidationResult getValidationResult(TradeGroup type, String value) {
@Override
public int getSize(TradeGroup type) {
switch (type) {
+ case ANTISEPTIC:
+ case BEER:
+ case DS:
case MILK:
case WATER:
- case BEER:
return getCode().length() + 4;
default:
return 0;
@@ -97,7 +112,7 @@ public int getSize(TradeGroup type) {
@Override
public ValidationResult getValidationResult(TradeGroup type, String value) {
return notBlank
- .and(checkTradeGroup(type, PERFUMERY, SHOES, LP))
+ .and(checkTradeGroup(type, SHOES, ANTISEPTIC, BICYCLES, CAMERAS, CLOTHES, DS, LP, MP, PERFUMERY, TIRES))
.and(fixedSize(getSize(type)))
.and(checkRegex(GS1_ISO_SUBSET_FOR_CRYPTO_TAIL))
.test(value);
@@ -108,8 +123,15 @@ public int getSize(TradeGroup type) {
switch (type) {
case SHOES:
return getCode().length() + 88;
- case PERFUMERY:
+ case ANTISEPTIC:
+ case BICYCLES:
+ case CAMERAS:
+ case CLOTHES:
+ case DS:
case LP:
+ case MP:
+ case PERFUMERY:
+ case TIRES:
return getCode().length() + 44;
default:
return 0;
@@ -155,6 +177,25 @@ public int getSize(TradeGroup type) {
}
},
+ AI_8005("8005", false) {
+ @Override
+ public ValidationResult getValidationResult(TradeGroup type, String value) {
+ return notBlank
+ .and(checkTradeGroup(type, NICOTINE))
+ .and(fixedSize(getSize(type)))
+ .and(onlyNumbers())
+ .test(value);
+ }
+
+ @Override
+ public int getSize(TradeGroup type) {
+ if (type == NICOTINE) {
+ return getCode().length() + 6;
+ }
+ return 0;
+ }
+ },
+
AI_335Y("335", false) {
@Override
public ValidationResult getValidationResult(TradeGroup type, String value) {
diff --git a/src/main/java/ru/lamoda/datamatrix/model/TradeGroup.java b/src/main/java/ru/lamoda/datamatrix/model/TradeGroup.java
index a5ce3e4..96155d7 100644
--- a/src/main/java/ru/lamoda/datamatrix/model/TradeGroup.java
+++ b/src/main/java/ru/lamoda/datamatrix/model/TradeGroup.java
@@ -1,6 +1,7 @@
package ru.lamoda.datamatrix.model;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import static java.util.Arrays.asList;
@@ -38,10 +39,53 @@ public enum TradeGroup {
* Товары лёгкой промышленности
*/
LP(AI_01, AI_21, AI_91, AI_92),
+ /**
+ * Одежда
+ */
+ CLOTHES(AI_01, AI_21, AI_91, AI_92),
/**
* Парфюмерия
*/
- PERFUMERY(AI_01, AI_21, AI_91, AI_92);
+ PERFUMERY(AI_01, AI_21, AI_91, AI_92),
+ /**
+ * Шины
+ */
+ TIRES(AI_01, AI_21, AI_91, AI_92),
+ /**
+ * Велосипеды
+ */
+ BICYCLES(AI_01, AI_21, AI_91, AI_92),
+ /**
+ * Мед. изделия - Medical products
+ */
+ MP(AI_01, AI_21, AI_91, AI_92),
+ /**
+ * Фотоаппараты
+ */
+ CAMERAS(AI_01, AI_21, AI_91, AI_92),
+ /**
+ * БАДы - dietary supplement
+ */
+ DS(
+ asList(AI_01, AI_21, AI_93),
+ asList(AI_01, AI_21, AI_91, AI_92)
+ ),
+ /**
+ * Антисептики
+ */
+ ANTISEPTIC(
+ asList(AI_01, AI_21, AI_93),
+ asList(AI_01, AI_21, AI_91, AI_92)
+ ),
+ /**
+ * Никотин-содержащая продукция - Nicotine-containing products
+ */
+ NICOTINE(
+ Collections.emptyList(),
+ Collections.singletonList(AI_01),
+ asList(AI_01, AI_21, AI_93),
+ asList(AI_01, AI_21, AI_8005, AI_93)
+ );
/**
* Список поддерживаемых форматов для каждой товарной группы
diff --git a/src/main/java/ru/lamoda/datamatrix/validation/DatamatrixValidator.java b/src/main/java/ru/lamoda/datamatrix/validation/DatamatrixValidator.java
index 4e974b1..f7a1576 100644
--- a/src/main/java/ru/lamoda/datamatrix/validation/DatamatrixValidator.java
+++ b/src/main/java/ru/lamoda/datamatrix/validation/DatamatrixValidator.java
@@ -103,19 +103,23 @@ private static List splitToAis(String datamatrixCode, TradeGroup type) {
List ais = Arrays.stream(AI.values())
.filter(ai -> part.startsWith(ai.getCode()))
.collect(Collectors.toList());
- if (ais.size() == 0) {
- throw new DatamatrixCodeIncorrectException("unknown AI");
- }
- for (AI identifier : ais) {
- if (!identifier.isFixedSize()) {
- identifier.validateThrow(type, part);
- result.add(identifier);
- } else {
- String begin = part.substring(0, identifier.getSize(type));
- identifier.validateThrow(type, begin);
- result.add(identifier);
- result.addAll(splitToAis(part.substring(identifier.getSize(type)), type));
+ if (!ais.isEmpty()) {
+ for (AI identifier : ais) {
+ if (!identifier.isFixedSize()) {
+ identifier.validateThrow(type, part);
+ result.add(identifier);
+ } else {
+ String begin = part.substring(0, identifier.getSize(type));
+ identifier.validateThrow(type, begin);
+ result.add(identifier);
+ result.addAll(splitToAis(part.substring(identifier.getSize(type)), type));
+ }
}
+ } else if (datamatrixCode.length() == 29 || datamatrixCode.length() == 15) {
+ //for short NICOTINE
+ return result;
+ } else {
+ throw new DatamatrixCodeIncorrectException("unknown AI");
}
}
return result;
diff --git a/src/main/java/ru/lamoda/datamatrix/validation/ValidationHelper.java b/src/main/java/ru/lamoda/datamatrix/validation/ValidationHelper.java
index 82d30a3..d326f6b 100644
--- a/src/main/java/ru/lamoda/datamatrix/validation/ValidationHelper.java
+++ b/src/main/java/ru/lamoda/datamatrix/validation/ValidationHelper.java
@@ -31,7 +31,8 @@ public static Validation notContainsDoubleGS() {
}
public static Validation containsGS() {
- return SimpleValidation.from((s) -> contains(s, GS), "must contain ");
+ return SimpleValidation.from((s) -> contains(s, GS) || s.length() == 29,
+ "must contain or code length must be 29 characters");
}
public static Validation onlyNumbers() {
diff --git a/src/test/java/ru/lamoda/datamatrix/DatamatrixValidatorTest.java b/src/test/java/ru/lamoda/datamatrix/DatamatrixValidatorTest.java
index 0bf22be..eb7b139 100644
--- a/src/test/java/ru/lamoda/datamatrix/DatamatrixValidatorTest.java
+++ b/src/test/java/ru/lamoda/datamatrix/DatamatrixValidatorTest.java
@@ -43,6 +43,9 @@ public static Object[][] badDatamatrixList() {
String beerCodeWithWrongVolumeSize = "0104610053147452215d,OiLl\u001D93dGVz\u001D335112345";
String withUnknownCode = "0104610053149777215d/wuU\u001D93dGVz\u001D88dGVz";
String withDoubleCode = "0104653820923088215GoNfWgdcBeVZ\u001D93dGVz\u001D93dGVz";
+ String invalidShortNicotine = "04603731175212JEIjNYDAAAAtFw";
+ String invalidCamerasCode = "0102900000387843215v&XqVigrspEe95cj\"jF\u001D91FFD0\u001D";
+
return new Object[][]{
{null},
{""},
@@ -57,6 +60,8 @@ public static Object[][] badDatamatrixList() {
{beerCodeWithWrongVolumeSize},
{withUnknownCode},
{withDoubleCode},
+ {invalidShortNicotine},
+ {invalidCamerasCode},
};
}
@@ -69,6 +74,49 @@ public static Object[][] goodDatamatrixList() {
String beerCode = "0104610053147452215d,OiLl\u001D93dGVz";
String beerCodeWithVolume = "0104610053147452215d,OiLl\u001D93dGVz\u001D3350123456";
String lpCode = "0104669000322220215t*NH>t:ngCfH\u001D91FFD0\u001D92dGVzdBL8SAtwRqhp7H9rfyI59GoJ8ec6X9GhckDf8JE=";
+// Обувь
+ String footwear = "0104680128320356215BWOM0ip7Ns3M91FFD092testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest";
+// Одежда
+ String clothes = "0104669000322695215YCQ?cX3bNsD<91FFD092dGVzdMXgZt5JFLIfm/gTAGFQsN1zD3MhYdOBHhprah8=";
+// Молоко
+ String milk = "01046690003220602156BelF93dGVz";
+// Духи
+ String perfume = "0104669000322169215GqtjhXBO%LNp91FFD092dGVzdCR1+WbFwT1f8YoWctkvZKnLEpdiMjfsYVlNFAM=";
+// Вода
+ String water = "01046690003222372151G'OclhkkPrJ93dGVz";
+// Шины
+ String tires = "0104669000322152215W&r