diff --git a/api-admin/pom.xml b/api-admin/pom.xml index 5c23b5e..9c5fce2 100644 --- a/api-admin/pom.xml +++ b/api-admin/pom.xml @@ -368,6 +368,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + diff --git a/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/BussinessChangeTypeController.java b/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/BussinessChangeTypeController.java index 81629a0..2323368 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/BussinessChangeTypeController.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/BussinessChangeTypeController.java @@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import java.util.Date; import java.util.List; @RestController @@ -132,6 +133,9 @@ public class BussinessChangeTypeController { } if (bussinessTypeEntity != null) { bussinessChangeTypeService.updateBusChangeType(bussinessTypeEntity); + BussinessLocalTypeEntity bussinessLocalTypeEntity = bussinessLocalTypeService.findBTByAction(bussinessTypeEntity.getAction()); + bussinessLocalTypeEntity.setUpdateTime(new Date()); + bussinessLocalTypeService.updateBusLocalType(bussinessLocalTypeEntity); } else { ResultVOUtils.error(999, "参数错误"); } diff --git a/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncDownloadService.java b/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncDownloadService.java index 31c66f0..c3e3cb2 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncDownloadService.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncDownloadService.java @@ -199,6 +199,8 @@ public class SpsSyncDownloadService { BussinessLocalTypeService bussinessLocalTypeService; @Resource BussinessOriginTypeService bussinessOriginTypeService; + @Resource + private BussinessChangeTypeService bussinessChangeTypeService; public BaseResponse findBusType(SpsSyncDataRequest spsSyncDataRequest) { @@ -216,14 +218,19 @@ public class SpsSyncDownloadService { BeanUtils.copyProperties(spsSyncDataRequest, bussinessLocalTypeFilterRequest); List bussinessLocalTypeEntities = bussinessLocalTypeService.filterAllList(bussinessLocalTypeFilterRequest); + List allBussinessChanges = new ArrayList<>(); + List spsBusLoclTypeResponses = new ArrayList<>(); bussinessLocalTypeEntities.forEach(bussinessTypeEntity -> { SpsBusLoclTypeResponse busLoclTypeResponse = new SpsBusLoclTypeResponse(); BeanUtils.copyProperties(bussinessTypeEntity, busLoclTypeResponse); spsBusLoclTypeResponses.add(busLoclTypeResponse); - }); + List bussinessChangeTypeEntities = bussinessChangeTypeService.findByAction(bussinessTypeEntity.getAction()); + allBussinessChanges.addAll(bussinessChangeTypeEntities); + }); spsSyncBusResponse.setBussinessLocalTypeEntities(spsBusLoclTypeResponses); + spsSyncBusResponse.setBussinessChangeTypeEntities(allBussinessChanges); } if (syncDataSetEntity.isTypeThird()) { BussinessOriginTypeFilterRequest bussinessOriginTypeFilterRequest = new BussinessOriginTypeFilterRequest(); diff --git a/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncUploadController.java b/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncUploadController.java index f126936..42c8a06 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncUploadController.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/controller/basic/SpsSyncUploadController.java @@ -21,6 +21,7 @@ import com.glxp.sale.admin.res.basic.SpsSyncBusResponse; import com.glxp.sale.admin.res.basic.SpsSyncDataResponse; import com.glxp.sale.admin.res.basic.SpsSyncOrderResponse; import com.glxp.sale.admin.service.basic.BasicUnitMaintainService; +import com.glxp.sale.admin.service.basic.BussinessChangeTypeService; import com.glxp.sale.admin.service.basic.UdiRelevanceService; import com.glxp.sale.admin.service.info.CompanyProductRelevanceService; import com.glxp.sale.admin.service.inout.OrderService; @@ -60,6 +61,8 @@ public class SpsSyncUploadController { WarehouseUserDao warehouseUserDao; @Resource WarehouseBussinessTypeDao warehouseBussinessTypeDao; + @Resource + BussinessChangeTypeService bussinessChangeTypeService; @PostMapping("sps/sync/basic/upload") public BaseResponse findProductInfo(@RequestBody SpsSyncDataResponse syncDataResponse) { @@ -292,16 +295,20 @@ public class SpsSyncUploadController { try { List spsBusLoclTypeResponses = syncDataResponse.getBussinessLocalTypeEntities(); List bussinessLocalTypeEntities = new ArrayList<>(); + BussinessLocalTypeDao mapper = batchSession.getMapper(BussinessLocalTypeDao.class); spsBusLoclTypeResponses.forEach(spsBusLoclTypeResponse -> { BussinessLocalTypeEntity bussinessLocalTypeEntity = new BussinessLocalTypeEntity(); BeanUtils.copyProperties(spsBusLoclTypeResponse, bussinessLocalTypeEntity); - bussinessLocalTypeEntities.add(bussinessLocalTypeEntity); + bussinessLocalTypeEntity.setUpdateTime(null); + bussinessChangeTypeService.deleteByAction(spsBusLoclTypeResponse.getAction()); + mapper.insertBussinessType(bussinessLocalTypeEntity); }); - BussinessLocalTypeDao mapper = batchSession.getMapper(BussinessLocalTypeDao.class); - for (BussinessLocalTypeEntity bussinessTypeEntity : bussinessLocalTypeEntities) { - bussinessTypeEntity.setUpdateTime(null); - mapper.insertBussinessType(bussinessTypeEntity); + List bussinessChangeTypeEntities = syncDataResponse.getBussinessChangeTypeEntities(); + if (CollUtil.isNotEmpty(bussinessChangeTypeEntities)) { + for (BussinessChangeTypeEntity bussinessChangeTypeEntity : bussinessChangeTypeEntities) { + bussinessChangeTypeService.insertBusChangeTypee(bussinessChangeTypeEntity); + } } batchSession.commit(); } catch (Exception e) { diff --git a/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/OrderController.java b/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/OrderController.java index 1c0ae22..aea035a 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/OrderController.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/OrderController.java @@ -364,7 +364,7 @@ public class OrderController { String supplementOrderNo = orderNo; supplementOrder.setOriginUllageSupNo(orderEntity.getId()); supplementOrder.setId(supplementOrderNo); - supplementOrder.setStatus(ConstantStatus.ORDER_STATUS_PROCESS); + supplementOrder.setStatus(ConstantStatus.ORDER_STATUS_ADDITIONAL); supplementOrder.setExportStatus(0); //设置导出状态为未导出 diff --git a/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/StockOrderDetailController.java b/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/StockOrderDetailController.java index 05cb65c..ab2364d 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/StockOrderDetailController.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/controller/inout/StockOrderDetailController.java @@ -1,5 +1,6 @@ package com.glxp.sale.admin.controller.inout; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.github.pagehelper.PageInfo; import com.glxp.sale.admin.annotation.AuthRuleAnnotation; @@ -90,6 +91,19 @@ public class StockOrderDetailController { } List stockOrderDetailEntityList = stockOrderDetailService.filterStockOrderDetail(stockOrderDetailFilterRequest); + +// if (CollUtil.isNotEmpty(stockOrderDetailEntityList)) { +// +// for (StockOrderDetailEntity stockOrderDetailEntity : stockOrderDetailEntityList) { +// UdiRelevanceResponse udiInfoEntity = udiRelevanceService.selectGroupById(stockOrderDetailEntity.getProductId()); +// stockOrderDetailEntity.setAllowNoBatch(udiInfoEntity.isAllowNoBatch()); +// stockOrderDetailEntity.setAllowNoBatch(udiInfoEntity.isAllowNoBatch()); +// stockOrderDetailEntity.setAllowNoBatch(udiInfoEntity.isAllowNoBatch()); +// } +// +// } + + PageInfo pageInfo; pageInfo = new PageInfo<>(stockOrderDetailEntityList); PageSimpleResponse pageSimpleResponse = new PageSimpleResponse<>(); @@ -289,7 +303,7 @@ public class StockOrderDetailController { stockOrderDetailEntity.setYlqxzcrbarmc(udiInfoEntity.getYlqxzcrbarmc()); stockOrderDetailEntity.setZczbhhzbapzbh(udiInfoEntity.getZczbhhzbapzbh()); stockOrderDetailEntity.setAllowNoBatch(udiInfoEntity.isAllowNoBatch()); - if(StrUtil.isNotEmpty(udiInfoEntity.getPrice())){ + if (StrUtil.isNotEmpty(udiInfoEntity.getPrice())) { stockOrderDetailEntity.setPrice(new BigDecimal(udiInfoEntity.getPrice())); } if (stockOrderIdsRequest.getUdiEntity() != null) { diff --git a/api-admin/src/main/java/com/glxp/sale/admin/entity/basic/SpsBusLoclTypeResponse.java b/api-admin/src/main/java/com/glxp/sale/admin/entity/basic/SpsBusLoclTypeResponse.java index 7dbb9fc..d9161f4 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/entity/basic/SpsBusLoclTypeResponse.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/entity/basic/SpsBusLoclTypeResponse.java @@ -27,5 +27,6 @@ public class SpsBusLoclTypeResponse { private String prefix; private String localPrefix; private boolean preIn; + private boolean changeEnable; } diff --git a/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/StockOrderDetailEntity.java b/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/StockOrderDetailEntity.java index f61c8e9..ac08589 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/StockOrderDetailEntity.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/StockOrderDetailEntity.java @@ -36,5 +36,7 @@ public class StockOrderDetailEntity { private String invoiceDate; private String manufactory; private boolean allowNoBatch; + private boolean allowNoExpire; + private boolean allowNoProduct; } diff --git a/api-admin/src/main/java/com/glxp/sale/admin/res/basic/SpsSyncBusResponse.java b/api-admin/src/main/java/com/glxp/sale/admin/res/basic/SpsSyncBusResponse.java index 748d9bb..7f458c7 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/res/basic/SpsSyncBusResponse.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/res/basic/SpsSyncBusResponse.java @@ -1,10 +1,7 @@ package com.glxp.sale.admin.res.basic; import com.glxp.sale.admin.entity.auth.AuthAdmin; -import com.glxp.sale.admin.entity.basic.BussinessLocalTypeEntity; -import com.glxp.sale.admin.entity.basic.BussinessOriginTypeEntity; -import com.glxp.sale.admin.entity.basic.BussinessTypeEntity; -import com.glxp.sale.admin.entity.basic.SpsBusLoclTypeResponse; +import com.glxp.sale.admin.entity.basic.*; import lombok.Data; import java.util.List; @@ -15,6 +12,7 @@ public class SpsSyncBusResponse { private List bussinessTypeEntities; private List bussinessOriginTypeEntities; private List bussinessLocalTypeEntities; + private List bussinessChangeTypeEntities; } diff --git a/api-admin/src/main/java/com/glxp/sale/admin/service/basic/BussinessLocalTypeService.java b/api-admin/src/main/java/com/glxp/sale/admin/service/basic/BussinessLocalTypeService.java index d120ebc..b7e4dbf 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/service/basic/BussinessLocalTypeService.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/service/basic/BussinessLocalTypeService.java @@ -19,6 +19,8 @@ public interface BussinessLocalTypeService { List filterLeftJoin(BussinessLocalTypeFilterRequest bussinessTypeFilterRequest); + BussinessLocalTypeEntity findByAction(String action); + BussinessLocalTypeEntity findBTByAction(String action); BussinessLocalTypeEntity findBTByName(String name); diff --git a/api-admin/src/main/java/com/glxp/sale/admin/service/basic/impl/BussinessLocalTypeServiceImpl.java b/api-admin/src/main/java/com/glxp/sale/admin/service/basic/impl/BussinessLocalTypeServiceImpl.java index ca590b8..8382f0f 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/service/basic/impl/BussinessLocalTypeServiceImpl.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/service/basic/impl/BussinessLocalTypeServiceImpl.java @@ -1,5 +1,6 @@ package com.glxp.sale.admin.service.basic.impl; +import cn.hutool.core.collection.CollUtil; import com.github.pagehelper.PageHelper; import com.glxp.sale.admin.dao.basic.BussinessLocalTypeDao; import com.glxp.sale.admin.entity.basic.BussinessLocalTypeEntity; @@ -75,6 +76,17 @@ public class BussinessLocalTypeServiceImpl implements BussinessLocalTypeService return data; } + @Override + public BussinessLocalTypeEntity findByAction(String action) { + BussinessLocalTypeFilterRequest bussinessLocalTypeFilterRequest = new BussinessLocalTypeFilterRequest(); + bussinessLocalTypeFilterRequest.setAction(action); + List data = bussinessLocalTypeDao.filterAllList(bussinessLocalTypeFilterRequest); + if (CollUtil.isNotEmpty(data)) { + data.get(0); + } + return null; + } + @Override public BussinessLocalTypeEntity findBTByAction(String action) { BussinessLocalTypeFilterRequest bussinessTypeFilterRequest = new BussinessLocalTypeFilterRequest(); diff --git a/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java b/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java index 95a9d2e..ef19194 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java @@ -586,7 +586,7 @@ public class IoTransInoutService { return; } } else if (orderEntity.getFromType().intValue() == ConstantStatus.FROM_UDIWMS) { - if (!bussinessTypeEntity.isSecCheckUdiwms()) { + if (!bussinessTypeEntity.isCheckUdiwms()) { unCheckFinish(orderEntity, warehouseEntityList); return; } diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/FilterUdiUtils.java b/api-admin/src/main/java/com/glxp/sale/admin/util/FilterUdiUtils.java index 142ae30..ec0ba35 100644 --- a/api-admin/src/main/java/com/glxp/sale/admin/util/FilterUdiUtils.java +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/FilterUdiUtils.java @@ -1,9 +1,16 @@ package com.glxp.sale.admin.util; +import cn.hutool.core.util.StrUtil; import com.glxp.sale.admin.entity.basic.UdiInfoEntity; import com.glxp.sale.admin.entity.inout.WarehouseEntity; import com.glxp.sale.admin.entity.udid.UdiEntity; +import com.glxp.sale.admin.util.gs1.AI; +import com.glxp.sale.admin.util.gs1.AIs; +import com.glxp.sale.admin.util.gs1.Gs1128Decoder; +import com.glxp.sale.admin.util.gs1.Gs1128Engine; + +import java.util.Map; /** * @author 彭于晏 @@ -25,7 +32,7 @@ public class FilterUdiUtils { return null; } - public static UdiEntity getGS1Udi(String data) { + public static UdiEntity getGS1UdiOld(String data) { String batchNo = ""; String produceDate = ""; String expireDate = ""; @@ -50,8 +57,8 @@ public class FilterUdiUtils { } else { serialNo = null; } - }else{ - if (last.length() >= 10 && last.substring(8, 10).equals("21")){ + } else { + if (last.length() >= 10 && last.substring(8, 10).equals("21")) { serialNo = last.substring(10); } } @@ -64,8 +71,8 @@ public class FilterUdiUtils { } else { serialNo = null; } - }else { - if (last.length() >= 10 && last.substring(8, 10).equals("21")){ + } else { + if (last.length() >= 10 && last.substring(8, 10).equals("21")) { serialNo = last.substring(10); } } @@ -90,7 +97,7 @@ public class FilterUdiUtils { batchNo = data.substring(34, data.length()); } - }else if (data.length() >= 34 && data.substring(32, 34).equals("21")) { + } else if (data.length() >= 34 && data.substring(32, 34).equals("21")) { serialNo = data.substring(34, data.length()); } } else if (data.length() >= 26 && data.substring(24, 26).equals("10")) { @@ -164,6 +171,32 @@ public class FilterUdiUtils { return udiEntity; } + + public static UdiEntity getGS1Udi(String data) { + Gs1128Engine engine = new Gs1128Engine(); + Gs1128Decoder decoder = engine.decoder(); + Map result = decoder.decode("]C1" + data); + UdiEntity udiEntity = new UdiEntity(); + for (Map.Entry entry : result.entrySet()) { + if (entry.getKey() == AIs.GTIN) { + udiEntity.setUdi(entry.getValue()); + } else if (entry.getKey() == AIs.BATCH_LOT) { + udiEntity.setBatchNo(entry.getValue()); + } else if (entry.getKey() == AIs.EXPIRY) { + udiEntity.setExpireDate(entry.getValue()); + } else if (entry.getKey() == AIs.PROD_DATE) { + udiEntity.setProduceDate(entry.getValue()); + } else if (entry.getKey() == AIs.SERIAL) { + udiEntity.setSerialNo(entry.getValue()); + } + } + if (StrUtil.isEmpty(udiEntity.getUdi())) { + return null; + } else + return udiEntity; + } + + public static UdiEntity getZGCUdi(String data) { String batchNo = ""; String produceDate = ""; diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AI.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AI.java new file mode 100644 index 0000000..af7333f --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AI.java @@ -0,0 +1,14 @@ +package com.glxp.sale.admin.util.gs1; + +/** + * @author guilherme.pacheco + */ +public interface AI { + + String getCode(); + + String getDescription(); + + String getFormat(); + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AIs.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AIs.java new file mode 100644 index 0000000..7f6ca11 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AIs.java @@ -0,0 +1,112 @@ +package com.glxp.sale.admin.util.gs1; + +/** + * @author guilherme.pacheco + */ +public enum AIs implements AI { + + SSCC("00", "Serial Shipping Container Code", "n2+n18"), + GTIN("01", "GTIN-14", "n2+n14"), + CONTENT("02", "Number of containers", "n2+n14"), + BATCH_LOT("10", "Batch Number", "n2+an..20"), + PROD_DATE("11", "Production Date", "n2+n6"), + DUE_DATE("12", "Production Date", "n2+n6"), + PACK_DATE("13", "Packaging Date", "n2+n6"), + BEST_BEFORE("15", "Sell by Date (Quality Control) ", "n2+n6"), + EXPIRY("17", "Expiration Date", "n2+n6"), + VARIANT("20", "Product Variant", "n2+n2"), + SERIAL("21", "Serial Number", "n2+an..20"), + INTERNAL("91", "Company Internal Information", "n2+an..30"), + ADDITIONAL_ID("240", "Additional Product Identification", "n3+an..30"), + CUSTOMER_PART("241", "Customer Part Number", "n3+an..30"), + VARIATION_NUMBER("242", "242 Made-to-Order variation no", "n2+n..30"), + SECONDARY_SERIAL("250", "Secondary Serial Number", "n3+an..30"), + REF_TO_SOURCE("251", "Reference to source entity", "n3+an..30"), + DOC_ID("253", "Global Document Type Identifier", "n3+n13+n..17"), + GLN_EXTENSION("254", "GLN extension component ", "n3+an..20"), + VAR_COUNT("30", "Quantity Each", "n2+n..8"), + NET_WEIGHT("310n", "Product Net Weight in kg", "n4+n6"), + LENGTH("311n", "Product Length/1st Dimension, in meters", "n4+n6"), + WIDTH("312n", "Product Width/Diameter/2nd Dimension, in meters", "n4+n6"), + HEIGHT("313n", "Product Depth/Thickness/3rd Dimension, in meters", "n4+n6"), + AREA("314n", "Product Area, in square meters", "n4+n6"), + NET_VOLUME_LITERS("315n", " Product Volume, in liters", "n4+n6"), + NET_VOLUME_CUBICS("316n", " product Volume, in cubic meters", "n4+n6"), + NET_WEIGHT_POUNDS("320n", "Product Net Weight, in pounds", "n4+n6"), + LENGTH_INCHES("321n", "Product Length/1st Dimension, in inches", "n4+n6"), + LENGTH_PES("322n", "Product Length/1st Dimension, in feet", "n4+n6"), + LENGTH_YARDS("323n", "Product Length/1st Dimension, in yards", "n4+n6"), + WIDTH_INCHES("324n", "Product Width/Diameter/2nd Dimension, in inches", "n4+n6"), + WIDTH_FEET("325n", "Product Width/Diameter/2nd Dimension, in feet", "n4+n6"), + WIDTH_YARDS("326n", "Product Width/Diameter/2nd Dimension, in yards", "n4+n6"), + HEIGHT_INCHES("327n", "Product Depth/Thickness/3rd Dimension, in inches", "n4+n6"), + HEIGHT_FEET("328n", "Product Depth/Thickness/3rd Dimension, in feet", "n4+n6"), + HEIGHT_YARDS("329n", "Product Depth/Thickness/3rd Dimension, in yards", "n4+n6"), + PRODUCT_AREA_INCHES("350n", "Product Area (Square Inches)", "n4+n6"), + PRODUCT_AREA_FEET("351n", "Product Area (Square Feet)", "n4+n6"), + PRODUCT_AREA_YARDS("352n", "Product Area (Square Yards)", "n4+n6"), + CONTAINER_AREA_INCHES("353n", "Container Area (Square Inches) ", "n4+n6"), + CONTAINER_AREA_FEET("354n", "Container Area (Square Feet) ", "n4+n6"), + CONTAINER_AREA_YARDS("355n", "Container Area (Square Yards) ", "n4+n6"), + NET_WEIGHT_OUNCES("356n", "Net Weight (Troy Ounces)", "n4+n6"), + PRODUCT_VOLUME_QUARTS("360n", " Product Volume (Quarts)", "n4+n6"), + PRODUCT_VOLUME_GALLONS("361n", " Product Volume (Gallons)", "n4+n6"), + CONTAINER_VOLUME_QUARTS("362n", " Container Gross Volume (Quarts)", "n4+n6"), + CONTAINER_VOLUME_GALLONS("363n", " Container Gross Volume (Gallons)", "n4+n6"), + PRODUCT_VOLUME_INCHES("364n", " Product Volume (Cubic Inches)", "n4+n6"), + PRODUCT_VOLUME_FEET("365n", " Product Volume (Cubic Feet)", "n4+n6"), + PRODUCT_VOLUME_YARDS("366n", " Product Volume (Cubic Yards)", "n4+n6"), + CONTAINER_VOLUME_INCHES("367n", " Container Gross Volume (Cubic Inches)", "n4+n6"), + CONTAINER_VOLUME_FEET("368n", " Container Gross Volume (Cubic Feet)", "n4+n6"), + CONTAINER_VOLUME_YARDS("369n", " Container Gross Volume (Cubic Yards)", "n4+n6"), + COUNT("37", " Number of Units Contained", "n2+n..8"), + ORDER_NUMBER("400", "Customer Purchase Order Number", "n3+an..30"), + SHIP_TO_DELIVER_TO_LOCATION_CODE("410", "Ship To/Deliver To Location Code (EAN13 or DUNS code)", "n3+n13"), + BILL_TO_INVOICEE_TO_LOCATION_CODE("411", "Bill To/Invoice Location Code (EAN13 or DUNS code)", "n3+n13"), + PURCHASE_FROM_LOCATION_CODE("412", "Purchase From Location Code (EAN13 or DUNS code)", "n3+n13"), + SHIP_TO_DELIVER_TO_POSTALCODE("420", "Ship To/Deliver To Postal Code (Single Postal Authority)", "n3+an..9"), + SHIP_TO_DELIVER_TO_MULTI_POSTALCODE("421", "Ship To/Deliver To Postal Code (Multiple Postal Authority)", + "n3+n3+an..9"), + ORIGIN("422", "Country orign", "n3+n3"), + COUNTRY_INITIAL_PROCESS("423", "County initial processing", "n3+n3+n..12"), + COUNTRY_PROCESS("424", "County processing", "n3+n3"), + COUNTRY_DISASSEMBLY("425", "Country disassembly", "n3+n3"), + COUNTRY_FULL_PROCESS("426", "Country pull processing", "n3+n3"), + ROLL_PRODUCTS("8001", "Roll Products – Width/Length/Core Diameter", "n4+n14"), + ESN("8002", "Electronic Serial Number (ESN) for Cellular Phone", "n4+an..20"), + UPC_EAN_RETURNABLE_ASSET("8003", "UPC/EAN Number and Serial Number of Returnable Asset", "n4+an..30"), + UPC_EAN_SERIAL_IDENTIFICATION("8004", "UPC/EAN Serial Identification", "n4+an..30"), + PRICE_UNIT_MEASURE("8005", "Price per Unit of Measure", "n4+n6"), + ; + + private final String code; + private final String description; + private final String format; + + private AIs(String code, String description, String format) { + this.code = code; + this.description = description; + this.format = format; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getFormat() { + return format; + } + + @Override + public String toString() { + return description; + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AiFactory.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AiFactory.java new file mode 100644 index 0000000..08d0bf8 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/AiFactory.java @@ -0,0 +1,32 @@ +package com.glxp.sale.admin.util.gs1; + +/** + * @author guilherme.pacheco + */ +public final class AiFactory { + + private AiFactory() { + super(); + } + + public static AI create(String code, String description, String format) { + return new AI() { + + @Override + public String getFormat() { + return format; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getCode() { + return code; + } + }; + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Format.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Format.java new file mode 100644 index 0000000..23d3772 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Format.java @@ -0,0 +1,71 @@ +package com.glxp.sale.admin.util.gs1; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; + +/** + * @author guilherme.pacheco + */ +final class Format { + + private static final String JOIN_SYMBOL = "+"; + private final List sessions; + + public Format(List sessions) { + this.sessions = Validate.notEmpty(sessions); + } + + public Format(Session... sessions) { + this(Arrays.asList(sessions)); + } + + public Session getIdentifier() { + return sessions.get(0); + } + + public List getDataSessions() { + return sessions.subList(1, sessions.size()); + } + + @Override + public String toString() { + return sessions.stream().map(String::valueOf).collect(Collectors.joining(JOIN_SYMBOL)); + } + + public boolean isValid(String value) { + if (StringUtils.isBlank(value)) { + return false; + } + if (!validLength(value)) { + return false; + } + return validate(value); + } + + private boolean validate(String value) { + return getDataSessions().stream().allMatch(s -> s.getType().isValid(Gs1128Utils.value(s, value))); + } + + private boolean validLength(String value) { + return isVaried() ? value.length() <= getLength() : value.length() == getLength(); + } + + public int getLength() { + return getDataSessions().stream().mapToInt(Session::getLength).sum(); + } + + public boolean isVaried() { + return getDataSessions().stream().anyMatch(Session::isVaried); + } + + public static Format valueOf(String value) { + String[] split = StringUtils.split(value, JOIN_SYMBOL); + List list = Arrays.stream(split).map(Session::valueOf).collect(Collectors.toList()); + return new Format(list); + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Decoder.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Decoder.java new file mode 100644 index 0000000..eec030d --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Decoder.java @@ -0,0 +1,61 @@ +package com.glxp.sale.admin.util.gs1; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.WeakHashMap; +import java.util.function.Function; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; + +/** + * @author guilherme.pacheco + */ +public final class Gs1128Decoder { + + private final Collection ais; + + Gs1128Decoder(Collection ais) { + this.ais = ais; + } + + public Map decode(final String barcode) { + validateBarcode(barcode); + String barcodeValue = StringUtils.remove(barcode, Gs1128Utils.PREFIX); + return extract(barcodeValue); + } + + private Map extract(String barcode) { + final Iterator iterator = Gs1128Utils.iterator(barcode); + final Map result = new WeakHashMap<>(4); + StringBuilder builder = new StringBuilder(); + while (iterator.hasNext()) { + builder.append(iterator.next()); + Optional> mapAi = mapAi(iterator, builder.toString()); + if (mapAi.isPresent()) { + result.putAll(mapAi.get()); + builder = new StringBuilder(); + } + } + return result; + } + + private Optional> mapAi(Iterator iterator, String builder) { + return ais.stream().filter(v -> v.getCode().equals(builder)).findFirst().map(aiValue(iterator)); + } + + private Function> aiValue(Iterator iterator) { + return ai -> { + String value = Gs1128Utils.value(ai, iterator); + return Map.of(ai, value); + }; + } + + private void validateBarcode(String barcode) { + Validate.notBlank(barcode, "Barcode cannot be blank"); + Validate.isTrue(StringUtils.startsWith(barcode, Gs1128Utils.PREFIX), "Barcode must start with prefix Gs1-128 \"]C1\""); + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Encoder.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Encoder.java new file mode 100644 index 0000000..a595255 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Encoder.java @@ -0,0 +1,33 @@ +package com.glxp.sale.admin.util.gs1; + +import java.util.Collection; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; + +/** + * @author guilherme.pacheco + */ +public final class Gs1128Encoder { + + Gs1128Encoder() { + super(); + } + + public String encode(Collection segments) { + Validate.notEmpty(segments); + String barcode = joinSegments(segments); + return checkBarcode(barcode); + } + + private String checkBarcode(String barcode) { + return StringUtils.removeEnd(barcode, String.valueOf(Gs1128Utils.END_AI_VARIED)); + } + + private String joinSegments(Collection segments) { + String joinValue = segments.stream().map(Segment::encode).collect(Collectors.joining()); + return Gs1128Utils.PREFIX.concat(joinValue); + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Engine.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Engine.java new file mode 100644 index 0000000..1e813c2 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Engine.java @@ -0,0 +1,35 @@ +package com.glxp.sale.admin.util.gs1; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; + +/** + * @author guilherme.pacheco + */ +public final class Gs1128Engine { + + private final Set aisRegistred = new HashSet<>(); + + public Gs1128Engine() { + aisRegistred.addAll(EnumSet.allOf(AIs.class)); + } + + public void registerAi(AI ai) { + aisRegistred.add(ai); + } + + public Set getAisRegistred() { + return Collections.unmodifiableSet(aisRegistred); + } + + public Gs1128Encoder encoder() { + return new Gs1128Encoder(); + } + + public Gs1128Decoder decoder() { + return new Gs1128Decoder(aisRegistred); + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Utils.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Utils.java new file mode 100644 index 0000000..ef33c18 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Gs1128Utils.java @@ -0,0 +1,59 @@ +package com.glxp.sale.admin.util.gs1; + +import java.util.Iterator; + +/** + * @author guilherme.pacheco + */ +final class Gs1128Utils { + + public static final String PREFIX = "]C1"; + public static final char END_AI_VARIED = (char) 29; + + private Gs1128Utils() { + super(); + } + + public static Iterator iterator(String value) { + return value.chars().mapToObj(c -> (char) c).iterator(); + } + + public static String value(AI ai, Iterator iterator) { + Format format = Format.valueOf(ai.getFormat()); + if (format.isVaried()) { + return variedValue(iterator); + } else { + return fixedValue(format.getLength(), iterator); + } + } + + public static String value(Session session, String value) { + Iterator iterator = iterator(value); + if (session.isVaried()) { + return variedValue(iterator); + } else { + return fixedValue(session.getLength(), iterator); + } + } + + private static String fixedValue(int size, Iterator iterator) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < size; i++) { + builder.append(iterator.next()); + } + return builder.toString(); + } + + private static String variedValue(Iterator iterator) { + StringBuilder builder = new StringBuilder(); + while (iterator.hasNext()) { + char value = iterator.next(); + if (value == END_AI_VARIED) { + break; + } + builder.append(value); + } + return builder.toString(); + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Segment.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Segment.java new file mode 100644 index 0000000..2f55f6d --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Segment.java @@ -0,0 +1,35 @@ +package com.glxp.sale.admin.util.gs1; + +import org.apache.commons.lang3.Validate; + +/** + * @author guilherme.pacheco + */ +public final class Segment { + + private final AI ai; + private final String value; + private final Format format; + + public Segment(AI ai, String value) { + this.ai = Validate.notNull(ai, "Invalid AI"); + format = Format.valueOf(ai.getFormat()); + this.value = validateValue(format, value); + } + + private String validateValue(Format format, String value) { + Validate.notBlank(value, "Invalid segment value"); + Validate.notNull(format, "Invalid format"); + Validate.isTrue(format.isValid(value)); + return value; + } + + String encode() { + String codeValue = ai.getCode().concat(value); + if (format.isVaried()) { + return codeValue + Gs1128Utils.END_AI_VARIED; + } + return codeValue; + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Session.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Session.java new file mode 100644 index 0000000..0d0e150 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/Session.java @@ -0,0 +1,69 @@ +package com.glxp.sale.admin.util.gs1; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; + +/** + * @author guilherme.pacheco + */ +final class Session { + + private static final String VARIED_CONSTANT = ".."; + + private final SessionType type; + private final boolean varied; + private final int length; + + public Session(SessionType type, int length, boolean varied) { + this.type = Validate.notNull(type); + Validate.isTrue(length > 0, "Session invalid lenght"); + this.length = length; + this.varied = varied; + } + + public SessionType getType() { + return type; + } + + public int getLength() { + return length; + } + + public boolean isVaried() { + return varied; + } + + public static Session valueOf(String value) { + Validate.notBlank(value, "Session cannot be blank"); + SessionType type = sessionType(value); + String strLength = value.substring(type.length()); + boolean varied = strLength.startsWith(VARIED_CONSTANT); + int length = createLength(strLength, varied); + return new Session(type, length, varied); + } + + private static SessionType sessionType(String value) { + return SessionType.valueByPrefix(value).orElseThrow(() -> new IllegalArgumentException("Invalid session type")); + } + + private static Integer createLength(String strLength, boolean varied) { + try { + if (varied) { + String lengthValue = StringUtils.substringAfter(strLength, VARIED_CONSTANT); + return Integer.parseInt(lengthValue); + } + return Integer.valueOf(strLength); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException(String.format("Invalid length: '%s'", strLength), ex); + } + } + + @Override + public String toString() { + return new StringBuilder(type.getSymbol()) + .append(varied ? VARIED_CONSTANT : StringUtils.EMPTY) + .append(length) + .toString(); + } + +} diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/SessionType.java b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/SessionType.java new file mode 100644 index 0000000..6d22119 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/sale/admin/util/gs1/SessionType.java @@ -0,0 +1,49 @@ +package com.glxp.sale.admin.util.gs1; + +import java.util.EnumSet; +import java.util.Optional; +import java.util.function.Predicate; +import org.apache.commons.lang3.StringUtils; + +/** + * @author guilherme.pacheco + */ +enum SessionType { + + ALPHANUMERIC("an", v -> Character.isAlphabetic(v) || Character.isDigit(v)), + ALPHABETIC("a", v -> Character.isAlphabetic(v)), + NUMERIC("n", v -> Character.isDigit(v)); + + private final String symbol; + private final Predicate validator; + + private SessionType(String symbol, Predicate validator) { + this.symbol = symbol; + this.validator = validator; + } + + public boolean isValid(String value) { + if (StringUtils.isBlank(value)) { + return false; + } + return value.chars().mapToObj(c -> (char) c).allMatch(validator::test); + } + + public String getSymbol() { + return symbol; + } + + public int length() { + return symbol.length(); + } + + public static Optional valueByPrefix(String value) { + if (StringUtils.isBlank(value)) { + return Optional.empty(); + } + return EnumSet.allOf(SessionType.class).stream() + .filter(v -> StringUtils.startsWithIgnoreCase(value, v.symbol)) + .findFirst(); + } + +} diff --git a/api-admin/src/main/resources/mybatis/mapper/inventory/InvPreInProductDetailDao.xml b/api-admin/src/main/resources/mybatis/mapper/inventory/InvPreInProductDetailDao.xml index fe0103e..a762813 100644 --- a/api-admin/src/main/resources/mybatis/mapper/inventory/InvPreInProductDetailDao.xml +++ b/api-admin/src/main/resources/mybatis/mapper/inventory/InvPreInProductDetailDao.xml @@ -221,7 +221,7 @@ AND productIdFk = #{productIdFk} - AND inv_product.batchNo like concat('%',#{batchNo},'%') + AND inv_prein_product_detail.batchNo like concat('%',#{batchNo},'%') AND batchNo is NULL