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