package com.genpt.nsight.v4.service.impl; import com.genpt.nsight.NSightCache; import com.genpt.nsight.NSightCacheLoader; import com.genpt.nsight.v1.SplunkLogger; import com.genpt.nsight.v1.model.HeaderRequest; import com.genpt.nsight.v1.model.Site; import com.genpt.nsight.v1.model.*; import com.genpt.nsight.v1.model.dto.SiteDTO; import com.genpt.nsight.v1.model.dto.SiteRelationDTO; import com.genpt.nsight.v4.AvailabilityServiceContextV4; import com.genpt.nsight.v4.model.Action; import com.genpt.nsight.v4.model.ActionRequest; import com.genpt.nsight.v4.model.DetailResponse; import com.genpt.nsight.v4.model.InventoryRelationshipsRequested; import com.genpt.nsight.v4.model.Part; import com.genpt.nsight.v4.model.ProductAvailabilityResponse; import com.genpt.nsight.v4.model.majoraccounts.*; import com.genpt.nsight.v4.service.LocateProductServiceV4; import com.genpt.nsight.v4.service.ProductAvailabilityDetailServiceV4; import com.genpt.nsight.v4.service.ProductTranslateService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @Service("LocateProductServiceV4") public class LocateProductServiceV4Impl implements LocateProductServiceV4 { @Autowired NSightCache nSightCache; @Autowired NSightCacheLoader nSightCacheLoader; private static final Logger LOGGER = LoggerFactory.getLogger(LocateProductServiceV4Impl.class); @Autowired ProductTranslateService productTranslateService; private ProductAvailabilityDetailServiceV4 productAvailabilityDetailServiceV4; private String[] DayOfWeekColNames = new String[]{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; @Autowired public void setProductAvailabilityDetailServiceV4(ProductAvailabilityDetailServiceV4 productAvailabilityDetailServiceV4) { this.productAvailabilityDetailServiceV4 = productAvailabilityDetailServiceV4; } @Override public AvailabilityServiceContextV4 initializeContext(AvailabilityServiceContextV4 availabilityServiceContextV4, LocateProductRequest request, boolean translatePart){ Requestor requestor = new Requestor(); requestor.setRequestorApplication(request.getHeaderRequest().getRequestor().getRequestorApplication()); requestor.setRequestorType(request.getHeaderRequest().getRequestor().getRequestorType()); RequestorIdentifier requestorIdentifier = new RequestorIdentifier(); requestorIdentifier.setType(request.getHeaderRequest().getRequestor().getRequestorIdentifier().getType()); requestorIdentifier.setValue(request.getHeaderRequest().getRequestor().getRequestorIdentifier().getValue()); requestor.setRequestorIdentifier(requestorIdentifier); Responder responder = new Responder(); responder.setResponderApplication(request.getHeaderRequest().getResponder().getResponderApplication()); if(request.getDetailRequest().getCustomer() != null && request.getDetailRequest().getCustomer().getIdentifier()!=null && request.getDetailRequest().getCustomer().getIdentifier().getType() != null && request.getDetailRequest().getCustomer().getIdentifier().getType().equalsIgnoreCase("Account Password") && request.getDetailRequest().getCustomer().getIdentifier().getValue() !=null && !request.getDetailRequest().getCustomer().getIdentifier().getValue().isEmpty()) { Security security = new Security(); UserCredentials userCredentials = new UserCredentials(); userCredentials.setPassword(request.getDetailRequest().getCustomer().getIdentifier().getValue()); userCredentials.setUserName("POS"); security.setUserCredentials(userCredentials); responder.setSecurity(security); } HeaderRequest headerRequest = new HeaderRequest(); headerRequest.setRequestor(requestor); headerRequest.setResponder(responder); headerRequest.setCorrelationId(request.getHeaderRequest().getCorrelationId()); //need to get the country code of the calling store if(request.getHeaderRequest().getCountryCode()==null) headerRequest.setCountryCode(nSightCache.getAlpha2CountryCode(request.getHeaderRequest().getRequestor().getRequestorIdentifier().getValue())); headerRequest.setCountryCode(request.getHeaderRequest().getCountryCode()); headerRequest.setLanguageCode(request.getHeaderRequest().getLanguageCode()); headerRequest.setTimestamp(request.getHeaderRequest().getTimestamp()); ActionRequest actionRequest = new ActionRequest(); Action action = new Action(); action.setNeedProductQuantity(request.getAction().getNeedAvailability()); action.setNeedCityStateInfo(true); action.setNeedPricing(request.getAction().getNeedPricing()); action.setNeedSuperSedes(request.getAction().getNeedSupersedes()); action.setNeedDeliveryEstimateCutOffTimes(request.getAction().getNeedDeliveryInformation()); if(request.getAction().getNeedDeliveryInformation()) availabilityServiceContextV4.setFreePaid(true); String callingStoreSIteID = nSightCache.getAliasToSiteIdMap().get(requestor.getRequestorIdentifier().getType() + "|" + requestor.getRequestorIdentifier().getValue()); actionRequest.setAction(action); com.genpt.nsight.v4.model.DetailRequest detailRequest = new com.genpt.nsight.v4.model.DetailRequest(); InventoryRelationshipsRequested inventoryRelationshipsRequested = new InventoryRelationshipsRequested(); inventoryRelationshipsRequested.setLocalStore(true); inventoryRelationshipsRequested.setServingDC(true); if(request.getAction().getNeedAvailability()) { inventoryRelationshipsRequested.setAllOtherDCs(true); inventoryRelationshipsRequested.setAllSuppliers(true); } else{ inventoryRelationshipsRequested.setAllOtherDCs(false); inventoryRelationshipsRequested.setAllSuppliers(false); } if (callingStoreSIteID!=null){ OtherRelationShips otherRelationShips = new OtherRelationShips(); otherRelationShips.setRelationshipName(new ArrayList<>()); otherRelationShips.getRelationshipName().add("Store Console Inventory Friend"); inventoryRelationshipsRequested.setOtherRelationShips(otherRelationShips); } detailRequest.setInventoryRelationshipsRequested(inventoryRelationshipsRequested); Set parts = new HashSet<>(); //before we create the partlist we would need to run through a translation if required ProductTranslateResponse productTranslateResponse = null; if (translatePart){ productTranslateResponse = invokePartTranslate(availabilityServiceContextV4, request, headerRequest, parts); } //default to this list of parts if we dont get any response from ibiz //or run into an error in that if (productTranslateResponse ==null || parts.size()==0) { for (Product product : request.getDetailRequest().getProductList()) { Part nsightPart = new Part(); nsightPart.setLineAbbrev(product.getLineAbbrev()); nsightPart.setPartNumber(product.getPartNumber()); if (product.getQtyNeeded() != null) nsightPart.setQuantityRequested(product.getQtyNeeded()); parts.add(nsightPart); } } detailRequest.setParts(parts); com.genpt.nsight.v4.model.ProductAvailabilityRequest productAvailabilityRequest = new com.genpt.nsight.v4.model.ProductAvailabilityRequest(); productAvailabilityRequest.setActionRequest(actionRequest); productAvailabilityRequest.setDetailRequest(detailRequest); productAvailabilityRequest.setHeaderRequest(headerRequest); availabilityServiceContextV4.setRequest(productAvailabilityRequest); return availabilityServiceContextV4; } private ProductTranslateResponse invokePartTranslate(AvailabilityServiceContextV4 availabilityServiceContextV4, LocateProductRequest request, HeaderRequest headerRequest, Set parts){ ProductTranslateRequest productTranslateRequest = new ProductTranslateRequest(); productTranslateRequest.setHeaderRequest(new com.genpt.nsight.v4.model.majoraccounts.HeaderRequest()); productTranslateRequest.getHeaderRequest().setRequestID(headerRequest.getRequestID()); productTranslateRequest.getHeaderRequest().setRequestor(headerRequest.getRequestor()); productTranslateRequest.getHeaderRequest().setCorrelationId(headerRequest.getCorrelationId()); productTranslateRequest.getHeaderRequest().setResponder(headerRequest.getResponder()); productTranslateRequest.getHeaderRequest().setCountryCode(headerRequest.getCountryCode()); productTranslateRequest.getHeaderRequest().setLanguageCode(headerRequest.getLanguageCode()); productTranslateRequest.getHeaderRequest().setTimestamp(Long.parseLong(headerRequest.getTimestamp())); productTranslateRequest.setDetailRequest(new ProductTranslateDetailRequest()); productTranslateRequest.getDetailRequest().setParts(new HashSet<>()); for ( Product product: request.getDetailRequest().getProductList()) { ProductTranslatePart productTranslatePart= new ProductTranslatePart(); productTranslatePart.setPartNumber(product.getPartNumber()); productTranslatePart.setLineAbbrev(product.getLineAbbrev()); productTranslateRequest.getDetailRequest().getParts().add(productTranslatePart); } ProductTranslateResponse productTranslateResponse =productTranslateService.translateProducts(productTranslateRequest); if (productTranslateResponse != null && productTranslateResponse.getTracking().getIsSuccess() && productTranslateResponse.getDetailResponse().getParts().size() >0) { //create a hashmap for storing the translated parts HashMap productTranslatePartHashMap = new HashMap<>(); for (ProductTranslatePart productTranslatePart : productTranslateResponse.getDetailResponse().getParts()) { productTranslatePartHashMap.put(productTranslatePart.getLineAbbrev() + "-" + productTranslatePart.getPartNumber(), productTranslatePart); } //now create the part list to be sent downstream for (Product product : request.getDetailRequest().getProductList()) { Part nsightPart = new Part(); ProductTranslatePart productTranslatePart = productTranslatePartHashMap.get(product.getLineAbbrev() + "-" + product.getPartNumber()); if (productTranslatePart != null && productTranslatePart.getTranslatedLineAbbrev() != null && productTranslatePart.getTranslatedLineAbbrev().trim().length() != 0 && productTranslatePart.getTranslatedPartNumber() != null && productTranslatePart.getTranslatedPartNumber().trim().length() != 0){ nsightPart.setLineAbbrev(productTranslatePart.getTranslatedLineAbbrev()); nsightPart.setPartNumber(productTranslatePart.getTranslatedPartNumber()); //add it to a map so we can translate back to original part availabilityServiceContextV4.getTranslatedPartMap().put(productTranslatePart.getTranslatedLineAbbrev()+"-"+productTranslatePart.getTranslatedPartNumber(),productTranslatePart.getLineAbbrev()+"-"+productTranslatePart.getPartNumber()); }else{ nsightPart.setLineAbbrev(product.getLineAbbrev()); nsightPart.setPartNumber(product.getPartNumber()); } if (product.getQtyNeeded() != null) nsightPart.setQuantityRequested(product.getQtyNeeded()); parts.add(nsightPart); } } return productTranslateResponse; } @Override public LocateProductResponse getProductAvailability(AvailabilityServiceContextV4 availabilityServiceContextV4) { SplunkLogger splunkLogger = new SplunkLogger(availabilityServiceContextV4.getRequestMajorAccounts().getHeaderRequest()); LOGGER.debug(splunkLogger.toString()+ " request payload{} ",availabilityServiceContextV4.getRequest().toString() ); long startTime = System.currentTimeMillis(); String siteId = nSightCache.getAliasToSiteIdMap().get(availabilityServiceContextV4.getRequest().getHeaderRequest().getRequestor().getRequestorIdentifier().getType() + "|" + availabilityServiceContextV4.getRequest().getHeaderRequest().getRequestor().getRequestorIdentifier().getValue()); SiteDTO callingStoreDTO = nSightCache.getSiteIdToSiteMap().get(siteId); if(callingStoreDTO.getTimeZone() == null || callingStoreDTO.getTimeZone().equalsIgnoreCase("NAN")) { LocateProductResponse locateProductResponse = availabilityServiceContextV4.getLocateProductResponseTemplate(availabilityServiceContextV4); Tracking tracking = new Tracking(); tracking.setIsSuccess(Boolean.FALSE); tracking.setFault(Fault.builder().code("3005").message("Invalid Data - Timezone is null in Nsight for requesting site").build()); LOGGER.error(splunkLogger.toString() + " Invalid Data - Timezone is null in Nsight for requesting site: 3005"); locateProductResponse.setTracking(tracking); return locateProductResponse; } String storeTZ = callingStoreDTO.getTimeZone(); //ZoneOffset zoneOffSet = ZoneOffset.of(storeTZ); ZoneOffset zoneOffSet = ZoneOffset.ofTotalSeconds((int) (Float.parseFloat(storeTZ) * 60 * 60)); ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")); OffsetDateTime localTime = OffsetDateTime.now(zoneOffSet); boolean isStoresUTCNextDay = false; if (now.getDayOfMonth() != localTime.getDayOfMonth()) { isStoresUTCNextDay = true; // the UTC has passed into next day. need to get back a day into the stores date now = now.minus(1,ChronoUnit.DAYS); } /* if(availabilityServiceContextV4.getTimeOfDay() == 0L) { availabilityServiceContextV4.setDayOfWeekLocal(localTime.getDayOfWeek().getValue() - 1); availabilityServiceContextV4.setTimeOfDay(getMillisFromMidnight(now)); }*/ final ZonedDateTime beginningOfDay = now.truncatedTo(ChronoUnit.DAYS); availabilityServiceContextV4.setDayOfWeekLocalStore(callingStoreDTO); //Get the detail response first ProductAvailabilityResponse productAvailabilityResponse = productAvailabilityDetailServiceV4.getProductAvailability(availabilityServiceContextV4, false); long buildResponseStartTime = System.currentTimeMillis();//start time for aggregate time taken DetailResponse detailResponse = productAvailabilityResponse.getDetailResponse();//start creating the response LocateProductResponse locateProductResponse = new LocateProductResponse(); locateProductResponse.setHeaderResponse(productAvailabilityResponse.getHeaderResponse()); locateProductResponse.getHeaderResponse().setCorrelationId(productAvailabilityResponse.getCorrelationId()); locateProductResponse.setTracking(productAvailabilityResponse.getTracking()); com.genpt.nsight.v4.model.majoraccounts.DetailResponse detailResponseMajorAccounts = new com.genpt.nsight.v4.model.majoraccounts.DetailResponse(); List products = new ArrayList(); List fulfillments = new ArrayList(); Map fulfillmentMap = new HashMap<>(); Set fulfillmentIdentifiers = new HashSet(); boolean isRequestingSiteMainCounter = isSiteMainCounter(siteId); //iterate over all the parts requested if(detailResponse.getParts()!=null) { detailResponse.getParts().forEach(part -> { if (true) { int index = detailResponse.getParts().indexOf(part); List partnerStoreQty = new LinkedList(); List localNapaNetworkQty = new LinkedList(); List nationalNapaNetworkQty = new LinkedList(); Product product = new Product(); String originalPart = availabilityServiceContextV4.getTranslatedPartMap().get(part.getLineAbbrev()+"-"+part.getPartNumber()); if (originalPart!=null && originalPart.indexOf('-') != -1){ String[] partlineAndNumber = originalPart.split("-"); product.setLineAbbrev(partlineAndNumber[0]); product.setPartNumber(partlineAndNumber[1]); }else { product.setLineAbbrev(part.getLineAbbrev()); product.setPartNumber(part.getPartNumber()); } availabilityServiceContextV4.getRequest().getDetailRequest().getParts().forEach(requestPart ->{ if(part.getLineAbbrev().equalsIgnoreCase(requestPart.getLineAbbrev()) && part.getPartNumber().equalsIgnoreCase(requestPart.getPartNumber())) product.setQtyNeeded(requestPart.getQuantityRequested()); }); //Set Virtual Kit components of product if(part.getProductKit()!= null && part.getProductKit().getKitComponents().size()>0){ List kits = new ArrayList(); part.getProductKit().getKitComponents().forEach(kitComponent -> { Kit kit = new Kit(); kit.setComponentLineAbbrev(kitComponent.getLineAbbrev()); kit.setComponentPartNumber(kitComponent.getPartNumber()); kit.setComponentQtyRequired(kitComponent.getQuantityRequired()); kits.add(kit); }); product.setKits(kits); } //Set Product level Tracking object if (part.getTracking() != null) { Tracking tracking = addTracking(part.getTracking()); product.setTracking(tracking); } // Set Pricing object of product if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedPricing() && part.getPrice() != null) { if(part.getPrice().getTracking()!=null && !part.getPrice().getTracking().getIsSuccess()){ Tracking tracking = addTracking(part.getPrice().getTracking()); product.setTracking(tracking); } else { Pricing pricing = new Pricing(); pricing.setCustomerPrice(part.getPrice().getCustomerPrice()); pricing.setListPrice(part.getPrice().getListPrice()); pricing.setCustomerCorePrice(part.getPrice().getCoreCustomerPrice()); pricing.setListCorePrice(part.getPrice().getCoreListPrice()); List miscCharges = new ArrayList(); if (part.getPrice().getMiscCharges() != null && part.getPrice().getMiscCharges().size() > 0) { part.getPrice().getMiscCharges().forEach(miscCharge -> { com.genpt.nsight.v4.model.majoraccounts.MiscCharge miscCharge1 = new com.genpt.nsight.v4.model.majoraccounts.MiscCharge(); miscCharge1.setMiscChargeAmt(miscCharge.getMiscCustomerPrice()); miscCharge1.setMiscChargeCode(miscCharge.getMiscType()); miscCharges.add(miscCharge1); }); } if (miscCharges.size() > 0) pricing.setMiscCharges(miscCharges); product.setPricing(pricing); } } List details = new ArrayList(); Map detailMap = new HashMap<>(); String primaryDCSiteId = nSightCache.getSiteIdToSiteMap().get(siteId).getPrimaryDCSiteId(); Aggregate aggregate = new Aggregate(); // One may think this is duplicate but this set is maintained to avoid duplicate Detail objects for the same part Set detailSiteIdentifiers = new HashSet(); if (part.getSites() != null) { part.getSites().forEach(site -> {// now iterate across all the sites for the part if (site.getPartAttributes() != null) { product.setPartDescription(site.getPartAttributes().getPartDescription()); } // Set supersedes for product in response if request has need supersedes set to true if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedSuperSedes() && site.getSuperSedes() != null && site.getSuperSedes().size() > 0) { List supersedes = new ArrayList(); site.getSuperSedes().forEach(superSede -> { Supersede supersede = new Supersede(); supersede.setLineAbbrev(superSede.getLineAbbrev()); supersede.setPartNumber(superSede.getPartNumber()); supersede.setType(superSede.getSuperSedeType()); supersedes.add(supersede); }); product.setSupersede(supersedes); } // Iterate through site relationships to add fulfillment location details and to add qty for each fulfillment location if request has need availability set to true // iterating through relationships to categorize partner store, localNapaNetwork and nationalNapaNetwork if(site.getSiteRelationships()!=null) { site.getSiteRelationships().forEach(siteRelationship -> { Boolean hasfulFillment = false; Boolean hasDetail = false; BigDecimal zero = new BigDecimal("0"); String displayName= getDisplayName(site.getSiteId()); if (fulfillmentIdentifiers.size() > 0 && fulfillmentIdentifiers.contains(site.getSiteId())) hasfulFillment = true; if (detailSiteIdentifiers.size() > 0 && detailSiteIdentifiers.contains(site.getSiteId())) hasDetail = true; //Condition to add Primary DC qty to localStore if (siteRelationship.getSiteRelationshipType().equalsIgnoreCase("LocalStore")) { if (!hasfulFillment) { if(site.getPartAttributes() != null && site.getPartAttributes().getUnitOfMeasure()!=null && !site.getPartAttributes().getUnitOfMeasure().trim().isEmpty()) product.setUnitOfMeasure(site.getPartAttributes().getUnitOfMeasure()); else product.setUnitOfMeasure("EA"); if (site.getQuantity() != null && site.getQuantity().getIncrementalSellQuantity()!=null) product.setIncrementalSellQty(site.getQuantity().getIncrementalSellQuantity()); if (site.getQuantity() != null && site.getQuantity().getMinimumSellQuantity()!=null) product.setMinSellQty(site.getQuantity().getMinimumSellQuantity()); Fulfillment fulfillment = new Fulfillment(); fulfillment.setFulfillmentIdentifier(UUID.fromString(site.getSiteId())); fulfillment.setType("Local Store"); if(siteRelationship.getSiteRelationshipRank()!=null) fulfillment.setRank(siteRelationship.getSiteRelationshipRank()); fulfillment.setCommonIdentifier(getSiteValue(site.getSiteIdentifiers(), "9 Digit Store Number")); if(displayName!="") fulfillment.setAlternateIdentifier(displayName); fulfillment.setCity(site.getSiteCity()); fulfillment.setState(site.getSiteState()); //set fulfillment country and zip code SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()); if (siteDTO.getZipCode() != null) fulfillment.setZipcode(siteDTO.getZipCode()); else fulfillment.setZipcode("Not Available"); if (siteDTO.getCountry() != null) fulfillment.setCountry(siteDTO.getCountry()); else fulfillment.setCountry("Not Available"); fulfillment.setAddress1("-"); fulfillment.setAddress2(""); if (availabilityServiceContextV4.getRequestMajorAccounts().getAction().getNeedDeliveryInformation()) { Delivery delivery = addDeliveryInformation(site, availabilityServiceContextV4, beginningOfDay); fulfillment.setDelivery(delivery); } fulfillmentMap.put(site.getSiteId(),fulfillment); } if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null && !hasDetail) { Detail detail = new Detail(); detail.setQty(site.getQuantity().getAvailable().compareTo(zero)<0 ? zero : site.getQuantity().getAvailable()); detail.setFulfillmentIdentifier(site.getSiteId()); detailMap.put(site.getSiteId(),detail); } } else if (siteRelationship.getSiteRelationshipType().equalsIgnoreCase("Primary DC")) { // Don't add fulfillment asection for primary DC if store is main counter if (!hasfulFillment && !isRequestingSiteMainCounter) { Fulfillment fulfillment = new Fulfillment(); fulfillment.setFulfillmentIdentifier(UUID.fromString(site.getSiteId())); fulfillment.setType("Serving DC"); int rank = getSiteRelationshipRank(siteId, site.getSiteId()); if (rank != 0) fulfillment.setRank(rank); fulfillment.setCommonIdentifier(getSiteValue(site.getSiteIdentifiers(), "DC Abbreviation Code")); if (displayName != "") fulfillment.setAlternateIdentifier(displayName); fulfillment.setCity(site.getSiteCity()); fulfillment.setState(site.getSiteState()); //set fulfillment country and zip code SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()); if (siteDTO.getZipCode() != null) fulfillment.setZipcode(siteDTO.getZipCode()); else fulfillment.setZipcode("Not Available"); if (siteDTO.getCountry() != null) fulfillment.setCountry(siteDTO.getCountry()); else fulfillment.setCountry("Not Available"); fulfillment.setAddress1("-"); fulfillment.setAddress2(""); if (availabilityServiceContextV4.getRequestMajorAccounts().getAction().getNeedDeliveryInformation()) { Delivery delivery = addDeliveryInformation(site, availabilityServiceContextV4, beginningOfDay); fulfillment.setDelivery(delivery); } fulfillmentMap.put(site.getSiteId(),fulfillment); } if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null && !hasDetail) { Detail detail = new Detail(); detail.setQty(site.getQuantity().getAvailable()); detail.setFulfillmentIdentifier(site.getSiteId()); detailMap.put(site.getSiteId(),detail); } }else if (siteRelationship.getSiteRelationshipType().equalsIgnoreCase("Store Console Inventory Friend") && site.getSiteType().equalsIgnoreCase("Store")) { if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null) partnerStoreQty.add(site.getQuantity().getAvailable().compareTo(zero)<0 ? zero : site.getQuantity().getAvailable()); if (!hasfulFillment) { Fulfillment fulfillment = new Fulfillment(); fulfillment.setFulfillmentIdentifier(UUID.fromString(site.getSiteId())); fulfillment.setType("Partner Store"); if(siteRelationship.getSiteRelationshipRank()!=null) fulfillment.setRank(siteRelationship.getSiteRelationshipRank()); fulfillment.setCommonIdentifier(getSiteValue(site.getSiteIdentifiers(), "9 Digit Store Number")); if(displayName!="") fulfillment.setAlternateIdentifier(displayName); fulfillment.setCity(site.getSiteCity()); fulfillment.setState(site.getSiteState()); //set fulfillment country and zip code SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()); if (siteDTO.getZipCode() != null) fulfillment.setZipcode(siteDTO.getZipCode()); else fulfillment.setZipcode("Not Available"); if (siteDTO.getCountry() != null) fulfillment.setCountry(siteDTO.getCountry()); else fulfillment.setCountry("Not Available"); fulfillment.setAddress1("-"); fulfillment.setAddress2(""); if(availabilityServiceContextV4.getRequestMajorAccounts().getAction().getNeedDeliveryInformation()){ Delivery delivery = addDeliveryInformation(site, availabilityServiceContextV4, beginningOfDay); fulfillment.setDelivery(delivery); } fulfillmentMap.put(site.getSiteId(),fulfillment); } if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null && !hasDetail) { Detail detail = new Detail(); detail.setQty(site.getQuantity().getAvailable().compareTo(zero)<0 ? zero : site.getQuantity().getAvailable()); detail.setFulfillmentIdentifier(site.getSiteId()); detailMap.put(site.getSiteId(),detail); } } else if (siteRelationship.getSiteRelationshipType().equalsIgnoreCase("Store Console Inventory Friend") && ((site.getSiteType().equalsIgnoreCase("DC") && !site.getSiteId().equalsIgnoreCase(callingStoreDTO.getPrimaryDCSiteId())) || site.getSiteType().equalsIgnoreCase("Supplier"))) { if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null && !hasDetail) { Detail detail = new Detail(); detail.setQty(site.getQuantity().getAvailable().compareTo(zero)<0 ? zero : site.getQuantity().getAvailable()); detail.setFulfillmentIdentifier(site.getSiteId()); detailMap.put(site.getSiteId(),detail); } if (site.getSiteType().equalsIgnoreCase("DC")) { if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null) localNapaNetworkQty.add(site.getQuantity().getAvailable().compareTo(zero)<0 ? zero : site.getQuantity().getAvailable()); if (!hasfulFillment) { Fulfillment fulfillment = new Fulfillment(); fulfillment.setType("Local NAPA Network"); if(siteRelationship.getSiteRelationshipRank()!=null) fulfillment.setRank(siteRelationship.getSiteRelationshipRank()); fulfillment.setFulfillmentIdentifier(UUID.fromString(site.getSiteId())); fulfillment.setCommonIdentifier(getSiteValue(site.getSiteIdentifiers(), "DC Abbreviation Code")); if(displayName!="") fulfillment.setAlternateIdentifier(displayName); fulfillment.setCity(site.getSiteCity()); fulfillment.setState(site.getSiteState()); //set fulfillment country and zip code SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()); if (siteDTO.getZipCode() != null) fulfillment.setZipcode(siteDTO.getZipCode()); else fulfillment.setZipcode("Not Available"); if (siteDTO.getCountry() != null) fulfillment.setCountry(siteDTO.getCountry()); else fulfillment.setCountry("Not Available"); fulfillment.setAddress1("-"); fulfillment.setAddress2(""); if(availabilityServiceContextV4.getRequestMajorAccounts().getAction().getNeedDeliveryInformation()){ Delivery delivery = addDeliveryInformation(site, availabilityServiceContextV4, beginningOfDay); fulfillment.setDelivery(delivery); } fulfillmentMap.put(site.getSiteId(),fulfillment); } } else if (site.getSiteType().equalsIgnoreCase("Supplier")) { if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null) localNapaNetworkQty.add(site.getQuantity().getAvailable()); if (!hasfulFillment) { Fulfillment fulfillment = new Fulfillment(); fulfillment.setType("Local NAPA Network"); if(siteRelationship.getSiteRelationshipRank()!=null) fulfillment.setRank(siteRelationship.getSiteRelationshipRank()); fulfillment.setFulfillmentIdentifier(UUID.fromString(site.getSiteId())); fulfillment.setCommonIdentifier(getSiteValue(site.getSiteIdentifiers(), "Supplier Abbreviation Location")); if(displayName!="") fulfillment.setAlternateIdentifier(displayName); fulfillment.setCity(site.getSiteCity()); fulfillment.setState(site.getSiteState()); //set fulfillment country and zip code SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()); if (siteDTO.getZipCode() != null) fulfillment.setZipcode(siteDTO.getZipCode()); else fulfillment.setZipcode("Not Available"); if (siteDTO.getCountry() != null) fulfillment.setCountry(siteDTO.getCountry()); else fulfillment.setCountry("Not Available"); fulfillment.setAddress1("-"); fulfillment.setAddress2(""); if(availabilityServiceContextV4.getRequestMajorAccounts().getAction().getNeedDeliveryInformation()){ Delivery delivery = addDeliveryInformation(site, availabilityServiceContextV4, beginningOfDay); fulfillment.setDelivery(delivery); } fulfillmentMap.put(site.getSiteId(),fulfillment); } } } else if (siteRelationship.getSiteRelationshipType().equalsIgnoreCase("AllOtherDCs") || siteRelationship.getSiteRelationshipType().equalsIgnoreCase("AllSuppliers")) { if (availabilityServiceContextV4.getRequest().getActionRequest().getAction().getNeedProductQuantity() && site.getQuantity() != null) nationalNapaNetworkQty.add(site.getQuantity().getAvailable().compareTo(zero)<0 ? zero : site.getQuantity().getAvailable()); } fulfillmentIdentifiers.add(site.getSiteId()); detailSiteIdentifiers.add(site.getSiteId()); }); } //Set Aggregated quantity fields aggregate.setPartnerStoreQty(partnerStoreQty.stream().reduce(BigDecimal.ZERO, BigDecimal::add)); aggregate.setLocalNapaNetworkQty(localNapaNetworkQty.stream().reduce(BigDecimal.ZERO, BigDecimal::add)); aggregate.setNationalNapaNetworkQty(nationalNapaNetworkQty.stream().reduce(BigDecimal.ZERO, BigDecimal::add)); });//for each site within a part }//valid sites array present Availability availability = new Availability(); //Add PrimaryDCQty to localStoreQty and remove primaryDC detail object if store is mainCounter if(isRequestingSiteMainCounter) { Detail detail = detailMap.get(siteId); if(detail!=null) { BigDecimal localStoreQty = detail.getQty(); if (primaryDCSiteId != "") { Detail primaryDCDetail = detailMap.get(primaryDCSiteId); if(primaryDCDetail!=null) { BigDecimal primaryDCStoreQty = primaryDCDetail.getQty(); BigDecimal qty = localStoreQty.add(primaryDCStoreQty); detail.setQty(qty); detailMap.remove(primaryDCSiteId); } } } //Populate localStore detail object with PrimaryDCQty as localStoreQty when localStore site is not found for part and store is main counter else{ if (primaryDCSiteId != "") { Detail primaryDCDetail = detailMap.get(primaryDCSiteId); if(primaryDCDetail!=null) { BigDecimal primaryDCStoreQty = primaryDCDetail.getQty(); Detail localStoreDetail = new Detail(); localStoreDetail.setFulfillmentIdentifier(siteId); localStoreDetail.setQty(primaryDCStoreQty); detailMap.put(siteId, localStoreDetail); detailMap.remove(primaryDCSiteId); if (fulfillmentIdentifiers.size() > 0 && fulfillmentIdentifiers.contains(siteId)){ Fulfillment fulfillment = createLocalStoreFulfillment(siteId, availabilityServiceContextV4.getRequestMajorAccounts().getAction().getNeedDeliveryInformation() ); fulfillmentMap.put(siteId,fulfillment); } } } } } details = detailMap.values().stream().collect(Collectors.toList()); availability.setDetails(details); availability.setAggregate(aggregate); // If inventory not found for Local Store then set default unitOfMeasure if(product.getUnitOfMeasure()==null) product.setUnitOfMeasure("EA"); product.setAvailability(availability); products.add(product); } }); } detailResponseMajorAccounts.setProducts(products); fulfillments = fulfillmentMap.values().stream().collect(Collectors.toList()); detailResponseMajorAccounts.setFulfillments(fulfillments); locateProductResponse.setDetailResponse(detailResponseMajorAccounts); LOGGER.debug(splunkLogger.toString() + " Time taken to build response = {} ", (System.currentTimeMillis() - buildResponseStartTime)); LOGGER.info(splunkLogger.toString() + " Total time within Locate Product MicroService = {}", System.currentTimeMillis() - startTime); return locateProductResponse; } public String getSiteValue(List siteIdentifiers, String storeAlias){ String siteValue=""; SiteIdentifier s = siteIdentifiers.stream().filter(siteIdentifier -> siteIdentifier.getName().equalsIgnoreCase(storeAlias)).findFirst().orElse(null); if(s!=null) siteValue =s.getValue(); return siteValue; } protected long getMillisFromMidnight(ZonedDateTime now) { ZonedDateTime midnight = now.truncatedTo(ChronoUnit.DAYS); Duration duration = Duration.between(midnight, now); TimeZone tz = TimeZone.getDefault(); boolean isOn = ZoneId.of(tz.getID()) // Represent a specific time zone, the history of past, present, and future changes to the offset-from-UTC used by the people of a certain region. .getRules() // Obtain the list of those changes in offset. .isDaylightSavings( // See if the people of this region are observing Daylight Saving Time at a specific moment. Instant.now() // Specify the moment. Here we capture the current moment at runtime. ) ; // Returns a boolean. if (isOn) return duration.getSeconds() * 1000L +tz.getDSTSavings(); else return duration.getSeconds() * 1000L ; } private String getDateTime(int days, long timeInMills, ZonedDateTime now, boolean nextDay) { long minutes = timeInMills / (60 * 1000L); String dateTime = null; try { if (nextDay) dateTime = DateTimeFormatter.ISO_INSTANT.format(now.plusDays(days+1).plusMinutes(minutes)); else dateTime = DateTimeFormatter.ISO_INSTANT.format(now.plusDays(days).plusMinutes(minutes)); } catch (Exception e) { e.printStackTrace(); } return dateTime; } private Delivery addDeliveryInformation(Site site, AvailabilityServiceContextV4 availabilityServiceContextV4, ZonedDateTime beginningOfDay){ SplunkLogger splunkLogger = new SplunkLogger(availabilityServiceContextV4.getRequestMajorAccounts().getHeaderRequest()); Delivery majorAccountsDelivery = new Delivery(); boolean localCrossedUTCMidnight = false; localCrossedUTCMidnight = availabilityServiceContextV4.isStorePastMidnightUTC(); try { List deliveryList = availabilityServiceContextV4.getDeliveryBySiteSorted().get(site.getSiteId()); if (deliveryList != null && deliveryList.size() > 0) { for (com.genpt.nsight.v4.model.Delivery delivery : deliveryList) { String cutOffDateTime = delivery.getCutOffDateTime(); //free delivery quickest option if (delivery.isFreeDelivery() && delivery.isQuickestOption()) { majorAccountsDelivery.setFreeDeliveryMOT(delivery.getDeliveryType()); majorAccountsDelivery.setFreeDeliveryCutOffDateTime(cutOffDateTime); /** if (delivery.getDeliveryEstimate() != null) { //get the timezone to check if its after midnight float shipFromTZ = 0; boolean isNextDay = false; String tz = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()).getTimeZone(); if (tz != null && tz.trim() != "" && tz.trim().compareToIgnoreCase("NaN") != 0) shipFromTZ = Float.parseFloat(nSightCache.getSiteIdToSiteMap().get(site.getSiteId()).getTimeZone()); if (availabilityServiceContextV4.getStoreOffSetTime() != null && shipFromTZ != 0) isNextDay = availabilityServiceContextV4.isCutOffNextDay(delivery.getCutOffTime(), shipFromTZ); delivery.setDayofweekString(DayOfWeekColNames[delivery.getDayOfWeek()]); if (isNextDay) majorAccountsDelivery.setFreeDeliveryMinDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMinValue(), delivery.getCutOffTime(), beginningOfDay, true, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); else majorAccountsDelivery.setFreeDeliveryMinDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMaxValue(), delivery.getCutOffTime(), beginningOfDay, false, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); if (isNextDay) majorAccountsDelivery.setFreeDeliveryMaxDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMinValue(), delivery.getCutOffTime(), beginningOfDay, true, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); else majorAccountsDelivery.setFreeDeliveryMaxDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMaxValue(), delivery.getCutOffTime(), beginningOfDay, false, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); } */ if (delivery.getDeliveryEstimate() != null) { if (delivery.getDeliveryEstimate().getExpectationRangeMin()!=null) majorAccountsDelivery.setFreeDeliveryMinDateRange(delivery.getDeliveryEstimate().getExpectationRangeMin()); if (delivery.getDeliveryEstimate().getExpectationRangeMax()!=null) majorAccountsDelivery.setFreeDeliveryMaxDateRange(delivery.getDeliveryEstimate().getExpectationRangeMax()); } } //Paid delivery quickest option else if (!delivery.isFreeDelivery() && delivery.isQuickestOption()) { majorAccountsDelivery.setPaidDeliveryMOT(delivery.getDeliveryType()); majorAccountsDelivery.setPaidDeliveryCutOffDateTime(cutOffDateTime); /** if (delivery.getDeliveryEstimate() != null) { //get the timezone to check if its after midnight float shipFromTZ = 0; boolean isNextDay = false; String tz = nSightCache.getSiteIdToSiteMap().get(site.getSiteId()).getTimeZone(); if (tz != null && tz.trim() != "" && tz.trim().compareToIgnoreCase("NaN") != 0) shipFromTZ = Float.parseFloat(nSightCache.getSiteIdToSiteMap().get(site.getSiteId()).getTimeZone()); if (availabilityServiceContextV4.getStoreOffSetTime() != null && shipFromTZ != 0) isNextDay = availabilityServiceContextV4.isCutOffNextDay(delivery.getCutOffTime(), shipFromTZ); if (isNextDay) majorAccountsDelivery.setPaidDeliveryMinDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMinValue(), delivery.getCutOffTime(), beginningOfDay, true, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); else majorAccountsDelivery.setPaidDeliveryMinDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMaxValue(), delivery.getCutOffTime(), beginningOfDay, false, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); if (isNextDay) majorAccountsDelivery.setPaidDeliveryMaxDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMinValue(), delivery.getCutOffTime(), beginningOfDay, true, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); else majorAccountsDelivery.setPaidDeliveryMaxDateRange(availabilityServiceContextV4.getDateTime(delivery.getDeliveryEstimate().getDurationMaxValue(), delivery.getCutOffTime(), beginningOfDay, false, delivery.getDeliveryEstimate().getDurationDesignator(), delivery.getDayofweekString(),localCrossedUTCMidnight)); } **/ if (delivery.getDeliveryEstimate() != null) { if (delivery.getDeliveryEstimate().getExpectationRangeMin()!=null) majorAccountsDelivery.setPaidDeliveryMinDateRange(delivery.getDeliveryEstimate().getExpectationRangeMin()); if (delivery.getDeliveryEstimate().getExpectationRangeMax()!=null) majorAccountsDelivery.setPaidDeliveryMaxDateRange(delivery.getDeliveryEstimate().getExpectationRangeMax()); } } } } }catch(Exception e){ LOGGER.info(splunkLogger.toString() + " Exception while adding delivery information. Exception : {}", e); } return majorAccountsDelivery; } private String getDisplayName(String siteId){ String displayName=""; if(nSightCache.getDisplayNameMap().get(siteId)!=null) displayName = nSightCache.getDisplayNameMap().get(siteId); return displayName; } private int getSiteRelationshipRank(String siteId, String relatedSite){ int rank=0; SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(siteId); for(SiteRelationDTO siteRelationDTO: siteDTO.getSiteRelationDTOList()) { if(siteRelationDTO.getRelationshipType().equalsIgnoreCase("Store Console Inventory Friend") && siteRelationDTO.getRelatedSiteIdentifier().equalsIgnoreCase(relatedSite)) { rank = siteRelationDTO.getRelationshipRank(); break; } } return rank; } private boolean isSiteMainCounter(String siteId){ boolean isMainCounter=false; SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(siteId); return siteDTO.getMainCounterFlag(); } private Map updateDetailMapForMainCounter(Map detailMap, String siteId, String primaryDCSiteId) { Detail detail = detailMap.get(siteId); if (detail != null) { BigDecimal localStoreQty = detail.getQty(); if (primaryDCSiteId != "") { Detail primaryDCDetail = detailMap.get(primaryDCSiteId); if (primaryDCDetail != null) { BigDecimal primaryDCStoreQty = primaryDCDetail.getQty(); BigDecimal qty = localStoreQty.add(primaryDCStoreQty); detail.setQty(qty); detailMap.remove(primaryDCSiteId); } } } //Populate localStore detail object with PrimaryDCQty as localStoreQty when localStore site is not found for part and store is main counter else { if (primaryDCSiteId != "") { Detail primaryDCDetail = detailMap.get(primaryDCSiteId); if (primaryDCDetail != null) { BigDecimal primaryDCStoreQty = primaryDCDetail.getQty(); Detail localStoreDetail = new Detail(); localStoreDetail.setFulfillmentIdentifier(siteId); localStoreDetail.setQty(primaryDCStoreQty); detailMap.put(siteId, localStoreDetail); detailMap.remove(primaryDCSiteId); } } } return detailMap; } private Fulfillment createLocalStoreFulfillment(String siteId, boolean needDeliveryInformation){ SiteDTO siteDTO = nSightCache.getSiteIdToSiteMap().get(siteId); Fulfillment fulfillment = new Fulfillment(); fulfillment.setFulfillmentIdentifier(UUID.fromString(siteId)); fulfillment.setType("Local Store"); for (SiteRelationDTO siteRelationDTO : siteDTO.getSiteRelationDTOList()) { if(siteRelationDTO.getRelatedSiteType().equalsIgnoreCase("Local Store") ){ fulfillment.setRank(siteRelationDTO.getRelationshipRank()); } } fulfillment.setCommonIdentifier(getSiteValue(siteDTO.getSiteIdentifierList(), "9 Digit Store Number")); if(siteDTO.getDisplayName()!=null) fulfillment.setAlternateIdentifier(siteDTO.getDisplayName()); fulfillment.setCity(siteDTO.getCity()); fulfillment.setState(siteDTO.getState()); //set fulfillment country and zip code if (siteDTO.getZipCode() != null) fulfillment.setZipcode(siteDTO.getZipCode()); else fulfillment.setZipcode("Not Available"); if (siteDTO.getCountry() != null) fulfillment.setCountry(siteDTO.getCountry()); else fulfillment.setCountry("Not Available"); fulfillment.setAddress1("-"); fulfillment.setAddress2(""); if (needDeliveryInformation) { Delivery delivery = new Delivery(); String localDateTimeInUTC = LocalDateTime.ofInstant(Instant.now(),ZoneId.systemDefault()).toString(); delivery.setFreeDeliveryCutOffDateTime(localDateTimeInUTC); delivery.setFreeDeliveryMaxDateRange(localDateTimeInUTC); delivery.setFreeDeliveryMinDateRange(localDateTimeInUTC); delivery.setFreeDeliveryMOT("Local Store"); fulfillment.setDelivery(delivery); } return fulfillment; } private Tracking addTracking(Tracking tracking){ Tracking locateProductTracking = new Tracking(); List logList = new ArrayList(); locateProductTracking.setIsSuccess(tracking.getIsSuccess()); if(tracking.getLog() != null) { tracking.getLog().forEach(log -> { Log log1 = new Log(log.getName(), log.getValue()); logList.add(log1); }); locateProductTracking.setLog(logList); } if(tracking.getFault() !=null){ locateProductTracking.setFault(Fault.builder().code(tracking.getFault().getCode()).message(tracking.getFault().getMessage()).build()); } return locateProductTracking; } }