|
@@ -0,0 +1,250 @@
|
|
|
|
|
+package cz.senslog.connector.fetch.fofr;
|
|
|
|
|
+
|
|
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
|
|
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
|
|
|
|
+import cz.senslog.connector.fetch.api.ConnectorFetcher;
|
|
|
|
|
+import cz.senslog.connector.model.api.VoidSession;
|
|
|
|
|
+import cz.senslog.connector.model.fofr.FofrModel;
|
|
|
|
|
+import cz.senslog.connector.model.fofr.ParcelUpdate;
|
|
|
|
|
+import cz.senslog.connector.tools.http.HttpClient;
|
|
|
|
|
+import cz.senslog.connector.tools.http.HttpRequest;
|
|
|
|
|
+import cz.senslog.connector.tools.http.HttpResponse;
|
|
|
|
|
+import cz.senslog.connector.tools.http.URLBuilder;
|
|
|
|
|
+import cz.senslog.connector.tools.util.Encoding;
|
|
|
|
|
+import cz.senslog.connector.tools.util.Tuple;
|
|
|
|
|
+import org.apache.logging.log4j.LogManager;
|
|
|
|
|
+import org.apache.logging.log4j.Logger;
|
|
|
|
|
+
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.OffsetDateTime;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.function.Function;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
+
|
|
|
|
|
+import static cz.senslog.connector.tools.json.BasicJson.jsonToObject;
|
|
|
|
|
+import static cz.senslog.connector.tools.json.BasicJson.objectToJson;
|
|
|
|
|
+import static java.lang.String.format;
|
|
|
|
|
+import static java.time.format.DateTimeFormatter.ofPattern;
|
|
|
|
|
+
|
|
|
|
|
+public class FofrFetcher implements ConnectorFetcher<VoidSession, FofrModel> {
|
|
|
|
|
+
|
|
|
|
|
+ private static final Logger logger = LogManager.getLogger(FofrFetcher.class);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ private final FofrConfig config;
|
|
|
|
|
+ private final HttpClient httpClient;
|
|
|
|
|
+ private final XmlMapper xmlMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private Map<String, WarehouseInfo> warehouses;
|
|
|
|
|
+ private Map<Integer, String> orderStates;
|
|
|
|
|
+
|
|
|
|
|
+ protected FofrFetcher(FofrConfig config, HttpClient httpClient) {
|
|
|
|
|
+ this.config = config;
|
|
|
|
|
+ this.httpClient = httpClient;
|
|
|
|
|
+ this.xmlMapper = new XmlMapper();
|
|
|
|
|
+
|
|
|
|
|
+ this.warehouses = Collections.emptyMap();
|
|
|
|
|
+ this.orderStates = Collections.emptyMap();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void init() throws Exception {
|
|
|
|
|
+ {
|
|
|
|
|
+ HttpRequest request = HttpRequest.newBuilder().GET()
|
|
|
|
|
+ .url(URLBuilder.newBuilder(config.getWarehouseLocationsUrl()).build())
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ HttpResponse response = httpClient.send(request);
|
|
|
|
|
+
|
|
|
|
|
+ if (response.isError()) {
|
|
|
|
|
+ throw logger.throwing(new Exception(format(
|
|
|
|
|
+ "Can not get information about the warehouses. %s", response.getBody()
|
|
|
|
|
+ )));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String responseBody = response.getBody();
|
|
|
|
|
+ List<?> responseDTO = jsonToObject(responseBody, List.class);
|
|
|
|
|
+ warehouses = responseDTO.stream().map(Map.class::cast).map(w -> new WarehouseInfo(
|
|
|
|
|
+ (String)w.get("KOD_STREDISKA"),
|
|
|
|
|
+ Double.parseDouble((String)w.get("GEOCODE_LAT")),
|
|
|
|
|
+ Double.parseDouble((String)w.get("GEOCODE_LNG"))
|
|
|
|
|
+ )).collect(Collectors.toMap(WarehouseInfo::getCode, Function.identity()));
|
|
|
|
|
+
|
|
|
|
|
+ for (WarehouseInfo missingWarehouse : config.getMissingWarehouses()) {
|
|
|
|
|
+ warehouses.put(missingWarehouse.getCode(), missingWarehouse);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+
|
|
|
|
|
+ HttpRequest request = HttpRequest.newBuilder().GET()
|
|
|
|
|
+ .url(URLBuilder.newBuilder(config.getOrderStatesUrl()).build())
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ HttpResponse response = httpClient.send(request, Encoding.WINDOWS_1250);
|
|
|
|
|
+
|
|
|
|
|
+ if (response.isError()) {
|
|
|
|
|
+ throw logger.throwing(new Exception(format(
|
|
|
|
|
+ "Can not get information about the statuses. %s", response.getBody()
|
|
|
|
|
+ )));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String responseBody = response.getBody();
|
|
|
|
|
+ List<?> xml = xmlMapper.readValue(responseBody, List.class);
|
|
|
|
|
+ orderStates = xml.stream().map(Map.class::cast).map(m -> Tuple.of(
|
|
|
|
|
+ Integer.parseInt((String)m.get("ID")),
|
|
|
|
|
+ (String)m.get("POPIS"))
|
|
|
|
|
+ ).collect(Collectors.toMap(Tuple::getItem1, Tuple::getItem2));
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public FofrModel fetch(Optional<VoidSession> session) {
|
|
|
|
|
+
|
|
|
|
|
+ List<OrderInfo> orderInfos = Collections.emptyList();
|
|
|
|
|
+//
|
|
|
|
|
+// {
|
|
|
|
|
+// HttpRequest request = HttpRequest.newBuilder().GET()
|
|
|
|
|
+// .url(URLBuilder.newBuilder(config.getActiveOrdersUrl()).build())
|
|
|
|
|
+// .build();
|
|
|
|
|
+//
|
|
|
|
|
+// HttpResponse response = httpClient.send(request);
|
|
|
|
|
+//
|
|
|
|
|
+// if (response.isOk()) {
|
|
|
|
|
+// String responseBody = response.getBody();
|
|
|
|
|
+// List<?> orderList = jsonToObject(responseBody, List.class);
|
|
|
|
|
+// orderInfos = new ArrayList<>(orderList.size());
|
|
|
|
|
+// for (Object orderO : orderList) {
|
|
|
|
|
+// if (orderO instanceof Map) {
|
|
|
|
|
+// Map<?, ?> orderMap = (Map<?, ?>) orderO;
|
|
|
|
|
+// orderInfos.add(new OrderInfo(
|
|
|
|
|
+// ((Double) orderMap.get("orderId")).longValue(),
|
|
|
|
|
+// ((Double) orderMap.get("parcelId")).longValue(),
|
|
|
|
|
+// ((Double) orderMap.get("unitId")).longValue()
|
|
|
|
|
+// ));
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+ orderInfos = Arrays.asList(new OrderInfo(0, 2590161966L, 0));
|
|
|
|
|
+
|
|
|
|
|
+ List<ParcelUpdate> parcelsToUpdate = new ArrayList<>();
|
|
|
|
|
+ for (OrderInfo orderInfo : orderInfos) {
|
|
|
|
|
+
|
|
|
|
|
+ long parcelId = orderInfo.getParcelId();
|
|
|
|
|
+
|
|
|
|
|
+ HttpRequest reqTrackingInfo = HttpRequest.newBuilder().GET()
|
|
|
|
|
+ .url(URLBuilder.newBuilder(config.getParcelTrackingUrl())
|
|
|
|
|
+ .addParam("shipment", parcelId)
|
|
|
|
|
+ .build())
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ HttpResponse resTrackingInfo = httpClient.send(reqTrackingInfo, Encoding.WINDOWS_1250);
|
|
|
|
|
+ if (resTrackingInfo.isError()) {
|
|
|
|
|
+ logger.error(resTrackingInfo.getBody()); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ String trackingInfoBody = resTrackingInfo.getBody();
|
|
|
|
|
+ ParcelTrackingStatus trackingInfo = xmlMapper.readValue(trackingInfoBody, ParcelTrackingStatus.class);
|
|
|
|
|
+
|
|
|
|
|
+ if (trackingInfo.getId() != (parcelId)) {
|
|
|
|
|
+ logger.warn("Received tracking ID does not match: {} != {}", parcelId, trackingInfo.getId()); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // TODO compare last status with the one from session if any updates
|
|
|
|
|
+ // TODO if no update, continue to next parcelId
|
|
|
|
|
+
|
|
|
|
|
+ if (trackingInfo.getStatuses().isEmpty()) {
|
|
|
|
|
+ logger.warn("No status for the parcel ID {}", trackingInfo.getId()); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int parcelYear = trackingInfo.getStatuses().get(0).getTimestamp().getYear();
|
|
|
|
|
+
|
|
|
|
|
+ HttpRequest reqParcelInfo = HttpRequest.newBuilder().GET()
|
|
|
|
|
+ .url(URLBuilder.newBuilder(String.format(config.getParcelInfoUrl(), parcelId, parcelYear)
|
|
|
|
|
+ ).build())
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ HttpResponse resParcelInfo = httpClient.send(reqParcelInfo);
|
|
|
|
|
+ if (resParcelInfo.isError()) {
|
|
|
|
|
+ logger.error(resParcelInfo.getBody()); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String parcelInfoBody = resParcelInfo.getBody();
|
|
|
|
|
+ List<?> parcelInfoList = jsonToObject(parcelInfoBody, List.class);
|
|
|
|
|
+ if (parcelInfoList.isEmpty()) {
|
|
|
|
|
+ logger.error("Parcel info of the ID " + parcelId + " not found"); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!(parcelInfoList.get(0) instanceof Map)) {
|
|
|
|
|
+ logger.error("Wrong type of parcel info."); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<?,?> parcelInfo = (Map<?,?>) parcelInfoList.get(0);
|
|
|
|
|
+ long shipmentNum = Long.parseLong((String) parcelInfo.get("shipment_num"));
|
|
|
|
|
+ if (parcelId != (shipmentNum)) {
|
|
|
|
|
+ logger.warn("Received parcel info data does not match: {} != {}", parcelId, trackingInfo.getId()); continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String officeBranchCode = (String) parcelInfo.get("kod_pobocky");
|
|
|
|
|
+ WarehouseInfo officeBranch = warehouses.get(officeBranchCode);
|
|
|
|
|
+
|
|
|
|
|
+ int lastTrackingStatusCode = ((Double)parcelInfo.get("posledni_statut")).intValue();
|
|
|
|
|
+ List<ParcelTrackingStatus.Status> statuses = trackingInfo.getStatuses();
|
|
|
|
|
+ if (statuses.get(statuses.size()-1).getCode() != lastTrackingStatusCode) {
|
|
|
|
|
+ statuses.sort(Comparator.comparing(ParcelTrackingStatus.Status::getTimestamp));
|
|
|
|
|
+ }
|
|
|
|
|
+ List<ParcelInfo.TrackingStatus> trackingStatuses = new ArrayList<>(statuses.size());
|
|
|
|
|
+ for (ParcelTrackingStatus.Status status : statuses) {
|
|
|
|
|
+ String statusName = orderStates.get(status.getCode());
|
|
|
|
|
+ if (statusName == null) {
|
|
|
|
|
+ logger.warn("No status name for '{}'", status.getCode());
|
|
|
|
|
+ }
|
|
|
|
|
+ WarehouseInfo transitWarehouse = warehouses.get(status.getWarehouseCode());
|
|
|
|
|
+ if (transitWarehouse == null) {
|
|
|
|
|
+ logger.warn("No warehouse for '{}'", status.getWarehouseCode());
|
|
|
|
|
+ }
|
|
|
|
|
+ trackingStatuses.add(new ParcelInfo.TrackingStatus(
|
|
|
|
|
+ status.getCode(), statusName, status.getTimestamp(), transitWarehouse
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LocalDateTime exportDate = LocalDateTime.parse((String)parcelInfo.get("datum_exportu"), ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
+
|
|
|
|
|
+ ParcelInfo parcel = new ParcelInfo(parcelId, officeBranch, exportDate, trackingStatuses,
|
|
|
|
|
+ new ParcelInfo.Address(
|
|
|
|
|
+ (String) parcelInfo.get("odes_firma"),
|
|
|
|
|
+ (String) parcelInfo.get("odes_stat"),
|
|
|
|
|
+ (String) parcelInfo.get("odes_mesto"),
|
|
|
|
|
+ (String) parcelInfo.get("odes_ulice"),
|
|
|
|
|
+ (String) parcelInfo.get("odes_psc")
|
|
|
|
|
+ ),
|
|
|
|
|
+ new ParcelInfo.Address(
|
|
|
|
|
+ (String) parcelInfo.get("prij_firma"),
|
|
|
|
|
+ (String) parcelInfo.get("prij_stat"),
|
|
|
|
|
+ (String) parcelInfo.get("prij_mesto"),
|
|
|
|
|
+ (String) parcelInfo.get("prij_ulice"),
|
|
|
|
|
+ (String) parcelInfo.get("prij_psc")
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (parcel.lastTrackingStatus().getId() == config.getDeliveryStatus()) {
|
|
|
|
|
+ // TODO parcel is delivered
|
|
|
|
|
+ // GET GPS coordination from delivery address
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ System.out.println(objectToJson(parcel));
|
|
|
|
|
+
|
|
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new FofrModel(parcelsToUpdate, OffsetDateTime.now(), OffsetDateTime.now());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+}
|