From 4d39716bcbaa639c39c2c08d998fdb4385d55bcb Mon Sep 17 00:00:00 2001 From: "Jonguk. Lim" Date: Mon, 13 May 2024 14:39:04 +0900 Subject: [PATCH] =?UTF-8?q?Barcode=20=EB=A6=AC=EB=8D=94=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=8B=9C=20=EB=B0=94=EC=BD=94=EB=93=9C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20parsing=20->=20=EC=A0=9C=ED=92=88=EC=BD=94=EB=93=9C?= =?UTF-8?q?,=20=EC=A0=9C=EC=A1=B0=EB=B2=88=ED=98=B8,=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EA=B8=B0=EA=B0=84,=20=EC=A0=9C=ED=92=88=EC=9D=BC=EB=A0=A8?= =?UTF-8?q?=EB=B2=88=ED=98=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adds/biz/nims/model/BizNimsResponse.java | 169 ++++++++++++++++++ .../xit/adds/biz/nims/web/QrController.java | 25 ++- 2 files changed, 189 insertions(+), 5 deletions(-) diff --git a/src/main/java/cokr/xit/adds/biz/nims/model/BizNimsResponse.java b/src/main/java/cokr/xit/adds/biz/nims/model/BizNimsResponse.java index f3517d0..025a2b5 100644 --- a/src/main/java/cokr/xit/adds/biz/nims/model/BizNimsResponse.java +++ b/src/main/java/cokr/xit/adds/biz/nims/model/BizNimsResponse.java @@ -1,9 +1,13 @@ package cokr.xit.adds.biz.nims.model; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import cokr.xit.adds.core.Constants; import cokr.xit.adds.inf.nims.model.NimsApiDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -148,4 +152,169 @@ public class BizNimsResponse { // */ // private String prtmSeNm; } + + /** + *
+	 * Barcode(GS1-128) 조회 response
+	 * 최소 30자리 이상
+	 * AI상품식별코드(2) + 상품코드(14) + AI최대유통일자(2) + 유통일자(6) + AI로트번호(2) + 제조번호(1) + AI일련번호(2) + 제품일련번호(1)
+	 * -> 상품코드(확장코드(1) + 상품코드(13)), 제조번호(1), 제품일련번호(1) 은 필수로 포함한다는 가정
+	 * 
+ */ + @Schema(name = "Barcode", description = "Barcode response DTO") + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Barcode { + /** + *
+		 * GS1-128 barcode - 01 : AI상품식별코드
+		 * 2자리 : 01
+		 * 
+ */ + @Builder.Default + private String gsId = "01"; + + /** + *
+		 * GS1-128 상품코드
+		 * 14자리 - 확장코드(0) + 상품코드(13)
+		 * 
+ */ + private String gsPrductCd; + + /** + *
+		 * GS1-128 확장코드
+		 * 1자리 - 확장코드(0)
+		 * 
+ */ + @Builder.Default + private String gsPrductExtCd = "0"; + + /** + *
+		 * AI최대유통일자
+		 * 2자리 : 17
+		 * 
+ */ + @Builder.Default + private String gsDistributionDel = "17"; + + /** + *
+		 * 유통일자 : YYMMDD
+		 * 6자리
+		 * 
+ */ + private String gsDistributionDate; + + /** + *
+		 * AI로트번호
+		 * 2자리 - 10
+		 * 
+ */ + @Builder.Default + private String gsAiLotNo = "10"; + + /** + *
+		 * 제조번호(제품의 생산라인 제조번호)
+		 * 20자 이하
+		 * AI로트번호(10) 이후 ~ AI일련번호(21) 이전
+		 * 
+ */ + private String gsMnfNo; + + /** + *
+		 * AI일련번호
+		 * 2자리 - 21
+		 * 
+ */ + @Builder.Default + private String gsAiSerialNo = "21"; + + /** + *
+		 * 제품일련번호
+		 * AI일련번호 이후 20자 이하
+		 * 
+ */ + private String gsMnfSeqNo; + + /** + *
+		 * 바코드 reader 사용시 - Barcode(GS1-128) 정보 파싱
+		 * 상품코드, 제조번호, 유효기간, 제조일련번호
+		 *
+		 * @param barcodeStr
+		 * @return NimsApiDto.MnfSeqInfo
+		 * 
+ */ + public NimsApiDto.MnfSeqInfo parseBarcode(final String barcodeStr){ + NimsApiDto.MnfSeqInfo mnfSeqInfo = new NimsApiDto.MnfSeqInfo(); + + if(barcodeStr.length() < 30){ + throw new IllegalArgumentException("Barcode는 최소 30자리 이상이어야 합니다."); + } + // AI상품식별코드(01)로 시작 + if(barcodeStr.startsWith(this.gsId) == false){ + throw new IllegalArgumentException("Barcode(GS1-128)는 AI상품식별코드(01)로 시작 되어야 합니다."); + } + String barcode = barcodeStr.substring(barcodeStr.indexOf(this.gsId)+this.gsId.length()); + + // 상품코드(확장코드(0) + 상품코드(13)) + String temp = barcode.substring(0, 14); + String regx = "^0(\\d{13})"; + Pattern pattern = Pattern.compile(regx); + Matcher matcher = pattern.matcher(temp); + if(matcher.find()) { + //this.gsPrductCd = matcher.group(1); + mnfSeqInfo.setPrductCd(matcher.group(1)); + }else{ + throw new IllegalArgumentException("Barcode(GS1-128) 상품코드는 확장코드(0) + 상품코드(13)로 구성되어야 합니다."); + } + barcode = barcode.substring(14); + + // 유통일자 : AI최대유통일자(17) + 6자리 유통일자 + temp = barcode.substring(0, 8); + regx = "^17(\\d{6})"; + pattern = Pattern.compile(regx); + matcher = pattern.matcher(temp); + if(matcher.find()) { + //this.gsDistributionDate = matcher.group(1); + mnfSeqInfo.setPrdValidDe(matcher.group(1)); + }else{ + throw new IllegalArgumentException("Barcode(GS1-128) 유통일자는 AI최대유통일자(17) + 유통일자(6)로 구성되어야 합니다."); + } + barcode = barcode.substring(8); + + // 제조번호 : AI로트번호(10)로 시작 ~ 20자 이하 제조번호 ~ AI일련번호(21) 이전 + regx = "^10(.{1,20})21"; + pattern = Pattern.compile(regx); + matcher = pattern.matcher(barcode); + if(matcher.find()) { + //this.gsMnfNo = matcher.group(1); + mnfSeqInfo.setMnfNo(matcher.group(1)); + }else { + throw new IllegalArgumentException("Barcode(GS1-128) 제조번호는 AI로트번호(10)로 시작 되어 AI일련번호(21)로 끝나야 합니다."); + } + barcode = barcode.substring(mnfSeqInfo.getMnfNo().length()+2); + + // 제품일련번호 : AI일련번호(21)로 시작 ~ 20자 이하 제조일련번호 + regx = "^21(.{1,20}$)"; + pattern = Pattern.compile(regx); + matcher = pattern.matcher(barcode); + if(matcher.find()) { + //this.gsMnfSeqNo = matcher.group(1); + mnfSeqInfo.setMnfSeq(matcher.group(1)); + }else { + throw new IllegalArgumentException("Barcode(GS1-128) 제조일련번호는 AI일련번호(21)로 시작 되어야 합니다."); + } + return mnfSeqInfo; + } + } } diff --git a/src/main/java/cokr/xit/adds/biz/nims/web/QrController.java b/src/main/java/cokr/xit/adds/biz/nims/web/QrController.java index 7e0022e..0d35701 100644 --- a/src/main/java/cokr/xit/adds/biz/nims/web/QrController.java +++ b/src/main/java/cokr/xit/adds/biz/nims/web/QrController.java @@ -1,6 +1,7 @@ package cokr.xit.adds.biz.nims.web; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,7 +15,10 @@ import org.springframework.web.servlet.ModelAndView; import com.google.zxing.NotFoundException; +import cokr.xit.adds.biz.nims.model.BizNimsResponse; import cokr.xit.adds.core.util.XingUtils; +import cokr.xit.adds.inf.nims.model.NimsApiDto; +import io.swagger.v3.oas.annotations.tags.Tag; /** *
@@ -31,23 +35,26 @@ import cokr.xit.adds.core.util.XingUtils;
  *
  * 
*/ +@Tag(name = "QrController", description = "qrcode API") @RestController public class QrController { - @GetMapping("/biz/nims/v1/qrcodeForm") + @GetMapping("/api/biz/nims/v1/qrcodeForm") public ModelAndView qrcodeForm() { return new ModelAndView("/zxing/index.html"); } - @PostMapping("/biz/nims/v1/getQrcode") - public List> uploadQrCode( + @PostMapping(value = "/api/biz/nims/v1/getQrcode", consumes = { "multipart/form-data" }) + public List uploadQrCode( @RequestParam("uploadFiles") final List multipartFiles ) { - return multipartFiles.stream().map(mf -> { + List mnfSeqInfos = new ArrayList<>(); + + List> list = multipartFiles.stream().map(mf -> { System.out.println(mf.getOriginalFilename()); System.out.println(mf.getSize()); - Map map = new HashMap<>(); + Map map = new HashMap<>(); try { map.put("qrcode", XingUtils.readQrcodeFromFile(XingUtils.convert(mf))); map.put("name", mf.getOriginalFilename()); @@ -56,5 +63,13 @@ public class QrController { } return map; }).toList(); + + for(Map map: list){ + System.out.println(map.get("qrcode")); + + BizNimsResponse.Barcode barcode = new BizNimsResponse.Barcode(); + mnfSeqInfos.add(barcode.parseBarcode(map.get("qrcode"))); + } + return mnfSeqInfos; } }