Skip to content

Instantly share code, notes, and snippets.

@rodrigocananea
Created May 28, 2024 14:22
Show Gist options
  • Save rodrigocananea/5fbca1cac36f3cdf690149daf843c9a1 to your computer and use it in GitHub Desktop.
Save rodrigocananea/5fbca1cac36f3cdf690149daf843c9a1 to your computer and use it in GitHub Desktop.
Útil para validação de códigos GTIN, aplicado cálculos baseado no GS1.
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
*
* @author Rodrigo Cananea <rodrigoaguiar35@gmail.com>
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class GTINUtil {
private static final String SEM_GTIN = "SEM GTIN";
public static boolean isGTIN(int gtin) {
return gtin == 8 || gtin == 12 || gtin == 13 || gtin == 14;
}
public static boolean isGTIN(String barras) {
if (barras == null) return false;
String numeric = barras.replaceAll("\\D", "");
int length = numeric.length();
return length >= 8 && length <= 14 && validaPrefixos(barras);
}
public static boolean isValido(String barras) {
return !SEM_GTIN.equals(validar(barras));
}
public static String validar(String barras) {
if (!isGTIN(barras)) {
return SEM_GTIN;
}
GTINEnum gtinEnum = GTINEnum.get(barras.replaceAll("\\D", "").length());
return validar(barras, gtinEnum);
}
public static String validar(String barras, GTINEnum gtinEnum) {
if (isGTIN(barras) && isGTIN(gtinEnum.getCodigo())) {
switch (gtinEnum) {
case GTIN8: return validaGTIN(barras, Arrays.asList(0, 2, 4, 6));
case GTIN12: return validaGTIN(barras, Arrays.asList(0, 2, 4, 6, 8, 10));
case GTIN13: return validaGTIN(barras, Arrays.asList(1, 3, 5, 7, 9, 11));
case GTIN14: return validaGTIN(barras, Arrays.asList(0, 2, 4, 6, 8, 10, 12));
default: return SEM_GTIN;
}
}
return SEM_GTIN;
}
private static String validaGTIN(String barras, List<Integer> indices) {
List<Integer> barrasArray = Arrays.stream(barras.split(""))
.map(Integer::valueOf)
.collect(Collectors.toList());
AtomicInteger soma = new AtomicInteger(0);
IntStream.range(0, barrasArray.size() - 1).forEach(i -> {
int n = barrasArray.get(i);
if (indices.contains(i)) {
n *= 3;
}
soma.addAndGet(n);
});
int multiplo = obterMultiploDeDez(soma.get());
int resultado = multiplo - soma.get();
boolean isValido = resultado == barrasArray.get(barrasArray.size() - 1);
return isValido ? barras : SEM_GTIN;
}
/**
* Múltiplo mais próximo, igual ou superior de dez
* https://www.gs1.org/services/how-calculate-check-digit-manually
*
* @param soma
* @return
*/
private static int obterMultiploDeDez(int soma) {
return (soma % 10 == 0 ? soma : (soma - (soma % 10)) + 10);
}
/**
* Validar prefixos validos de acordo com:
* https://www.gs1.org/standards/id-keys/company-prefix
*
* @param barras
* @return
*/
public static boolean validaPrefixos(String barras) {
return Arrays.stream(GS1Prefixo.values())
.anyMatch(gs1 -> Pattern.compile(gs1.getPrefixos()).matcher(barras).find());
}
@Getter
@RequiredArgsConstructor
public enum GS1Prefixo {
GS1_US("^(001|019|030|039|050|059|060|139)"),
GS1_FRANCE("^(300|379)"),
GS1_BULGARIA("^(380)"),
GS1_SLOVENIJA("^(383)"),
GS1_CROATIA("^(385)"),
GS1_BIH("^(387)"),
GS1_MONTENEGRO("^(389)"),
GS1_GERMANY("^(400|440)"),
GS1_JAPAN("^(450|459|490|499)"),
GS1_RUSSIA("^(460|469)"),
GS1_KYRGYZSTAN("^(470)"),
GS1_CHINESE_TAIPEI("^(471)"),
GS1_ESTONIA("^(474)"),
GS1_LATVIA("^(475)"),
GS1_AZERBAIJAN("^(476)"),
GS1_LITHUANIA("^(477)"),
GS1_UZBEKISTAN("^(478)"),
GS1_SRI_LANKA("^(479)"),
GS1_PHILIPPINES("^(480)"),
GS1_BELARUS("^(481)"),
GS1_UKRAINE("^(482)"),
GS1_TURKMENISTAN("^(483)"),
GS1_MOLDOVA("^(484)"),
GS1_ARMENIA("^(485)"),
GS1_GEORGIA("^(486)"),
GS1_KAZAKSTAN("^(487)"),
GS1_TAJIKISTAN("^(488)"),
GS1_HONG_KONG("^(489)"),
GS1_UK("^(500|509)"),
GS1_GREECE("^(520|521)"),
GS1_LEBANON("^(528)"),
GS1_CYPRUS("^(529)"),
GS1_ALBANIA("^(530)"),
GS1_MACEDONIA("^(531)"),
GS1_MALTA("^(535)"),
GS1_IRELAND("^(539)"),
GS1_BELGIUM_LUXEMBOURG("^(540|549)"),
GS1_PORTUGAL("^(560)"),
GS1_ICELAND("^(569)"),
GS1_DENMARK("^(570|579)"),
GS1_POLAND("^(590)"),
GS1_ROMANIA("^(594)"),
GS1_HUNGARY("^(599)"),
GS1_SOUTH_AFRICA("^(600|601)"),
GS1_GHANA("^(603)"),
GS1_SENEGAL("^(604)"),
GS1_OMAN("^(607)"),
GS1_BAHRAIN("^(608)"),
GS1_MAURITIUS("^(609)"),
GS1_MOROCCO("^(611)"),
GS1_ALGERIA("^(613)"),
GS1_NIGERIA("^(615)"),
GS1_KENYA("^(616)"),
GS1_CAMEROON("^(617)"),
GS1_COTE_D_IVOIRE("^(618)"),
GS1_TUNISIA("^(619)"),
GS1_TANZANIA("^(620)"),
GS1_SYRIA("^(621)"),
GS1_EGYPT("^(622)"),
GS1_LIBYA("^(624)"),
GS1_JORDAN("^(625)"),
GS1_IRAN("^(626)"),
GS1_KUWAIT("^(627)"),
GS1_SAUDI_ARABIA("^(628)"),
GS1_EMIRATES("^(629)"),
GS1_NAMIBIA("^(631)"),
GS1_FINLAND("^(640|649)"),
GS1_CHINA("^(680|681|690|699)"),
GS1_NORWAY("^(700|709)"),
GS1_ISRAEL("^(729)"),
GS1_SWEDEN("^(730|739)"),
GS1_GUATEMALA("^(740)"),
GS1_EL_SALVADOR("^(741)"),
GS1_HONDURAS("^(742)"),
GS1_NICARAGUA("^(743)"),
GS1_COSTA_RICA("^(744)"),
GS1_PANAMA("^(745)"),
GS1_DOMINICAN_REPUBLIC("^(746)"),
GS1_MEXICO("^(750)"),
GS1_CANADA("^(754|755)"),
GS1_VENEZUELA("^(759)"),
GS1_SWITZERLAND("^(760|769)"),
GS1_COLOMBIA("^(770|771)"),
GS1_URUGUAY("^(773)"),
GS1_PERU("^(775)"),
GS1_BOLIVIA("^(777)"),
GS1_ARGENTINA("^(778|779)"),
GS1_CHILE("^(780)"),
GS1_PARAGUAY("^(784)"),
GS1_ECUADOR("^(786)"),
GS1_BRASIL("^(789|790)"),
GS1_ITALY("^(800|839)"),
GS1_SPAIN("^(840|849)"),
GS1_CUBA("^(850)"),
GS1_SLOVAKIA("^(858)"),
GS1_CZECH("^(859)"),
GS1_SERBIA("^(860)"),
GS1_MONGOLIA("^(865)"),
GS1_NORTH_KOREA("^(867)"),
GS1_TURKEY("^(868|869)"),
GS1_NETHERLANDS("^(870|879)"),
GS1_SOUTH_KOREA("^(880|881)"),
GS1_MYANMAR("^(883)"),
GS1_CAMBODIA("^(884)"),
GS1_THAILAND("^(885)"),
GS1_SINGAPORE("^(888)"),
GS1_INDIA("^(890)"),
GS1_VIETNAM("^(893)"),
GS1_PAKISTAN("^(896)"),
GS1_INDONESIA("^(899)"),
GS1_AUSTRIA("^(900|919)"),
GS1_AUSTRALIA("^(930|939)"),
GS1_NEW_ZEALAND("^(940|949)"),
GS1_MALAYSIA("^(955)"),
GS1_MACAU("^(958)");
private final String prefixos;
}
@Getter
@RequiredArgsConstructor
public enum GTINEnum {
SEM_GTIN(0),
GTIN8(8),
GTIN12(12),
GTIN13(13),
GTIN14(14);
private final Integer codigo;
public static GTINEnum get(int codigo) {
return Arrays.stream(GTINEnum.values())
.filter(enums -> enums.getCodigo() == codigo)
.findFirst()
.orElse(GTINEnum.SEM_GTIN);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment