diff --git a/src/java/ABTProductsPUTGenerator/.gitignore b/src/java/ABTProductsPUTGenerator/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/.idea/.gitignore b/src/java/ABTProductsPUTGenerator/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/src/java/ABTProductsPUTGenerator/.idea/encodings.xml b/src/java/ABTProductsPUTGenerator/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/.idea/misc.xml b/src/java/ABTProductsPUTGenerator/.idea/misc.xml
new file mode 100644
index 0000000..7ace097
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/.idea/vcs.xml b/src/java/ABTProductsPUTGenerator/.idea/vcs.xml
new file mode 100644
index 0000000..c2365ab
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/bin/ABTProductsPUTGenerator.jar b/src/java/ABTProductsPUTGenerator/bin/ABTProductsPUTGenerator.jar
new file mode 100644
index 0000000..ab8352d
Binary files /dev/null and b/src/java/ABTProductsPUTGenerator/bin/ABTProductsPUTGenerator.jar differ
diff --git a/src/java/ABTProductsPUTGenerator/bin/README.md b/src/java/ABTProductsPUTGenerator/bin/README.md
new file mode 100644
index 0000000..b69e347
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/bin/README.md
@@ -0,0 +1,10 @@
+# ABTProducts PUT request body generator
+Simple tool to quickly edit HTM products via ABTProducts REST API.
+
+- Requires JRE 21
+- Run via: `java -jar ABTProductsPUTGenerator.jar`
+ - Specify custom input/output path via: `java -jar ABTProductsPUTGenerator.jar `
+- Takes a ABTProducts GET response body in JSON format (product details)
+- Generates the equivalent PUT request body
+- Default input path: /input.json
+- Default output path: /output.json (output is overwritten if it exists)
diff --git a/src/java/ABTProductsPUTGenerator/bin/input.json b/src/java/ABTProductsPUTGenerator/bin/input.json
new file mode 100644
index 0000000..2873379
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/bin/input.json
@@ -0,0 +1,154 @@
+{
+ "productId": 38,
+ "parentProductId": null,
+ "productCode": "30901-WA",
+ "gboPackageTemplateId": "30901",
+ "tapConnectProductCode": null,
+ "productGroupMetadata": null,
+ "productName": "HTM P1W Prolongatie-Test 90% Korting",
+ "productDescription": "Reis je regelmatig met HTM? Activeer dan HTM 90% Korting op je betaalpas of credit card en reis met korting!",
+ "validityPeriod": {
+ "validityPeriodId": 148,
+ "fromInclusive": "2023-12-31T23:00:00.000+00:00",
+ "toInclusive": "2029-12-08T04:00:00.000+00:00"
+ },
+ "productTranslations": [
+ {
+ "language": "en",
+ "name": "HTM Prolongation-Test 90% Discount",
+ "description": "Are you a regular traveler? Activate HTM 90% discount on your EMV card!"
+ }
+ ],
+ "productOwner": {
+ "productOwnerId": 17,
+ "name": "Corneel Verstoep",
+ "organization": "HTM"
+ },
+ "marketSegments": [
+ {
+ "marketSegmentId": 1,
+ "name": "B2C"
+ }
+ ],
+ "customerSegments": [
+ {
+ "customerSegmentId": 2,
+ "name": "Kind (4-11)"
+ },
+ {
+ "customerSegmentId": 3,
+ "name": "Jongere (12-18)"
+ },
+ {
+ "customerSegmentId": 4,
+ "name": "Volwassene (19-64)"
+ },
+ {
+ "customerSegmentId": 5,
+ "name": "Oudere (65+)"
+ }
+ ],
+ "productCategory": {
+ "productCategoryId": 1,
+ "isTravelProduct": true,
+ "name": "Kortingsabonnement"
+ },
+ "requiredCustomerLevel": {
+ "requiredCustomerLevelId": 3,
+ "name": "profile"
+ },
+ "requiredProducts": null,
+ "incompatibleProducts": null,
+ "mandatoryCustomerDataItems": [
+ {
+ "mandatoryCustomerDataItemId": 1,
+ "customerDataItem": "birthname"
+ },
+ {
+ "mandatoryCustomerDataItemId": 2,
+ "customerDataItem": "surname"
+ },
+ {
+ "mandatoryCustomerDataItemId": 4,
+ "customerDataItem": "emailAddress"
+ },
+ {
+ "mandatoryCustomerDataItemId": 5,
+ "customerDataItem": "address"
+ }
+ ],
+ "requiredGboPersonalAttributes": null,
+ "tokenTypes": [
+ {
+ "tokenTypeId": 1,
+ "name": "EMV"
+ }
+ ],
+ "paymentMoment": {
+ "paymentMomentId": 1,
+ "name": "prepaid"
+ },
+ "serviceOptions": null,
+ "validityDuration": "P1W",
+ "maxStartInFutureDuration": "P6W",
+ "isRenewable": true,
+ "sendInvoice": true,
+ "imageReference": "https://web.acc.cloud.htm.nl/media/leif2leu/htm-logo-mobile.svg",
+ "productPageUrl": "https://web.acc.cloud.htm.nl/webshop/htm-90-korting/",
+ "termsUrl": "https://web.acc.cloud.htm.nl/reisproducten/productvoorwaarden/htm-90-korting/",
+ "isSellableAtHtm": true,
+ "needsSolvencyCheckConsumer": false,
+ "needsSolvencyCheckBusiness": false,
+ "sellingPeriods": [
+ {
+ "sellingPeriodId": 89,
+ "fromInclusive": "2024-09-30T23:00:00.000+00:00",
+ "toInclusive": "2029-12-01T23:00:00.000+00:00",
+ "salesTouchpoint": {
+ "salesTouchpointId": 3,
+ "name": "Website (Perplex)",
+ "isActive": true,
+ "retailer": {
+ "retailerId": 1001,
+ "name": "HTM externe touchpoints",
+ "street": "Koningin Julianaplein",
+ "number": 10,
+ "numberAddition": null,
+ "postalCode": "2595 AA",
+ "city": "Den Haag",
+ "country": "Nederland",
+ "emailAddress": "info@htm.nl",
+ "phoneNumber": "070 374 9002",
+ "taxId": 572309345923,
+ "imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg"
+ }
+ },
+ "forbiddenPaymentMethods": null,
+ "sellingPrices": [
+ {
+ "sellingPriceId": 82,
+ "amountExclTax": 92,
+ "amountInclTax": 100,
+ "fromInclusive": "2024-09-30T23:00:00.000+00:00",
+ "toInclusive": "2029-12-01T23:00:00.000+00:00",
+ "internalPrice": 0.0000,
+ "taxMetadata": {
+ "taxMetadataId": "47C8972E-A730-4032-9BDA-AF0A5BCB2C85",
+ "taxCode": "V09",
+ "taxPercentageAmount": 9,
+ "description": "BTW VERKOOP LAAG 9%"
+ }
+ }
+ ]
+ }
+ ],
+ "purchasePrices": null,
+ "auditTrail": [
+ {
+ "auditTrailId": 162,
+ "action": "insert",
+ "user": "api",
+ "timestamp": "2024-11-25T08:39:36.793+00:00"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/bin/output.json b/src/java/ABTProductsPUTGenerator/bin/output.json
new file mode 100644
index 0000000..070aba6
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/bin/output.json
@@ -0,0 +1,58 @@
+{
+ "parentProductId" : null,
+ "productCode" : "30901-WA",
+ "gboPackageTemplateId" : "30901",
+ "tapConnectProductCode" : null,
+ "productGroupMetadata" : null,
+ "productName" : "HTM P1W Prolongatie-Test 90% Korting",
+ "productDescription" : "Reis je regelmatig met HTM? Activeer dan HTM 90% Korting op je betaalpas of credit card en reis met korting!",
+ "validityPeriod" : {
+ "validityPeriodId" : 148,
+ "fromInclusive" : "2023-12-31T23:00:00.000+00:00",
+ "toInclusive" : "2029-12-08T04:00:00.000+00:00"
+ },
+ "productTranslations" : [ {
+ "language" : "en",
+ "name" : "HTM Prolongation-Test 90% Discount",
+ "description" : "Are you a regular traveler? Activate HTM 90% discount on your EMV card!"
+ } ],
+ "productOwnerId" : 17,
+ "marketSegmentIds" : [ 1 ],
+ "customerSegmentIds" : [ 2, 3, 4, 5 ],
+ "productCategoryId" : 1,
+ "requiredCustomerLevelId" : 3,
+ "requiredProducts" : null,
+ "incompatibleProducts" : null,
+ "mandatoryCustomerDataItemIds" : [ 1, 2, 4, 5 ],
+ "requiredGboPersonalAttributes" : null,
+ "tokenTypeIds" : [ 1 ],
+ "paymentMomentId" : 1,
+ "serviceOptions" : null,
+ "validityDuration" : "P1W",
+ "maxStartInFutureDuration" : "P6W",
+ "isRenewable" : true,
+ "sendInvoice" : true,
+ "imageReference" : "https://web.acc.cloud.htm.nl/media/leif2leu/htm-logo-mobile.svg",
+ "productPageUrl" : "https://web.acc.cloud.htm.nl/webshop/htm-90-korting/",
+ "termsUrl" : "https://web.acc.cloud.htm.nl/reisproducten/productvoorwaarden/htm-90-korting/",
+ "isSellableAtHtm" : true,
+ "needsSolvencyCheckConsumer" : false,
+ "needsSolvencyCheckBusiness" : false,
+ "sellingPeriods" : [ {
+ "sellingPeriodId" : 89,
+ "fromInclusive" : "2024-09-30T23:00:00.000+00:00",
+ "toInclusive" : "2029-12-01T23:00:00.000+00:00",
+ "salesTouchpointId" : 3,
+ "forbiddenPaymentMethodIds" : null,
+ "sellingPrices" : [ {
+ "sellingPriceId" : 82,
+ "amountExclTax" : 92,
+ "amountInclTax" : 100,
+ "fromInclusive" : "2024-09-30T23:00:00.000+00:00",
+ "toInclusive" : "2029-12-01T23:00:00.000+00:00",
+ "internalPrice" : 0.0,
+ "taxMetadataId" : "47C8972E-A730-4032-9BDA-AF0A5BCB2C85"
+ } ]
+ } ],
+ "purchasePrices" : null
+}
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/output.json b/src/java/ABTProductsPUTGenerator/output.json
new file mode 100644
index 0000000..070aba6
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/output.json
@@ -0,0 +1,58 @@
+{
+ "parentProductId" : null,
+ "productCode" : "30901-WA",
+ "gboPackageTemplateId" : "30901",
+ "tapConnectProductCode" : null,
+ "productGroupMetadata" : null,
+ "productName" : "HTM P1W Prolongatie-Test 90% Korting",
+ "productDescription" : "Reis je regelmatig met HTM? Activeer dan HTM 90% Korting op je betaalpas of credit card en reis met korting!",
+ "validityPeriod" : {
+ "validityPeriodId" : 148,
+ "fromInclusive" : "2023-12-31T23:00:00.000+00:00",
+ "toInclusive" : "2029-12-08T04:00:00.000+00:00"
+ },
+ "productTranslations" : [ {
+ "language" : "en",
+ "name" : "HTM Prolongation-Test 90% Discount",
+ "description" : "Are you a regular traveler? Activate HTM 90% discount on your EMV card!"
+ } ],
+ "productOwnerId" : 17,
+ "marketSegmentIds" : [ 1 ],
+ "customerSegmentIds" : [ 2, 3, 4, 5 ],
+ "productCategoryId" : 1,
+ "requiredCustomerLevelId" : 3,
+ "requiredProducts" : null,
+ "incompatibleProducts" : null,
+ "mandatoryCustomerDataItemIds" : [ 1, 2, 4, 5 ],
+ "requiredGboPersonalAttributes" : null,
+ "tokenTypeIds" : [ 1 ],
+ "paymentMomentId" : 1,
+ "serviceOptions" : null,
+ "validityDuration" : "P1W",
+ "maxStartInFutureDuration" : "P6W",
+ "isRenewable" : true,
+ "sendInvoice" : true,
+ "imageReference" : "https://web.acc.cloud.htm.nl/media/leif2leu/htm-logo-mobile.svg",
+ "productPageUrl" : "https://web.acc.cloud.htm.nl/webshop/htm-90-korting/",
+ "termsUrl" : "https://web.acc.cloud.htm.nl/reisproducten/productvoorwaarden/htm-90-korting/",
+ "isSellableAtHtm" : true,
+ "needsSolvencyCheckConsumer" : false,
+ "needsSolvencyCheckBusiness" : false,
+ "sellingPeriods" : [ {
+ "sellingPeriodId" : 89,
+ "fromInclusive" : "2024-09-30T23:00:00.000+00:00",
+ "toInclusive" : "2029-12-01T23:00:00.000+00:00",
+ "salesTouchpointId" : 3,
+ "forbiddenPaymentMethodIds" : null,
+ "sellingPrices" : [ {
+ "sellingPriceId" : 82,
+ "amountExclTax" : 92,
+ "amountInclTax" : 100,
+ "fromInclusive" : "2024-09-30T23:00:00.000+00:00",
+ "toInclusive" : "2029-12-01T23:00:00.000+00:00",
+ "internalPrice" : 0.0,
+ "taxMetadataId" : "47C8972E-A730-4032-9BDA-AF0A5BCB2C85"
+ } ]
+ } ],
+ "purchasePrices" : null
+}
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/pom.xml b/src/java/ABTProductsPUTGenerator/pom.xml
new file mode 100644
index 0000000..6c41c8c
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/pom.xml
@@ -0,0 +1,67 @@
+
+ 4.0.0
+ nl.htm.ovpay.abt
+ ABTProductsPUTGenerator
+ 1.0-SNAPSHOT
+ ABTProductsPUTGenerator
+ Generate an ABTProducts PUT request body from a given ABTProducts GET response body
+
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.23.1
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.23.1
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ 2.23.1
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.17.2
+
+
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+
+ nl.htm.ovpay.abt.ABTProductsPUTGenerator
+
+
+
+ jar-with-dependencies
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 21
+ 21
+
+
+
+
+
diff --git a/src/java/ABTProductsPUTGenerator/src/main/java/nl/htm/ovpay/abt/ABTProductsPUTGenerator.java b/src/java/ABTProductsPUTGenerator/src/main/java/nl/htm/ovpay/abt/ABTProductsPUTGenerator.java
new file mode 100644
index 0000000..c82c5b8
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/src/main/java/nl/htm/ovpay/abt/ABTProductsPUTGenerator.java
@@ -0,0 +1,270 @@
+package nl.htm.ovpay.abt;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class ABTProductsPUTGenerator {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ABTProductsPUTGenerator.class);
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 2) {
+ LOGGER.info("To modify input/output path, use: java -jar ABTProductsPUTGenerator.jar ");
+ }
+ var inputFile = args.length > 0 ? args[0] : "input.json";
+ var outputFile = args.length > 1 ? args[1] : "output.json";
+ try(InputStream is = getInputStream(inputFile)) {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jsonNode = mapper.readTree(is);
+
+ LOGGER.info("Successfully parsed product with productId {} from JSON:\n{}\n", jsonNode.get("productId").asLong(), jsonNode.toPrettyString());
+
+ JsonNode putJsonNode = processJsonNode(jsonNode);
+
+ writeToFile(putJsonNode, outputFile);
+ }
+
+ LOGGER.info("DONE! Modify the output JSON as desired and send it as ABTProducts PUT request body.");
+ }
+
+ private static InputStream getInputStream(String filePath) throws IOException {
+ var externalResource = new File(filePath);
+ if (externalResource.exists()) {
+ LOGGER.info("Loading ABTProducts details JSON from external file {}...", externalResource.getAbsolutePath());
+ return externalResource.toURI().toURL().openStream();
+ } else {
+ LOGGER.info("External file {} not found, using internal resource /input.json...", filePath);
+ return ABTProductsPUTGenerator.class.getResourceAsStream("/input.json");
+ }
+ }
+
+ private static void writeToFile(JsonNode jsonNode, String filePath) throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ var outputFile = new File(filePath);
+ if (outputFile.exists()) {
+ LOGGER.info("Deleting existing output file {}...", filePath);
+ outputFile.delete();
+ }
+ mapper.writerWithDefaultPrettyPrinter().writeValue(outputFile, jsonNode);
+ LOGGER.info("Successfully wrote JSON to file {}!", outputFile.getAbsolutePath(), jsonNode.toPrettyString());
+ }
+
+ private static JsonNode processJsonNode(JsonNode jsonNode) {
+ var newJsonNode = new ObjectNode(new JsonNodeFactory(true));
+
+ jsonNode.fields().forEachRemaining(jsonField -> {
+ if (!List.of(JsonNodeType.ARRAY, JsonNodeType.OBJECT).contains(jsonField.getValue().getNodeType())) {
+ if (!jsonField.getKey().equals("productId") && !jsonField.getKey().equals("auditTrail")) {
+ LOGGER.info("Keeping {} as-is...", jsonField.getKey());
+ newJsonNode.put(jsonField.getKey(), jsonField.getValue());
+ }
+ } else {
+ if (List.of("validityPeriod", "productTranslations").contains(jsonField.getKey())) {
+ LOGGER.info("Keeping {} as-is...", jsonField.getKey());
+ newJsonNode.set(jsonField.getKey(), jsonField.getValue());
+ } else {
+ rewriteObjectFields(jsonField, newJsonNode);
+ rewriteArrayFields(jsonField, newJsonNode);
+ }
+ }
+ });
+
+ LOGGER.info("Successfully rewritten into PUT JSON:\n{}\n", newJsonNode.toPrettyString());
+
+ return newJsonNode;
+ }
+
+ private static void rewriteObjectFields(Map.Entry jsonField, JsonNode newJsonNode) {
+ switch (jsonField.getKey()) {
+ case "productOwner" -> {
+ LOGGER.info("Rewriting productOwner to productOwnerId...");
+ Long productOwnerId = jsonField.getValue().get("productOwnerId").asLong();
+ ((ObjectNode)newJsonNode).put("productOwnerId", productOwnerId);
+ }
+ case "productCategory" -> {
+ LOGGER.info("Rewriting productCategory to productCategoryId...");
+ Long productCategoryId = jsonField.getValue().get("productCategoryId").asLong();
+ ((ObjectNode)newJsonNode).put("productCategoryId", productCategoryId);
+ }
+ case "paymentMoment" -> {
+ LOGGER.info("Rewriting paymentMoment to paymentMomentId...");
+ Long paymentMomentId = jsonField.getValue().get("paymentMomentId").asLong();
+ ((ObjectNode)newJsonNode).put("paymentMomentId", paymentMomentId);
+ }
+ case "requiredCustomerLevel" -> {
+ LOGGER.info("Rewriting requiredCustomerLevel to requiredCustomerLevelId...");
+ Long requiredCustomerLevelId = jsonField.getValue().get("requiredCustomerLevelId").asLong();
+ ((ObjectNode)newJsonNode).put("requiredCustomerLevelId", requiredCustomerLevelId);
+ }
+ }
+ }
+
+ private static void rewriteArrayFields(Map.Entry jsonField, JsonNode newJsonNode) {
+ switch (jsonField.getKey()) {
+ case "marketSegments" -> {
+ LOGGER.info("Rewriting marketSegments to marketSegmentIds...");
+ if (jsonField.getValue() != null) {
+ ArrayNode marketSegmentIds = new ArrayNode(new JsonNodeFactory(true));
+ ((ArrayNode)jsonField.getValue()).elements().forEachRemaining(marketSegment -> {
+ marketSegmentIds.add(marketSegment.get("marketSegmentId").asLong());
+ });
+ ((ObjectNode)newJsonNode).putArray("marketSegmentIds").addAll(marketSegmentIds);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("marketSegmentIds", null);
+ }
+ }
+ case "customerSegments" -> {
+ LOGGER.info("Rewriting customerSegments to customerSegmentIds...");
+ if (jsonField.getValue() != null) {
+ ArrayNode customerSegmentIds = new ArrayNode(new JsonNodeFactory(true));
+ ((ArrayNode)jsonField.getValue()).elements().forEachRemaining(customerSegment -> {
+ customerSegmentIds.add(customerSegment.get("customerSegmentId").asLong());
+ });
+ ((ObjectNode)newJsonNode).putArray("customerSegmentIds").addAll(customerSegmentIds);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("customerSegmentIds", null);
+ }
+ }
+ case "tokenTypes" -> {
+ LOGGER.info("Rewriting tokenTypes to tokenTypeIds...");
+ if (jsonField.getValue() != null) {
+ ArrayNode tokenTypeIds = new ArrayNode(new JsonNodeFactory(true));
+ ((ArrayNode)jsonField.getValue()).elements().forEachRemaining(tokenType -> {
+ tokenTypeIds.add(tokenType.get("tokenTypeId").asLong());
+ });
+ ((ObjectNode)newJsonNode).putArray("tokenTypeIds").addAll(tokenTypeIds);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("tokenTypeIds", null);
+ }
+ }
+ case "mandatoryCustomerDataItems" -> {
+ LOGGER.info("Rewriting mandatoryCustomerDataItems to mandatoryCustomerDataItemIds...");
+ if (jsonField.getValue() != null) {
+ ArrayNode mandatoryCustomerDataItemIds = new ArrayNode(new JsonNodeFactory(true));
+ ((ArrayNode)jsonField.getValue()).elements().forEachRemaining(mandatoryCustomerDataItem -> {
+ mandatoryCustomerDataItemIds.add(mandatoryCustomerDataItem.get("mandatoryCustomerDataItemId").asLong());
+ });
+ ((ObjectNode)newJsonNode).putArray("mandatoryCustomerDataItemIds").addAll(mandatoryCustomerDataItemIds);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("mandatoryCustomerDataItemIds", null);
+ }
+ }
+ case "requiredGboPersonalAttributes" -> {
+ LOGGER.info("Rewriting requiredGboPersonalAttributes to requiredGboPersonalAttributeIds...");
+ if (jsonField.getValue() != null) {
+ ArrayNode requiredGboPersonalAttributeIds = new ArrayNode(new JsonNodeFactory(true));
+ ((ArrayNode)jsonField.getValue()).elements().forEachRemaining(requiredGboPersonalAttribute -> {
+ requiredGboPersonalAttributeIds.add(
+ requiredGboPersonalAttribute.get("requiredGboPersonalAttributeId").asLong());
+ });
+ ((ObjectNode)newJsonNode).putArray("requiredGboPersonalAttributeIds").addAll(requiredGboPersonalAttributeIds);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("requiredGboPersonalAttributeIds", null);
+ }
+ }
+ case "serviceOptions" -> {
+ LOGGER.info("Rewriting serviceOptions to serviceOptionIds...");
+ if (jsonField.getValue() != null) {
+ ArrayNode serviceOptionIds = new ArrayNode(new JsonNodeFactory(true));
+ ((ArrayNode)jsonField.getValue()).elements().forEachRemaining(serviceOption -> {
+ serviceOptionIds.add(serviceOption.get("serviceOptionId").asLong());
+ });
+ ((ObjectNode)newJsonNode).putArray("serviceOptionIds").addAll(serviceOptionIds);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("serviceOptionIds", null);
+ }
+ }
+ case "incompatibleProducts" -> {
+ LOGGER.info("Rewriting incompatibleProducts to remove product names...");
+ if (jsonField.getValue() != null) {
+ ArrayNode incompatibleProducts = ((ArrayNode)jsonField.getValue()).deepCopy();
+ incompatibleProducts.elements().forEachRemaining(incompatibleProduct -> {
+ ((ObjectNode)incompatibleProduct).remove("productName");
+ });
+ ((ObjectNode)newJsonNode).putArray("incompatibleProducts").addAll(incompatibleProducts);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("incompatibleProducts", null);
+ }
+ }
+ case "requiredProducts" -> {
+ LOGGER.info("Rewriting requiredProducts to remove product names...");
+ if (jsonField.getValue() != null) {
+ ArrayNode requiredProducts = ((ArrayNode)jsonField.getValue()).deepCopy();
+ requiredProducts.elements().forEachRemaining(requiredProduct -> {
+ ((ObjectNode)requiredProduct).remove("productName");
+ });
+ ((ObjectNode)newJsonNode).putArray("requiredProducts").addAll(requiredProducts);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("requiredProducts", null);
+ }
+ }
+ case "sellingPeriods" -> {
+ if (jsonField.getValue() != null) {
+ LOGGER.info("Rewriting salesTouchpoint in sellingPeriods to salesTouchpointId...");
+ ArrayNode sellingPeriods = ((ArrayNode)jsonField.getValue()).deepCopy();
+ sellingPeriods.elements().forEachRemaining(sellingPeriod -> {
+ Long salesTouchpointId = sellingPeriod.get("salesTouchpoint").get("salesTouchpointId").asLong();
+ ((ObjectNode)sellingPeriod).put("salesTouchpointId", salesTouchpointId);
+ ((ObjectNode)sellingPeriod).remove("salesTouchpoint");
+ if (sellingPeriod.get("forbiddenPaymentMethods") != null) {
+ LOGGER.info("Rewriting forbiddenPaymentMethods to forbiddenPaymentMethodIds...");
+ ArrayNode forbiddenPaymentMethodIds = new ArrayNode(new JsonNodeFactory(true));
+ sellingPeriod.get("forbiddenPaymentMethods").elements().forEachRemaining(forbiddenPaymentMethod -> {
+ forbiddenPaymentMethodIds.add(forbiddenPaymentMethod.get("forbiddenPaymentMethodId").asLong());
+ });
+ ((ObjectNode)sellingPeriod).remove("forbiddenPaymentMethods");
+ if (!forbiddenPaymentMethodIds.isEmpty()) {
+ ((ObjectNode)sellingPeriod).putArray("forbiddenPaymentMethodIds").addAll(forbiddenPaymentMethodIds);
+ } else {
+ ((ObjectNode)sellingPeriod).putRawValue("forbiddenPaymentMethodIds", null);
+ }
+ }
+ if (sellingPeriod.get("sellingPrices") != null) {
+ LOGGER.info("Rewriting taxMetadata in sellingPrices to taxMetadataId...");
+ ArrayNode sellingPrices = ((ArrayNode)sellingPeriod.get("sellingPrices")).deepCopy();
+ sellingPrices.elements().forEachRemaining(sellingPrice -> {
+ String taxMetadataId = sellingPrice.get("taxMetadata").get("taxMetadataId").asText();
+ ((ObjectNode)sellingPrice).put("taxMetadataId", taxMetadataId);
+ ((ObjectNode)sellingPrice).remove("taxMetadata");
+ });
+ ((ObjectNode)sellingPeriod).remove("sellingPrices");
+ if (!sellingPrices.isEmpty()) {
+ ((ObjectNode)sellingPeriod).putArray("sellingPrices").addAll(sellingPrices);
+ } else {
+ ((ObjectNode)sellingPeriod).putRawValue("sellingPrices", null);
+ }
+ }
+ });
+ ((ObjectNode)newJsonNode).putArray("sellingPeriods").addAll(sellingPeriods);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("sellingPeriods", null);
+ }
+ }
+ case "purchasePrices" -> {
+ LOGGER.info("Rewriting taxMetadata in purchasePrices to taxMetadataId...");
+ if (jsonField.getValue() != null) {
+ ArrayNode purchasePrices = ((ArrayNode)jsonField.getValue()).deepCopy();
+ purchasePrices.elements().forEachRemaining(purchasePrice -> {
+ String taxMetadataId = purchasePrice.get("taxMetadata").get("taxMetadataId").asText();
+ ((ObjectNode)purchasePrice).put("taxMetadataId", taxMetadataId);
+ ((ObjectNode)purchasePrice).remove("taxMetadata");
+ });
+ ((ObjectNode)newJsonNode).putArray("purchasePrices").addAll(purchasePrices);
+ } else {
+ ((ObjectNode)newJsonNode).putRawValue("purchasePrices", null);
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/ABTProductsPUTGenerator/src/main/resources/input.json b/src/java/ABTProductsPUTGenerator/src/main/resources/input.json
new file mode 100644
index 0000000..2873379
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/src/main/resources/input.json
@@ -0,0 +1,154 @@
+{
+ "productId": 38,
+ "parentProductId": null,
+ "productCode": "30901-WA",
+ "gboPackageTemplateId": "30901",
+ "tapConnectProductCode": null,
+ "productGroupMetadata": null,
+ "productName": "HTM P1W Prolongatie-Test 90% Korting",
+ "productDescription": "Reis je regelmatig met HTM? Activeer dan HTM 90% Korting op je betaalpas of credit card en reis met korting!",
+ "validityPeriod": {
+ "validityPeriodId": 148,
+ "fromInclusive": "2023-12-31T23:00:00.000+00:00",
+ "toInclusive": "2029-12-08T04:00:00.000+00:00"
+ },
+ "productTranslations": [
+ {
+ "language": "en",
+ "name": "HTM Prolongation-Test 90% Discount",
+ "description": "Are you a regular traveler? Activate HTM 90% discount on your EMV card!"
+ }
+ ],
+ "productOwner": {
+ "productOwnerId": 17,
+ "name": "Corneel Verstoep",
+ "organization": "HTM"
+ },
+ "marketSegments": [
+ {
+ "marketSegmentId": 1,
+ "name": "B2C"
+ }
+ ],
+ "customerSegments": [
+ {
+ "customerSegmentId": 2,
+ "name": "Kind (4-11)"
+ },
+ {
+ "customerSegmentId": 3,
+ "name": "Jongere (12-18)"
+ },
+ {
+ "customerSegmentId": 4,
+ "name": "Volwassene (19-64)"
+ },
+ {
+ "customerSegmentId": 5,
+ "name": "Oudere (65+)"
+ }
+ ],
+ "productCategory": {
+ "productCategoryId": 1,
+ "isTravelProduct": true,
+ "name": "Kortingsabonnement"
+ },
+ "requiredCustomerLevel": {
+ "requiredCustomerLevelId": 3,
+ "name": "profile"
+ },
+ "requiredProducts": null,
+ "incompatibleProducts": null,
+ "mandatoryCustomerDataItems": [
+ {
+ "mandatoryCustomerDataItemId": 1,
+ "customerDataItem": "birthname"
+ },
+ {
+ "mandatoryCustomerDataItemId": 2,
+ "customerDataItem": "surname"
+ },
+ {
+ "mandatoryCustomerDataItemId": 4,
+ "customerDataItem": "emailAddress"
+ },
+ {
+ "mandatoryCustomerDataItemId": 5,
+ "customerDataItem": "address"
+ }
+ ],
+ "requiredGboPersonalAttributes": null,
+ "tokenTypes": [
+ {
+ "tokenTypeId": 1,
+ "name": "EMV"
+ }
+ ],
+ "paymentMoment": {
+ "paymentMomentId": 1,
+ "name": "prepaid"
+ },
+ "serviceOptions": null,
+ "validityDuration": "P1W",
+ "maxStartInFutureDuration": "P6W",
+ "isRenewable": true,
+ "sendInvoice": true,
+ "imageReference": "https://web.acc.cloud.htm.nl/media/leif2leu/htm-logo-mobile.svg",
+ "productPageUrl": "https://web.acc.cloud.htm.nl/webshop/htm-90-korting/",
+ "termsUrl": "https://web.acc.cloud.htm.nl/reisproducten/productvoorwaarden/htm-90-korting/",
+ "isSellableAtHtm": true,
+ "needsSolvencyCheckConsumer": false,
+ "needsSolvencyCheckBusiness": false,
+ "sellingPeriods": [
+ {
+ "sellingPeriodId": 89,
+ "fromInclusive": "2024-09-30T23:00:00.000+00:00",
+ "toInclusive": "2029-12-01T23:00:00.000+00:00",
+ "salesTouchpoint": {
+ "salesTouchpointId": 3,
+ "name": "Website (Perplex)",
+ "isActive": true,
+ "retailer": {
+ "retailerId": 1001,
+ "name": "HTM externe touchpoints",
+ "street": "Koningin Julianaplein",
+ "number": 10,
+ "numberAddition": null,
+ "postalCode": "2595 AA",
+ "city": "Den Haag",
+ "country": "Nederland",
+ "emailAddress": "info@htm.nl",
+ "phoneNumber": "070 374 9002",
+ "taxId": 572309345923,
+ "imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg"
+ }
+ },
+ "forbiddenPaymentMethods": null,
+ "sellingPrices": [
+ {
+ "sellingPriceId": 82,
+ "amountExclTax": 92,
+ "amountInclTax": 100,
+ "fromInclusive": "2024-09-30T23:00:00.000+00:00",
+ "toInclusive": "2029-12-01T23:00:00.000+00:00",
+ "internalPrice": 0.0000,
+ "taxMetadata": {
+ "taxMetadataId": "47C8972E-A730-4032-9BDA-AF0A5BCB2C85",
+ "taxCode": "V09",
+ "taxPercentageAmount": 9,
+ "description": "BTW VERKOOP LAAG 9%"
+ }
+ }
+ ]
+ }
+ ],
+ "purchasePrices": null,
+ "auditTrail": [
+ {
+ "auditTrailId": 162,
+ "action": "insert",
+ "user": "api",
+ "timestamp": "2024-11-25T08:39:36.793+00:00"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/java/ABTProductsPUTGenerator/src/main/resources/log4j2.xml b/src/java/ABTProductsPUTGenerator/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..47eb2d8
--- /dev/null
+++ b/src/java/ABTProductsPUTGenerator/src/main/resources/log4j2.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+