From 18517236f8e852970dba92f0272b2ca6f608393c Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 11:46:28 +0200 Subject: [PATCH 01/23] added ReportSpecification --- .../entity/ReportSpecification.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java new file mode 100644 index 0000000..08824eb --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java @@ -0,0 +1,22 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; +import java.time.LocalDate; +import java.util.List; + +@Data +public class ReportSpecification { + private ReportType reportType; + private List reportOptions; + private LocalDate dataStartTime; + private LocalDate dataEndTime; + private List marketplaceIds; + + public enum ReportType { + GET_SALES_AND_TRAFFIC_REPORT + } + + public enum ReportOption { + DAY, PARENT + } +} From 2a3a96b9b1568a11e18141e61e658047a474bb43 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 12:50:22 +0200 Subject: [PATCH 02/23] added all classes --- .../entity/AverageSalesPerOrderItem.java | 4 +++ .../entity/AverageSalesPerOrderItemB2B.java | 4 +++ .../entity/AverageSellingPrice.java | 4 +++ .../entity/AverageSellingPriceB2B.java | 4 +++ .../entity/ClaimsAmount.java | 4 +++ .../entity/OrderedProductSales.java | 7 ++++ .../entity/OrderedProductSalesB2B.java | 7 ++++ .../entity/ReportOption.java | 10 ++++++ .../entity/ReportSpecification.java | 6 +--- .../entity/SaleAndTrafficByDate.java | 11 ++++++ .../entity/SaleParams.java | 15 ++++++++ .../entity/SalesAndTrafficByAsin.java | 10 ++++++ .../entity/SalesByAsin.java | 13 +++++++ .../entity/SalesByDate.java | 27 ++++++++++++++ .../entity/ShippedProductSales.java | 4 +++ .../entity/TrafficByAsin.java | 35 +++++++++++++++++++ .../entity/TrafficByDate.java | 30 ++++++++++++++++ 17 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/ReportOption.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/SaleParams.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/SalesByDate.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java b/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java new file mode 100644 index 0000000..7d6e40c --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity; + +public class AverageSalesPerOrderItem extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java b/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java new file mode 100644 index 0000000..0375d70 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity; + +public class AverageSalesPerOrderItemB2B extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java b/src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java new file mode 100644 index 0000000..f782857 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity; + +public class AverageSellingPrice extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java b/src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java new file mode 100644 index 0000000..1492e81 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity; + +public class AverageSellingPriceB2B extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java b/src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java new file mode 100644 index 0000000..42857b7 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity; + +public class ClaimsAmount extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java new file mode 100644 index 0000000..9f811f6 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java @@ -0,0 +1,7 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class OrderedProductSales extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java new file mode 100644 index 0000000..489415c --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java @@ -0,0 +1,7 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class OrderedProductSalesB2B extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportOption.java b/src/main/java/com/app/sellerretailreports/entity/ReportOption.java new file mode 100644 index 0000000..a8059df --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/ReportOption.java @@ -0,0 +1,10 @@ +package com.app.sellerretailreports.entity; + +public class ReportOption { + private Granularity dateGranularity; + private Granularity asinGranularity; + + public enum Granularity { + DAY, PARENT + } +} diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java index 08824eb..3171673 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java +++ b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java @@ -7,7 +7,7 @@ @Data public class ReportSpecification { private ReportType reportType; - private List reportOptions; + private ReportOption reportOptions; private LocalDate dataStartTime; private LocalDate dataEndTime; private List marketplaceIds; @@ -15,8 +15,4 @@ public class ReportSpecification { public enum ReportType { GET_SALES_AND_TRAFFIC_REPORT } - - public enum ReportOption { - DAY, PARENT - } } diff --git a/src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java new file mode 100644 index 0000000..3fb4873 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java @@ -0,0 +1,11 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; +import java.time.LocalDate; + +@Data +public class SaleAndTrafficByDate { + private LocalDate date; + private SalesByDate salesByDate; + private TrafficByDate trafficByDate; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java b/src/main/java/com/app/sellerretailreports/entity/SaleParams.java new file mode 100644 index 0000000..665f801 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/SaleParams.java @@ -0,0 +1,15 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class SaleParams { + private BigDecimal amount; + private CurrencyCode currencyCode; + + public enum CurrencyCode { + USD + } +} diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java new file mode 100644 index 0000000..42b913a --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java @@ -0,0 +1,10 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class SalesAndTrafficByAsin { + private String parentAsin; + private SalesByAsin salesByAsin; + private TrafficByAsin trafficByAsin; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java new file mode 100644 index 0000000..d45b64f --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java @@ -0,0 +1,13 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class SalesByAsin { + private int unitsOrdered; + private int unitsOrderedB2B; + private OrderedProductSales orderedProductSales; + private OrderedProductSalesB2B orderedProductSalesB2B; + private int totalOrderItems; + private int totalOrderItemsB2B; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java b/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java new file mode 100644 index 0000000..03447dd --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java @@ -0,0 +1,27 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class SalesByDate { + private OrderedProductSales orderedProductSales; + private OrderedProductSalesB2B orderedProductSalesB2B; + private int unitsOrdered; + private int getUnitsOrderedB2B; + private int totalOrderItems; + private int totalOrderItemsB2B; + private AverageSalesPerOrderItem averageSalesPerOrderItem; + private AverageSalesPerOrderItemB2B averageSalesPerOrderItemB2B; + private BigDecimal averageUnitsPerOrderItem; + private BigDecimal averageUnitsPerOrderItemB2B; + private AverageSellingPrice averageSellingPrice; + private AverageSellingPriceB2B averageSellingPriceB2B; + private int unitsRefunded; + private BigDecimal refundRate; + private int claimsGranted; + private ShippedProductSales shippedProductSales; + private int unitsShipped; + private int ordersShipped; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java b/src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java new file mode 100644 index 0000000..9649090 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity; + +public class ShippedProductSales extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java new file mode 100644 index 0000000..0e5b68a --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java @@ -0,0 +1,35 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class TrafficByAsin { + private int browserSessions; + private int browserSessionsB2B; + private int mobileAppSessions; + private int mobileAppSessionsB2B; + private int sessions; + private int sessionsB2B; + private double browserSessionPercentage; + private double browserSessionPercentageB2B; + private double mobileAppSessionPercentage; + private double mobileAppSessionPercentageB2B; + private double sessionPercentage; + private double sessionPercentageB2B; + private int browserPageViews; + private int browserPageViewsB2B; + private int mobileAppPageViews; + private int mobileAppPageViewsB2B; + private int pageViews; + private int pageViewsB2B; + private double browserPageViewsPercentage; + private double browserPageViewsPercentageB2B; + private double mobileAppPageViewsPercentage; + private double mobileAppPageViewsPercentageB2B; + private double pageViewsPercentage; + private double pageViewsPercentageB2B; + private double buyBoxPercentage; + private double buyBoxPercentageB2B; + private double unitSessionPercentage; + private double unitSessionPercentageB2B; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java new file mode 100644 index 0000000..721d7ca --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java @@ -0,0 +1,30 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class TrafficByDate { + private int browserPageViews; + private int browserPageViewsB2B; + private int mobileAppPageViews; + private int mobileAppPageViewsB2B; + private int pageViews; + private int pageViewsB2B; + private int browserSessions; + private int browserSessionsB2B; + private int mobileAppSessions; + private int mobileAppSessionsB2B; + private int sessions; + private int sessionsB2B; + private double buyBoxPercentage; + private double buyBoxPercentageB2B; + private double orderItemSessionPercentage; + private double orderItemSessionPercentageB2B; + private double unitSessionPercentage; + private double unitSessionPercentageB2B; + private int averageOfferCount; + private int averageParentItems; + private int feedbackReceived; + private int negativeFeedbackReceived; + private double receivedNegativeFeedbackRate; +} From 02048393ba85fedb9c2e94368a4e49c7c2e2c325 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 13:09:37 +0200 Subject: [PATCH 03/23] added dependencies and health endpoint --- pom.xml | 11 ++++++----- .../controller/HealthController.java | 12 ++++++++++++ .../entity/SalesAndTrafficReport.java | 10 ++++++++++ .../repository/ReportRepository.java | 9 +++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/controller/HealthController.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java create mode 100644 src/main/java/com/app/sellerretailreports/repository/ReportRepository.java diff --git a/pom.xml b/pom.xml index 6c2365c..778c68e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ seller-retail-reports 17 + 3.12.14 @@ -34,17 +35,17 @@ org.springframework.boot spring-boot-starter-data-mongodb + + org.mongodb + mongo-java-driver + ${mongodb.version} + org.projectlombok lombok true - - org.springframework.boot - spring-boot-starter-test - test - diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java new file mode 100644 index 0000000..1706e90 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -0,0 +1,12 @@ +package com.app.sellerretailreports.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthController { + @GetMapping("/health") + public String getHealth() { + return "API working..."; + } +} diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java new file mode 100644 index 0000000..9c1344a --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java @@ -0,0 +1,10 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; + +@Data +public class SalesAndTrafficReport { + private ReportSpecification reportSpecification; + private SaleAndTrafficByDate saleAndTrafficByDate; + private SalesAndTrafficByAsin salesAndTrafficByAsin; +} diff --git a/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java b/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java new file mode 100644 index 0000000..fea8a9c --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java @@ -0,0 +1,9 @@ +package com.app.sellerretailreports.repository; + +import com.app.sellerretailreports.entity.SalesAndTrafficReport; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReportRepository extends MongoRepository { +} From 440037645cc98cc28da33c2b1bc5a29709522fe1 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 15:00:18 +0200 Subject: [PATCH 04/23] test commit --- .../controller/HealthController.java | 9 +++++++++ .../com/app/sellerretailreports/entity/Obj.java | 14 ++++++++++++++ .../entity/OrderedProductSales.java | 1 - .../entity/OrderedProductSalesB2B.java | 1 - .../sellerretailreports/entity/ReportOption.java | 7 +++++++ .../entity/ReportSpecification.java | 4 ++++ .../sellerretailreports/entity/SaleParams.java | 3 +++ .../entity/SalesAndTrafficByAsin.java | 3 +++ ...fficByDate.java => SalesAndTrafficByDate.java} | 6 +++++- .../entity/SalesAndTrafficReport.java | 2 +- .../repository/TestRepository.java | 10 ++++++++++ .../service/ReportService.java | 9 +++++++++ .../service/ReportServiceImpl.java | 15 +++++++++++++++ src/main/resources/application.properties | 7 +++++++ 14 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/entity/Obj.java rename src/main/java/com/app/sellerretailreports/entity/{SaleAndTrafficByDate.java => SalesAndTrafficByDate.java} (61%) create mode 100644 src/main/java/com/app/sellerretailreports/repository/TestRepository.java create mode 100644 src/main/java/com/app/sellerretailreports/service/ReportService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java index 1706e90..650484c 100644 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -1,9 +1,18 @@ package com.app.sellerretailreports.controller; +import com.app.sellerretailreports.entity.Obj; +import com.app.sellerretailreports.entity.SalesAndTrafficReport; +import com.app.sellerretailreports.service.ReportService; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RestController +@RequiredArgsConstructor public class HealthController { @GetMapping("/health") public String getHealth() { diff --git a/src/main/java/com/app/sellerretailreports/entity/Obj.java b/src/main/java/com/app/sellerretailreports/entity/Obj.java new file mode 100644 index 0000000..987188e --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/Obj.java @@ -0,0 +1,14 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.MongoId; + +@Data +@Document(collection = "objects") +public class Obj { + @Id + private String id; + private String string; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java index 9f811f6..8968c53 100644 --- a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java +++ b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java @@ -2,6 +2,5 @@ import lombok.Data; -@Data public class OrderedProductSales extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java index 489415c..da452cf 100644 --- a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java +++ b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java @@ -2,6 +2,5 @@ import lombok.Data; -@Data public class OrderedProductSalesB2B extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportOption.java b/src/main/java/com/app/sellerretailreports/entity/ReportOption.java index a8059df..6c159f9 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ReportOption.java +++ b/src/main/java/com/app/sellerretailreports/entity/ReportOption.java @@ -1,7 +1,14 @@ package com.app.sellerretailreports.entity; +import lombok.Data; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.FieldType; + +@Data public class ReportOption { + @Field(targetType = FieldType.STRING) private Granularity dateGranularity; + @Field(targetType = FieldType.STRING) private Granularity asinGranularity; public enum Granularity { diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java index 3171673..8aba30b 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java +++ b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java @@ -1,11 +1,15 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.FieldType; + import java.time.LocalDate; import java.util.List; @Data public class ReportSpecification { + @Field(targetType = FieldType.STRING) private ReportType reportType; private ReportOption reportOptions; private LocalDate dataStartTime; diff --git a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java b/src/main/java/com/app/sellerretailreports/entity/SaleParams.java index 665f801..9a6fb64 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java +++ b/src/main/java/com/app/sellerretailreports/entity/SaleParams.java @@ -1,12 +1,15 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.FieldType; import java.math.BigDecimal; @Data public class SaleParams { private BigDecimal amount; + @Field(targetType = FieldType.STRING) private CurrencyCode currencyCode; public enum CurrencyCode { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java index 42b913a..b2c1e6a 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java @@ -1,9 +1,12 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; @Data public class SalesAndTrafficByAsin { + @Id + private Long id; private String parentAsin; private SalesByAsin salesByAsin; private TrafficByAsin trafficByAsin; diff --git a/src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java similarity index 61% rename from src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java rename to src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java index 3fb4873..0e290d0 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SaleAndTrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java @@ -1,10 +1,14 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; + import java.time.LocalDate; @Data -public class SaleAndTrafficByDate { +public class SalesAndTrafficByDate { + @Id + private Long id; private LocalDate date; private SalesByDate salesByDate; private TrafficByDate trafficByDate; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java index 9c1344a..0894961 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java @@ -5,6 +5,6 @@ @Data public class SalesAndTrafficReport { private ReportSpecification reportSpecification; - private SaleAndTrafficByDate saleAndTrafficByDate; + private SalesAndTrafficByDate salesAndTrafficByDate; private SalesAndTrafficByAsin salesAndTrafficByAsin; } diff --git a/src/main/java/com/app/sellerretailreports/repository/TestRepository.java b/src/main/java/com/app/sellerretailreports/repository/TestRepository.java new file mode 100644 index 0000000..a9bad4d --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/repository/TestRepository.java @@ -0,0 +1,10 @@ +package com.app.sellerretailreports.repository; + +import com.app.sellerretailreports.entity.Obj; +import com.app.sellerretailreports.entity.SalesAndTrafficReport; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TestRepository extends MongoRepository { +} diff --git a/src/main/java/com/app/sellerretailreports/service/ReportService.java b/src/main/java/com/app/sellerretailreports/service/ReportService.java new file mode 100644 index 0000000..f9ac9f2 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/ReportService.java @@ -0,0 +1,9 @@ +package com.app.sellerretailreports.service; + +import com.app.sellerretailreports.entity.Obj; +import com.app.sellerretailreports.entity.SalesAndTrafficReport; + +import java.util.List; + +public interface ReportService { +} diff --git a/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java new file mode 100644 index 0000000..c43b7e9 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java @@ -0,0 +1,15 @@ +package com.app.sellerretailreports.service; + +import com.app.sellerretailreports.entity.Obj; +import com.app.sellerretailreports.entity.SalesAndTrafficReport; +import com.app.sellerretailreports.repository.ReportRepository; +import com.app.sellerretailreports.repository.TestRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ReportServiceImpl implements ReportService { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4d360de..f49cae7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,8 @@ +spring.data.mongodb.host=localhost +spring.data.mongodb.port=27017 +#spring.data.mongodb.authentication-database=admin +#spring.data.mongodb.username=root +spring.data.mongodb.password=password +spring.data.mongodb.database=report_db + server.port=8081 From c97034d4a2739e63d217d527c233d49f7758731a Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 18:05:20 +0200 Subject: [PATCH 05/23] stable version --- pom.xml | 6 +++--- .../controller/HealthController.java | 6 ++---- .../entity/SalesAndTrafficByAsin.java | 2 -- .../entity/SalesAndTrafficByDate.java | 2 -- .../entity/SalesAndTrafficReport.java | 11 +++++++++-- .../app/sellerretailreports/entity/SalesByAsin.java | 1 + .../app/sellerretailreports/entity/SalesByDate.java | 1 + .../app/sellerretailreports/entity/TrafficByAsin.java | 1 + .../app/sellerretailreports/entity/TrafficByDate.java | 1 + .../repository/TestRepository.java | 10 ---------- .../service/ReportServiceImpl.java | 6 ------ 11 files changed, 18 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/com/app/sellerretailreports/repository/TestRepository.java diff --git a/pom.xml b/pom.xml index 778c68e..3aae94b 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ seller-retail-reports 17 - 3.12.14 + @@ -35,11 +35,11 @@ org.springframework.boot spring-boot-starter-data-mongodb - + org.projectlombok diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java index 650484c..90fd54e 100644 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -1,16 +1,14 @@ package com.app.sellerretailreports.controller; -import com.app.sellerretailreports.entity.Obj; import com.app.sellerretailreports.entity.SalesAndTrafficReport; -import com.app.sellerretailreports.service.ReportService; +import com.app.sellerretailreports.entity.SalesByDate; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @RestController @RequiredArgsConstructor public class HealthController { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java index b2c1e6a..e01c177 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java @@ -5,8 +5,6 @@ @Data public class SalesAndTrafficByAsin { - @Id - private Long id; private String parentAsin; private SalesByAsin salesByAsin; private TrafficByAsin trafficByAsin; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java index 0e290d0..eabdf4f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java @@ -7,8 +7,6 @@ @Data public class SalesAndTrafficByDate { - @Id - private Long id; private LocalDate date; private SalesByDate salesByDate; private TrafficByDate trafficByDate; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java index 0894961..3d503b7 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java @@ -1,10 +1,17 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.List; @Data +@Document(collection = "objects") public class SalesAndTrafficReport { + @Id + private String id; private ReportSpecification reportSpecification; - private SalesAndTrafficByDate salesAndTrafficByDate; - private SalesAndTrafficByAsin salesAndTrafficByAsin; + private List salesAndTrafficByDate; + private List salesAndTrafficByAsin; } diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java index d45b64f..1d84275 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java @@ -1,6 +1,7 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; @Data public class SalesByAsin { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java b/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java index 03447dd..04a3251 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java @@ -1,6 +1,7 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; import java.math.BigDecimal; diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java index 0e5b68a..70706f1 100644 --- a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java @@ -1,6 +1,7 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; @Data public class TrafficByAsin { diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java index 721d7ca..e53ecc5 100644 --- a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java @@ -1,6 +1,7 @@ package com.app.sellerretailreports.entity; import lombok.Data; +import org.springframework.data.annotation.Id; @Data public class TrafficByDate { diff --git a/src/main/java/com/app/sellerretailreports/repository/TestRepository.java b/src/main/java/com/app/sellerretailreports/repository/TestRepository.java deleted file mode 100644 index a9bad4d..0000000 --- a/src/main/java/com/app/sellerretailreports/repository/TestRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.app.sellerretailreports.repository; - -import com.app.sellerretailreports.entity.Obj; -import com.app.sellerretailreports.entity.SalesAndTrafficReport; -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface TestRepository extends MongoRepository { -} diff --git a/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java index c43b7e9..c88addb 100644 --- a/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java @@ -1,14 +1,8 @@ package com.app.sellerretailreports.service; -import com.app.sellerretailreports.entity.Obj; -import com.app.sellerretailreports.entity.SalesAndTrafficReport; -import com.app.sellerretailreports.repository.ReportRepository; -import com.app.sellerretailreports.repository.TestRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.List; - @Service @RequiredArgsConstructor public class ReportServiceImpl implements ReportService { From 534502cdd29fbc5eed7b93da2a7f5e29da9d5c49 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 18:14:22 +0200 Subject: [PATCH 06/23] checkstyle fixed --- .github/workflows/ci.yml | 18 ++ checkstyle.xml | 250 ++++++++++++++++++ pom.xml | 31 ++- .../SellerRetailReportsApplication.java | 8 +- .../controller/HealthController.java | 5 - .../app/sellerretailreports/entity/Obj.java | 1 - .../entity/OrderedProductSales.java | 2 - .../entity/OrderedProductSalesB2B.java | 2 - .../entity/ReportSpecification.java | 5 +- .../entity/SaleParams.java | 3 +- .../entity/SalesAndTrafficByAsin.java | 1 - .../entity/SalesAndTrafficByDate.java | 4 +- .../entity/SalesAndTrafficReport.java | 3 +- .../entity/SalesByAsin.java | 1 - .../entity/SalesByDate.java | 4 +- .../entity/TrafficByAsin.java | 1 - .../entity/TrafficByDate.java | 1 - .../service/ReportService.java | 5 - .../SellerRetailReportsApplicationTests.java | 8 +- 19 files changed, 302 insertions(+), 51 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 checkstyle.xml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7e75529 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,18 @@ +name: Java CI + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 17 + uses: actions/setup-java@v2 + with: + java-version: '17' + distribution: 'adopt' + cache: maven + - name: Build with Maven + run: mvn --batch-mode --update-snapshots verify diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..9186968 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 3aae94b..156c69c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent 3.2.3 - + com.app seller-retail-reports @@ -14,8 +14,8 @@ seller-retail-reports seller-retail-reports + checkstyle.xml 17 - @@ -35,22 +35,35 @@ org.springframework.boot spring-boot-starter-data-mongodb - - org.projectlombok lombok true - + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.3.0 + + + compile + + check + + + + + ${maven.checkstyle.plugin.configLocation} + true + true + false + src + + org.springframework.boot spring-boot-maven-plugin diff --git a/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java b/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java index 1285d08..b930c73 100644 --- a/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java +++ b/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java @@ -5,9 +5,7 @@ @SpringBootApplication public class SellerRetailReportsApplication { - - public static void main(String[] args) { - SpringApplication.run(SellerRetailReportsApplication.class, args); - } - + public static void main(String[] args) { + SpringApplication.run(SellerRetailReportsApplication.class, args); + } } diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java index 90fd54e..6991279 100644 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -1,12 +1,7 @@ package com.app.sellerretailreports.controller; -import com.app.sellerretailreports.entity.SalesAndTrafficReport; -import com.app.sellerretailreports.entity.SalesByDate; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController diff --git a/src/main/java/com/app/sellerretailreports/entity/Obj.java b/src/main/java/com/app/sellerretailreports/entity/Obj.java index 987188e..8c9274f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/Obj.java +++ b/src/main/java/com/app/sellerretailreports/entity/Obj.java @@ -3,7 +3,6 @@ import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.data.mongodb.core.mapping.MongoId; @Data @Document(collection = "objects") diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java index 8968c53..183f346 100644 --- a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java +++ b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java @@ -1,6 +1,4 @@ package com.app.sellerretailreports.entity; -import lombok.Data; - public class OrderedProductSales extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java index da452cf..cb81744 100644 --- a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java +++ b/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java @@ -1,6 +1,4 @@ package com.app.sellerretailreports.entity; -import lombok.Data; - public class OrderedProductSalesB2B extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java index 8aba30b..26e0e5a 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java +++ b/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java @@ -1,12 +1,11 @@ package com.app.sellerretailreports.entity; +import java.time.LocalDate; +import java.util.List; import lombok.Data; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.FieldType; -import java.time.LocalDate; -import java.util.List; - @Data public class ReportSpecification { @Field(targetType = FieldType.STRING) diff --git a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java b/src/main/java/com/app/sellerretailreports/entity/SaleParams.java index 9a6fb64..5336c6f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java +++ b/src/main/java/com/app/sellerretailreports/entity/SaleParams.java @@ -1,11 +1,10 @@ package com.app.sellerretailreports.entity; +import java.math.BigDecimal; import lombok.Data; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.FieldType; -import java.math.BigDecimal; - @Data public class SaleParams { private BigDecimal amount; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java index e01c177..42b913a 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java @@ -1,7 +1,6 @@ package com.app.sellerretailreports.entity; import lombok.Data; -import org.springframework.data.annotation.Id; @Data public class SalesAndTrafficByAsin { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java index eabdf4f..693aa0b 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java @@ -1,9 +1,7 @@ package com.app.sellerretailreports.entity; -import lombok.Data; -import org.springframework.data.annotation.Id; - import java.time.LocalDate; +import lombok.Data; @Data public class SalesAndTrafficByDate { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java index 3d503b7..e245177 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java @@ -1,11 +1,10 @@ package com.app.sellerretailreports.entity; +import java.util.List; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; -import java.util.List; - @Data @Document(collection = "objects") public class SalesAndTrafficReport { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java b/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java index 1d84275..d45b64f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java @@ -1,7 +1,6 @@ package com.app.sellerretailreports.entity; import lombok.Data; -import org.springframework.data.annotation.Id; @Data public class SalesByAsin { diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java b/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java index 04a3251..b19b27a 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java @@ -1,9 +1,7 @@ package com.app.sellerretailreports.entity; -import lombok.Data; -import org.springframework.data.annotation.Id; - import java.math.BigDecimal; +import lombok.Data; @Data public class SalesByDate { diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java index 70706f1..0e5b68a 100644 --- a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java @@ -1,7 +1,6 @@ package com.app.sellerretailreports.entity; import lombok.Data; -import org.springframework.data.annotation.Id; @Data public class TrafficByAsin { diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java index e53ecc5..721d7ca 100644 --- a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java @@ -1,7 +1,6 @@ package com.app.sellerretailreports.entity; import lombok.Data; -import org.springframework.data.annotation.Id; @Data public class TrafficByDate { diff --git a/src/main/java/com/app/sellerretailreports/service/ReportService.java b/src/main/java/com/app/sellerretailreports/service/ReportService.java index f9ac9f2..cf0aa08 100644 --- a/src/main/java/com/app/sellerretailreports/service/ReportService.java +++ b/src/main/java/com/app/sellerretailreports/service/ReportService.java @@ -1,9 +1,4 @@ package com.app.sellerretailreports.service; -import com.app.sellerretailreports.entity.Obj; -import com.app.sellerretailreports.entity.SalesAndTrafficReport; - -import java.util.List; - public interface ReportService { } diff --git a/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java b/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java index c9c01b5..6290415 100644 --- a/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java +++ b/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java @@ -5,9 +5,7 @@ @SpringBootTest class SellerRetailReportsApplicationTests { - - @Test - void contextLoads() { - } - + @Test + void contextLoads() { + } } From 99db313ddb4a2a088e93e7cd7295416963475ac2 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 19:05:03 +0200 Subject: [PATCH 07/23] added jwt authentication --- pom.xml | 69 +++++++++++++++++++ .../config/MapperConfig.java | 13 ++++ .../controller/AuthenticationController.java | 34 +++++++++ .../dto/user/UserLoginRequestDto.java | 14 ++++ .../dto/user/UserLoginResponseDto.java | 8 +++ .../dto/user/UserRegisterRequestDto.java | 27 ++++++++ .../dto/user/UserRegisterResponseDto.java | 11 +++ .../entity/ClaimsAmount.java | 4 -- .../app/sellerretailreports/entity/Obj.java | 13 ---- .../app/sellerretailreports/entity/User.java | 20 ++++++ .../AverageSalesPerOrderItem.java | 2 +- .../AverageSalesPerOrderItemB2B.java | 2 +- .../{ => report}/AverageSellingPrice.java | 2 +- .../{ => report}/AverageSellingPriceB2B.java | 2 +- .../entity/report/ClaimsAmount.java | 4 ++ .../{ => report}/OrderedProductSales.java | 2 +- .../{ => report}/OrderedProductSalesB2B.java | 2 +- .../entity/{ => report}/ReportOption.java | 2 +- .../{ => report}/ReportSpecification.java | 2 +- .../entity/{ => report}/SaleParams.java | 2 +- .../{ => report}/SalesAndTrafficByAsin.java | 2 +- .../{ => report}/SalesAndTrafficByDate.java | 2 +- .../{ => report}/SalesAndTrafficReport.java | 2 +- .../entity/{ => report}/SalesByAsin.java | 2 +- .../entity/{ => report}/SalesByDate.java | 2 +- .../{ => report}/ShippedProductSales.java | 2 +- .../entity/{ => report}/TrafficByAsin.java | 2 +- .../entity/{ => report}/TrafficByDate.java | 2 +- .../exception/RegistrationException.java | 11 +++ .../mapper/UserMapper.java | 14 ++++ .../repository/ReportRepository.java | 2 +- .../repository/user/UserRepository.java | 11 +++ .../security/AuthenticationService.java | 27 ++++++++ .../security/JwtAuthenticationFilter.java | 52 ++++++++++++++ .../sellerretailreports/security/JwtUtil.java | 59 ++++++++++++++++ .../security/SecurityConfig.java | 63 +++++++++++++++++ .../service/user/UserService.java | 9 +++ .../service/user/UserServiceImpl.java | 32 +++++++++ .../validation/FieldMatch.java | 17 +++++ .../PasswordAndRepeatPasswordValidator.java | 15 ++++ src/main/resources/application.properties | 6 +- 41 files changed, 530 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/config/MapperConfig.java create mode 100644 src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/user/UserLoginRequestDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/user/UserLoginResponseDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/user/UserRegisterRequestDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/user/UserRegisterResponseDto.java delete mode 100644 src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java delete mode 100644 src/main/java/com/app/sellerretailreports/entity/Obj.java create mode 100644 src/main/java/com/app/sellerretailreports/entity/User.java rename src/main/java/com/app/sellerretailreports/entity/{ => report}/AverageSalesPerOrderItem.java (52%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/AverageSalesPerOrderItemB2B.java (54%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/AverageSellingPrice.java (50%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/AverageSellingPriceB2B.java (52%) create mode 100644 src/main/java/com/app/sellerretailreports/entity/report/ClaimsAmount.java rename src/main/java/com/app/sellerretailreports/entity/{ => report}/OrderedProductSales.java (50%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/OrderedProductSalesB2B.java (52%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/ReportOption.java (85%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/ReportSpecification.java (88%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/SaleParams.java (84%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/SalesAndTrafficByAsin.java (74%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/SalesAndTrafficByDate.java (76%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/SalesAndTrafficReport.java (86%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/SalesByAsin.java (82%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/SalesByDate.java (92%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/ShippedProductSales.java (50%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/TrafficByAsin.java (93%) rename src/main/java/com/app/sellerretailreports/entity/{ => report}/TrafficByDate.java (91%) create mode 100644 src/main/java/com/app/sellerretailreports/exception/RegistrationException.java create mode 100644 src/main/java/com/app/sellerretailreports/mapper/UserMapper.java create mode 100644 src/main/java/com/app/sellerretailreports/repository/user/UserRepository.java create mode 100644 src/main/java/com/app/sellerretailreports/security/AuthenticationService.java create mode 100644 src/main/java/com/app/sellerretailreports/security/JwtAuthenticationFilter.java create mode 100644 src/main/java/com/app/sellerretailreports/security/JwtUtil.java create mode 100644 src/main/java/com/app/sellerretailreports/security/SecurityConfig.java create mode 100644 src/main/java/com/app/sellerretailreports/service/user/UserService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/user/UserServiceImpl.java create mode 100644 src/main/java/com/app/sellerretailreports/validation/FieldMatch.java create mode 100644 src/main/java/com/app/sellerretailreports/validation/PasswordAndRepeatPasswordValidator.java diff --git a/pom.xml b/pom.xml index 156c69c..ff806ce 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,10 @@ checkstyle.xml 17 + 0.12.5 + 0.2.0 + 1.5.5.Final + 2.3.0 @@ -35,11 +39,51 @@ org.springframework.boot spring-boot-starter-data-mongodb + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${openapi.version} + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + runtime + ${jjwt.version} + + + io.jsonwebtoken + jjwt-jackson + runtime + ${jjwt.version} + org.projectlombok lombok true + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.projectlombok + lombok-mapstruct-binding + ${lombok.mapstruct.binding.version} + @@ -76,6 +120,31 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + org.projectlombok + lombok + ${lombok.version} + + + org.projectlombok + lombok-mapstruct-binding + ${lombok.mapstruct.binding.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + diff --git a/src/main/java/com/app/sellerretailreports/config/MapperConfig.java b/src/main/java/com/app/sellerretailreports/config/MapperConfig.java new file mode 100644 index 0000000..149a0d6 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/config/MapperConfig.java @@ -0,0 +1,13 @@ +package com.app.sellerretailreports.config; + +import org.mapstruct.InjectionStrategy; +import org.mapstruct.NullValueCheckStrategy; + +@org.mapstruct.MapperConfig( + componentModel = "spring", + injectionStrategy = InjectionStrategy.CONSTRUCTOR, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + implementationPackage = ".impl" +) +public class MapperConfig { +} diff --git a/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java b/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java new file mode 100644 index 0000000..e5742a8 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java @@ -0,0 +1,34 @@ +package com.app.sellerretailreports.controller; + +import com.app.sellerretailreports.dto.user.UserLoginRequestDto; +import com.app.sellerretailreports.dto.user.UserLoginResponseDto; +import com.app.sellerretailreports.dto.user.UserRegisterRequestDto; +import com.app.sellerretailreports.dto.user.UserRegisterResponseDto; +import com.app.sellerretailreports.exception.RegistrationException; +import com.app.sellerretailreports.security.AuthenticationService; +import com.app.sellerretailreports.service.user.UserService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/auth") +public class AuthenticationController { + private final UserService userService; + private final AuthenticationService authenticationService; + + @PostMapping(value = "/login") + public UserLoginResponseDto login(@RequestBody @Valid UserLoginRequestDto requestDto) { + return authenticationService.authenticate(requestDto); + } + + @PostMapping(value = "/register") + public UserRegisterResponseDto register(@RequestBody @Valid UserRegisterRequestDto requestDto) + throws RegistrationException { + return userService.register(requestDto); + } +} diff --git a/src/main/java/com/app/sellerretailreports/dto/user/UserLoginRequestDto.java b/src/main/java/com/app/sellerretailreports/dto/user/UserLoginRequestDto.java new file mode 100644 index 0000000..809c780 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/user/UserLoginRequestDto.java @@ -0,0 +1,14 @@ +package com.app.sellerretailreports.dto.user; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +@Data +public class UserLoginRequestDto { + @NotBlank + private String email; + @NotBlank + @Length(min = 8, max = 35, message = "should be between 8 and 35 letters and symbols") + private String password; +} diff --git a/src/main/java/com/app/sellerretailreports/dto/user/UserLoginResponseDto.java b/src/main/java/com/app/sellerretailreports/dto/user/UserLoginResponseDto.java new file mode 100644 index 0000000..3406842 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/user/UserLoginResponseDto.java @@ -0,0 +1,8 @@ +package com.app.sellerretailreports.dto.user; + +import lombok.Data; + +@Data +public class UserLoginResponseDto { + private String token; +} diff --git a/src/main/java/com/app/sellerretailreports/dto/user/UserRegisterRequestDto.java b/src/main/java/com/app/sellerretailreports/dto/user/UserRegisterRequestDto.java new file mode 100644 index 0000000..94b6368 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/user/UserRegisterRequestDto.java @@ -0,0 +1,27 @@ +package com.app.sellerretailreports.dto.user; + +import com.app.sellerretailreports.validation.FieldMatch; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +@Data +@FieldMatch +public class UserRegisterRequestDto { + @NotBlank + @Email + private String email; + @NotBlank + @Length(min = 8, max = 35, message = "should be between 8 and 35 letters and symbols") + private String password; + @NotBlank + @Length(min = 8, max = 35, message = "should be between 8 and 35 letters and symbols") + private String repeatPassword; + @NotBlank + @Length(min = 2, max = 35, message = "should be between 2 and 35 letters") + private String firstName; + @NotBlank + @Length(min = 2, max = 35, message = "should be between 2 and 35 letters") + private String lastName; +} diff --git a/src/main/java/com/app/sellerretailreports/dto/user/UserRegisterResponseDto.java b/src/main/java/com/app/sellerretailreports/dto/user/UserRegisterResponseDto.java new file mode 100644 index 0000000..b52f6ef --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/user/UserRegisterResponseDto.java @@ -0,0 +1,11 @@ +package com.app.sellerretailreports.dto.user; + +import lombok.Data; + +@Data +public class UserRegisterResponseDto { + private String id; + private String email; + private String firstName; + private String lastName; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java b/src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java deleted file mode 100644 index 42857b7..0000000 --- a/src/main/java/com/app/sellerretailreports/entity/ClaimsAmount.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.app.sellerretailreports.entity; - -public class ClaimsAmount extends SaleParams { -} diff --git a/src/main/java/com/app/sellerretailreports/entity/Obj.java b/src/main/java/com/app/sellerretailreports/entity/Obj.java deleted file mode 100644 index 8c9274f..0000000 --- a/src/main/java/com/app/sellerretailreports/entity/Obj.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.app.sellerretailreports.entity; - -import lombok.Data; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; - -@Data -@Document(collection = "objects") -public class Obj { - @Id - private String id; - private String string; -} diff --git a/src/main/java/com/app/sellerretailreports/entity/User.java b/src/main/java/com/app/sellerretailreports/entity/User.java new file mode 100644 index 0000000..efd0f96 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/User.java @@ -0,0 +1,20 @@ +package com.app.sellerretailreports.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document(collection = "users") +public class User { + @Id + private String id; + private String email; + @ToString.Exclude + @EqualsAndHashCode.Exclude + private String password; + private String firstName; + private String lastName; +} diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java b/src/main/java/com/app/sellerretailreports/entity/report/AverageSalesPerOrderItem.java similarity index 52% rename from src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java rename to src/main/java/com/app/sellerretailreports/entity/report/AverageSalesPerOrderItem.java index 7d6e40c..972279f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItem.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/AverageSalesPerOrderItem.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class AverageSalesPerOrderItem extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java b/src/main/java/com/app/sellerretailreports/entity/report/AverageSalesPerOrderItemB2B.java similarity index 54% rename from src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java rename to src/main/java/com/app/sellerretailreports/entity/report/AverageSalesPerOrderItemB2B.java index 0375d70..9be0b4f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/AverageSalesPerOrderItemB2B.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/AverageSalesPerOrderItemB2B.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class AverageSalesPerOrderItemB2B extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java b/src/main/java/com/app/sellerretailreports/entity/report/AverageSellingPrice.java similarity index 50% rename from src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java rename to src/main/java/com/app/sellerretailreports/entity/report/AverageSellingPrice.java index f782857..e393ba4 100644 --- a/src/main/java/com/app/sellerretailreports/entity/AverageSellingPrice.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/AverageSellingPrice.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class AverageSellingPrice extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java b/src/main/java/com/app/sellerretailreports/entity/report/AverageSellingPriceB2B.java similarity index 52% rename from src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java rename to src/main/java/com/app/sellerretailreports/entity/report/AverageSellingPriceB2B.java index 1492e81..776edc6 100644 --- a/src/main/java/com/app/sellerretailreports/entity/AverageSellingPriceB2B.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/AverageSellingPriceB2B.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class AverageSellingPriceB2B extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/report/ClaimsAmount.java b/src/main/java/com/app/sellerretailreports/entity/report/ClaimsAmount.java new file mode 100644 index 0000000..6c4ed1c --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/entity/report/ClaimsAmount.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.entity.report; + +public class ClaimsAmount extends SaleParams { +} diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java b/src/main/java/com/app/sellerretailreports/entity/report/OrderedProductSales.java similarity index 50% rename from src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java rename to src/main/java/com/app/sellerretailreports/entity/report/OrderedProductSales.java index 183f346..b8844e0 100644 --- a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSales.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/OrderedProductSales.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class OrderedProductSales extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java b/src/main/java/com/app/sellerretailreports/entity/report/OrderedProductSalesB2B.java similarity index 52% rename from src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java rename to src/main/java/com/app/sellerretailreports/entity/report/OrderedProductSalesB2B.java index cb81744..18d6e36 100644 --- a/src/main/java/com/app/sellerretailreports/entity/OrderedProductSalesB2B.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/OrderedProductSalesB2B.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class OrderedProductSalesB2B extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportOption.java b/src/main/java/com/app/sellerretailreports/entity/report/ReportOption.java similarity index 85% rename from src/main/java/com/app/sellerretailreports/entity/ReportOption.java rename to src/main/java/com/app/sellerretailreports/entity/report/ReportOption.java index 6c159f9..908c215 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ReportOption.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/ReportOption.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import lombok.Data; import org.springframework.data.mongodb.core.mapping.Field; diff --git a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java b/src/main/java/com/app/sellerretailreports/entity/report/ReportSpecification.java similarity index 88% rename from src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java rename to src/main/java/com/app/sellerretailreports/entity/report/ReportSpecification.java index 26e0e5a..7593f33 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ReportSpecification.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/ReportSpecification.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import java.time.LocalDate; import java.util.List; diff --git a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java b/src/main/java/com/app/sellerretailreports/entity/report/SaleParams.java similarity index 84% rename from src/main/java/com/app/sellerretailreports/entity/SaleParams.java rename to src/main/java/com/app/sellerretailreports/entity/report/SaleParams.java index 5336c6f..90c3ca1 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SaleParams.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SaleParams.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import java.math.BigDecimal; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficByAsin.java similarity index 74% rename from src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java rename to src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficByAsin.java index 42b913a..07bf1bf 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficByAsin.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficByDate.java similarity index 76% rename from src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java rename to src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficByDate.java index 693aa0b..3f9b3cc 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficByDate.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import java.time.LocalDate; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java similarity index 86% rename from src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java rename to src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java index e245177..64c156f 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesAndTrafficReport.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import java.util.List; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesByAsin.java similarity index 82% rename from src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java rename to src/main/java/com/app/sellerretailreports/entity/report/SalesByAsin.java index d45b64f..824f323 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesByAsin.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java similarity index 92% rename from src/main/java/com/app/sellerretailreports/entity/SalesByDate.java rename to src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java index b19b27a..67ca907 100644 --- a/src/main/java/com/app/sellerretailreports/entity/SalesByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import java.math.BigDecimal; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java b/src/main/java/com/app/sellerretailreports/entity/report/ShippedProductSales.java similarity index 50% rename from src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java rename to src/main/java/com/app/sellerretailreports/entity/report/ShippedProductSales.java index 9649090..87774a1 100644 --- a/src/main/java/com/app/sellerretailreports/entity/ShippedProductSales.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/ShippedProductSales.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; public class ShippedProductSales extends SaleParams { } diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java b/src/main/java/com/app/sellerretailreports/entity/report/TrafficByAsin.java similarity index 93% rename from src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java rename to src/main/java/com/app/sellerretailreports/entity/report/TrafficByAsin.java index 0e5b68a..ef35615 100644 --- a/src/main/java/com/app/sellerretailreports/entity/TrafficByAsin.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/TrafficByAsin.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java b/src/main/java/com/app/sellerretailreports/entity/report/TrafficByDate.java similarity index 91% rename from src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java rename to src/main/java/com/app/sellerretailreports/entity/report/TrafficByDate.java index 721d7ca..1178d47 100644 --- a/src/main/java/com/app/sellerretailreports/entity/TrafficByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/TrafficByDate.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.entity; +package com.app.sellerretailreports.entity.report; import lombok.Data; diff --git a/src/main/java/com/app/sellerretailreports/exception/RegistrationException.java b/src/main/java/com/app/sellerretailreports/exception/RegistrationException.java new file mode 100644 index 0000000..15edaf7 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/exception/RegistrationException.java @@ -0,0 +1,11 @@ +package com.app.sellerretailreports.exception; + +public class RegistrationException extends Exception { + public RegistrationException(String message) { + super(message); + } + + public RegistrationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java b/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java new file mode 100644 index 0000000..540854d --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java @@ -0,0 +1,14 @@ +package com.app.sellerretailreports.mapper; + +import com.app.sellerretailreports.dto.user.UserRegisterRequestDto; +import com.app.sellerretailreports.dto.user.UserRegisterResponseDto; +import com.app.sellerretailreports.entity.User; +import org.mapstruct.Mapper; +import org.mapstruct.MapperConfig; + +@Mapper(config = MapperConfig.class) +public interface UserMapper { + UserRegisterResponseDto toDto(User user); + + User toUser(UserRegisterRequestDto requestDto); +} diff --git a/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java b/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java index fea8a9c..83d630d 100644 --- a/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java +++ b/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java @@ -1,6 +1,6 @@ package com.app.sellerretailreports.repository; -import com.app.sellerretailreports.entity.SalesAndTrafficReport; +import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/app/sellerretailreports/repository/user/UserRepository.java b/src/main/java/com/app/sellerretailreports/repository/user/UserRepository.java new file mode 100644 index 0000000..c44c5f5 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/repository/user/UserRepository.java @@ -0,0 +1,11 @@ +package com.app.sellerretailreports.repository.user; + +import com.app.sellerretailreports.entity.User; +import java.util.Optional; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends MongoRepository { + Optional findByEmail(String email); +} diff --git a/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java b/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java new file mode 100644 index 0000000..0832d74 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java @@ -0,0 +1,27 @@ +package com.app.sellerretailreports.security; + +import com.app.sellerretailreports.dto.user.UserLoginRequestDto; +import com.app.sellerretailreports.dto.user.UserLoginResponseDto; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AuthenticationService { + private final JwtUtil jwtUtil; + private final AuthenticationManager authenticationManager; + + public UserLoginResponseDto authenticate(UserLoginRequestDto requestDto) { + final Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(requestDto.getEmail(), requestDto.getPassword()) + ); + + String generatedToken = jwtUtil.generateToken(authentication.getName()); + UserLoginResponseDto responseDto = new UserLoginResponseDto(); + responseDto.setToken(generatedToken); + return responseDto; + } +} diff --git a/src/main/java/com/app/sellerretailreports/security/JwtAuthenticationFilter.java b/src/main/java/com/app/sellerretailreports/security/JwtAuthenticationFilter.java new file mode 100644 index 0000000..0071e02 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/security/JwtAuthenticationFilter.java @@ -0,0 +1,52 @@ +package com.app.sellerretailreports.security; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +@Component +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + private static final String AUTHORIZATION_HEADER_NAME = "Authorization"; + private static final String BEARER_PREFIX = "Bearer "; + private final JwtUtil jwtUtil; + private final UserDetailsService userDetailsService; + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain + ) throws ServletException, IOException { + String token = getToken(request); + if (token != null && jwtUtil.isTokenValid(token)) { + String email = jwtUtil.getEmail(token); + UserDetails userDetails = userDetailsService.loadUserByUsername(email); + Authentication authentication = + new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities() + ); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + filterChain.doFilter(request, response); + } + + private String getToken(HttpServletRequest request) { + String bearerToken = request.getHeader(AUTHORIZATION_HEADER_NAME); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) { + return bearerToken.substring(BEARER_PREFIX.length()); + } + return null; + } +} diff --git a/src/main/java/com/app/sellerretailreports/security/JwtUtil.java b/src/main/java/com/app/sellerretailreports/security/JwtUtil.java new file mode 100644 index 0000000..5bf533e --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/security/JwtUtil.java @@ -0,0 +1,59 @@ +package com.app.sellerretailreports.security; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Date; +import java.util.function.Function; + +@Component +public class JwtUtil { + private final Key secretKey; + @Value("${jwt.expiration}") + private long expiration; + + public JwtUtil(@Value("${jwt.secret}") String secretString) { + secretKey = Keys.hmacShaKeyFor(secretString.getBytes(StandardCharsets.UTF_8)); + } + + public String generateToken(String email) { + return Jwts.builder() + .setSubject(email) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + expiration)) + .signWith(secretKey) + .compact(); + } + + public boolean isTokenValid(String token) { + try { + Jws claimsJws = Jwts.parser() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(token); + return !claimsJws.getBody().getExpiration().before(new Date()); + } catch (JwtException | IllegalArgumentException e) { + throw new JwtException("Expired or invalid JWT token"); + } + } + + public String getEmail(String token) { + return getClaimFromToken(token, Claims::getSubject); + } + + private T getClaimFromToken(String token, Function claimsFunction) { + final Claims claims = Jwts.parser() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(token) + .getBody(); + return claimsFunction.apply(claims); + } +} diff --git a/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java b/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java new file mode 100644 index 0000000..56144f6 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java @@ -0,0 +1,63 @@ +package com.app.sellerretailreports.security; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@Configuration +@RequiredArgsConstructor +@EnableMethodSecurity +public class SecurityConfig { + private static final String[] AUTH_WHITELIST = { + "/auth/**", + "/error", + "/swagger-ui/**" + }; + + private final UserDetailsService userDetailsService; + private final JwtAuthenticationFilter jwtAuthenticationFilter; + + @Bean + public PasswordEncoder getPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + return http + .cors(AbstractHttpConfigurer::disable) + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests( + auth -> auth + .requestMatchers(AUTH_WHITELIST) + .permitAll() + .anyRequest() + .authenticated() + ) + .sessionManagement(session -> session + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .httpBasic(Customizer.withDefaults()) + .addFilterBefore(jwtAuthenticationFilter, + UsernamePasswordAuthenticationFilter.class) + .userDetailsService(userDetailsService) + .build(); + } + + @Bean + public AuthenticationManager authenticationManager( + AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } +} diff --git a/src/main/java/com/app/sellerretailreports/service/user/UserService.java b/src/main/java/com/app/sellerretailreports/service/user/UserService.java new file mode 100644 index 0000000..107b609 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/user/UserService.java @@ -0,0 +1,9 @@ +package com.app.sellerretailreports.service.user; + +import com.app.sellerretailreports.dto.user.UserRegisterRequestDto; +import com.app.sellerretailreports.dto.user.UserRegisterResponseDto; +import com.app.sellerretailreports.exception.RegistrationException; + +public interface UserService { + UserRegisterResponseDto register(UserRegisterRequestDto requestDto) throws RegistrationException; +} diff --git a/src/main/java/com/app/sellerretailreports/service/user/UserServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/user/UserServiceImpl.java new file mode 100644 index 0000000..b5b7eb1 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/user/UserServiceImpl.java @@ -0,0 +1,32 @@ +package com.app.sellerretailreports.service.user; + +import com.app.sellerretailreports.dto.user.UserRegisterRequestDto; +import com.app.sellerretailreports.dto.user.UserRegisterResponseDto; +import com.app.sellerretailreports.entity.User; +import com.app.sellerretailreports.exception.RegistrationException; +import com.app.sellerretailreports.mapper.UserMapper; +import com.app.sellerretailreports.repository.user.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + private final UserMapper userMapper; + private final PasswordEncoder passwordEncoder; + + @Override + public UserRegisterResponseDto register(UserRegisterRequestDto requestDto) + throws RegistrationException { + if (userRepository.findByEmail(requestDto.getEmail()).isPresent()) { + throw new RegistrationException(String.format( + "Can't register user with email %s", requestDto.getEmail()) + ); + } + User user = userMapper.toUser(requestDto); + user.setPassword(passwordEncoder.encode(requestDto.getPassword())); + return userMapper.toDto(userRepository.save(user)); + } +} diff --git a/src/main/java/com/app/sellerretailreports/validation/FieldMatch.java b/src/main/java/com/app/sellerretailreports/validation/FieldMatch.java new file mode 100644 index 0000000..400d4f2 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/validation/FieldMatch.java @@ -0,0 +1,17 @@ +package com.app.sellerretailreports.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Constraint(validatedBy = PasswordAndRepeatPasswordValidator.class) +@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface FieldMatch { + String message() default "Passwords don't match"; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/src/main/java/com/app/sellerretailreports/validation/PasswordAndRepeatPasswordValidator.java b/src/main/java/com/app/sellerretailreports/validation/PasswordAndRepeatPasswordValidator.java new file mode 100644 index 0000000..fe55bea --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/validation/PasswordAndRepeatPasswordValidator.java @@ -0,0 +1,15 @@ +package com.app.sellerretailreports.validation; + +import com.app.sellerretailreports.dto.user.UserRegisterRequestDto; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import java.util.Objects; + +public class PasswordAndRepeatPasswordValidator implements + ConstraintValidator { + @Override + public boolean isValid(UserRegisterRequestDto requestDto, + ConstraintValidatorContext constraintValidatorContext) { + return Objects.equals(requestDto.getPassword(), requestDto.getRepeatPassword()); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f49cae7..a65fb89 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,8 +1,6 @@ +server.port=8081 + spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 -#spring.data.mongodb.authentication-database=admin -#spring.data.mongodb.username=root spring.data.mongodb.password=password spring.data.mongodb.database=report_db - -server.port=8081 From c80c434695461c7266359053d813f917a52c6c40 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 19:29:57 +0200 Subject: [PATCH 08/23] stable version with authentication --- .../app/sellerretailreports/entity/User.java | 35 ++++++++++++++++++- .../mapper/UserMapper.java | 2 +- .../security/AuthenticationService.java | 4 ++- .../security/CustomUserDetailsService.java | 21 +++++++++++ .../sellerretailreports/security/JwtUtil.java | 5 ++- .../security/SecurityConfig.java | 1 + .../service/user/UserService.java | 3 +- src/main/resources/application.properties | 5 ++- .../SellerRetailReportsApplicationTests.java | 4 --- src/test/resources/application.properties | 4 +++ 10 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/security/CustomUserDetailsService.java create mode 100644 src/test/resources/application.properties diff --git a/src/main/java/com/app/sellerretailreports/entity/User.java b/src/main/java/com/app/sellerretailreports/entity/User.java index efd0f96..7279faa 100644 --- a/src/main/java/com/app/sellerretailreports/entity/User.java +++ b/src/main/java/com/app/sellerretailreports/entity/User.java @@ -1,14 +1,17 @@ package com.app.sellerretailreports.entity; +import java.util.Collection; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; @Data @Document(collection = "users") -public class User { +public class User implements UserDetails { @Id private String id; private String email; @@ -17,4 +20,34 @@ public class User { private String password; private String firstName; private String lastName; + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getUsername() { + return email; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } } diff --git a/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java b/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java index 540854d..d4a2edb 100644 --- a/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java +++ b/src/main/java/com/app/sellerretailreports/mapper/UserMapper.java @@ -1,10 +1,10 @@ package com.app.sellerretailreports.mapper; +import com.app.sellerretailreports.config.MapperConfig; import com.app.sellerretailreports.dto.user.UserRegisterRequestDto; import com.app.sellerretailreports.dto.user.UserRegisterResponseDto; import com.app.sellerretailreports.entity.User; import org.mapstruct.Mapper; -import org.mapstruct.MapperConfig; @Mapper(config = MapperConfig.class) public interface UserMapper { diff --git a/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java b/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java index 0832d74..a7ab930 100644 --- a/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java +++ b/src/main/java/com/app/sellerretailreports/security/AuthenticationService.java @@ -16,7 +16,9 @@ public class AuthenticationService { public UserLoginResponseDto authenticate(UserLoginRequestDto requestDto) { final Authentication authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(requestDto.getEmail(), requestDto.getPassword()) + new UsernamePasswordAuthenticationToken( + requestDto.getEmail(), requestDto.getPassword() + ) ); String generatedToken = jwtUtil.generateToken(authentication.getName()); diff --git a/src/main/java/com/app/sellerretailreports/security/CustomUserDetailsService.java b/src/main/java/com/app/sellerretailreports/security/CustomUserDetailsService.java new file mode 100644 index 0000000..a37e649 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/security/CustomUserDetailsService.java @@ -0,0 +1,21 @@ +package com.app.sellerretailreports.security; + +import com.app.sellerretailreports.repository.user.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + private static final String CANNOT_FIND_USER_BY_EMAIL = "Can't find user by email: "; + private final UserRepository userRepository; + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + return userRepository.findByEmail(email).orElseThrow(() + -> new UsernameNotFoundException(CANNOT_FIND_USER_BY_EMAIL + email)); + } +} diff --git a/src/main/java/com/app/sellerretailreports/security/JwtUtil.java b/src/main/java/com/app/sellerretailreports/security/JwtUtil.java index 5bf533e..affa222 100644 --- a/src/main/java/com/app/sellerretailreports/security/JwtUtil.java +++ b/src/main/java/com/app/sellerretailreports/security/JwtUtil.java @@ -5,13 +5,12 @@ import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - import java.nio.charset.StandardCharsets; import java.security.Key; import java.util.Date; import java.util.function.Function; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; @Component public class JwtUtil { diff --git a/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java b/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java index 56144f6..3ac1c99 100644 --- a/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java +++ b/src/main/java/com/app/sellerretailreports/security/SecurityConfig.java @@ -21,6 +21,7 @@ @EnableMethodSecurity public class SecurityConfig { private static final String[] AUTH_WHITELIST = { + "/health", "/auth/**", "/error", "/swagger-ui/**" diff --git a/src/main/java/com/app/sellerretailreports/service/user/UserService.java b/src/main/java/com/app/sellerretailreports/service/user/UserService.java index 107b609..edcfc03 100644 --- a/src/main/java/com/app/sellerretailreports/service/user/UserService.java +++ b/src/main/java/com/app/sellerretailreports/service/user/UserService.java @@ -5,5 +5,6 @@ import com.app.sellerretailreports.exception.RegistrationException; public interface UserService { - UserRegisterResponseDto register(UserRegisterRequestDto requestDto) throws RegistrationException; + UserRegisterResponseDto register(UserRegisterRequestDto requestDto) + throws RegistrationException; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a65fb89..fc58ea5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,5 +2,8 @@ server.port=8081 spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 -spring.data.mongodb.password=password +spring.data.mongodb.password=${MANGODB_PASSWORD} spring.data.mongodb.database=report_db + +jwt.expiration=${JWT_EXPIRATION} +jwt.secret=${JWT_SECRET} diff --git a/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java b/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java index 6290415..80e591d 100644 --- a/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java +++ b/src/test/java/com/app/sellerretailreports/SellerRetailReportsApplicationTests.java @@ -1,11 +1,7 @@ package com.app.sellerretailreports; -import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class SellerRetailReportsApplicationTests { - @Test - void contextLoads() { - } } diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..13bde9d --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,4 @@ +server.port=8081 + +jwt.expiration=${JWT_EXPIRATION} +jwt.secret=${JWT_SECRET} From 2d9e5b02129aa754b34a74653ce3e9815f936919 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 19:38:32 +0200 Subject: [PATCH 09/23] added Swagger tags --- .../controller/AuthenticationController.java | 6 ++++++ .../sellerretailreports/controller/HealthController.java | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java b/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java index e5742a8..7391a25 100644 --- a/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java +++ b/src/main/java/com/app/sellerretailreports/controller/AuthenticationController.java @@ -7,6 +7,8 @@ import com.app.sellerretailreports.exception.RegistrationException; import com.app.sellerretailreports.security.AuthenticationService; import com.app.sellerretailreports.service.user.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; @@ -17,16 +19,20 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/auth") +@Tag(name = "Authentication management", + description = "Endpoints for managing authentication.") public class AuthenticationController { private final UserService userService; private final AuthenticationService authenticationService; @PostMapping(value = "/login") + @Operation(summary = "Login") public UserLoginResponseDto login(@RequestBody @Valid UserLoginRequestDto requestDto) { return authenticationService.authenticate(requestDto); } @PostMapping(value = "/register") + @Operation(summary = "Register") public UserRegisterResponseDto register(@RequestBody @Valid UserRegisterRequestDto requestDto) throws RegistrationException { return userService.register(requestDto); diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java index 6991279..3526c3c 100644 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -1,14 +1,18 @@ package com.app.sellerretailreports.controller; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor +@Tag(name = "Health Check", description = "Endpoint to check API") public class HealthController { @GetMapping("/health") + @Operation(summary = "Check Health") public String getHealth() { - return "API working..."; + return "API is running..."; } } From b8259e440515a05b360256025b8b8c874cce4a46 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 21:25:11 +0200 Subject: [PATCH 10/23] mapper fixed --- pom.xml | 2 -- .../controller/ReportController.java | 26 +++++++++++++++++++ .../dto/report/ReportRequestDto.java | 4 +++ .../dto/report/ReportResponseDto.java | 12 +++++++++ .../dto/report/ReportSpecificationDto.java | 19 ++++++++++++++ .../dto/report/SalesAndTrafficByAsinDto.java | 12 +++++++++ .../dto/report/SalesAndTrafficByDateDto.java | 13 ++++++++++ .../mapper/ReportMapper.java | 21 +++++++++++++++ .../mapper/ReportSpecificationMapper.java | 13 ++++++++++ .../mapper/SalesAndTrafficByAsinMapper.java | 13 ++++++++++ .../mapper/SalesAndTrafficByDateMapper.java | 13 ++++++++++ .../{ => report}/ReportRepository.java | 2 +- .../service/ReportService.java | 4 --- .../service/ReportServiceImpl.java | 9 ------- .../service/report/ReportService.java | 8 ++++++ .../service/report/ReportServiceImpl.java | 22 ++++++++++++++++ 16 files changed, 177 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/controller/ReportController.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/report/ReportResponseDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/report/ReportSpecificationDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByAsinDto.java create mode 100644 src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByDateDto.java create mode 100644 src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java create mode 100644 src/main/java/com/app/sellerretailreports/mapper/ReportSpecificationMapper.java create mode 100644 src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByAsinMapper.java create mode 100644 src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByDateMapper.java rename src/main/java/com/app/sellerretailreports/repository/{ => report}/ReportRepository.java (82%) delete mode 100644 src/main/java/com/app/sellerretailreports/service/ReportService.java delete mode 100644 src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java create mode 100644 src/main/java/com/app/sellerretailreports/service/report/ReportService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/report/ReportServiceImpl.java diff --git a/pom.xml b/pom.xml index ff806ce..d340c63 100644 --- a/pom.xml +++ b/pom.xml @@ -60,13 +60,11 @@ io.jsonwebtoken jjwt-impl - runtime ${jjwt.version} io.jsonwebtoken jjwt-jackson - runtime ${jjwt.version} diff --git a/src/main/java/com/app/sellerretailreports/controller/ReportController.java b/src/main/java/com/app/sellerretailreports/controller/ReportController.java new file mode 100644 index 0000000..302b9cc --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/controller/ReportController.java @@ -0,0 +1,26 @@ +package com.app.sellerretailreports.controller; + +import com.app.sellerretailreports.dto.report.ReportResponseDto; +import com.app.sellerretailreports.service.report.ReportService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/report") +@Tag(name = "Report management", + description = "Endpoints for managing reports.") +public class ReportController { + private final ReportService reportService; + + @GetMapping(value = "/all") + @Operation(summary = "Get reports by all dates") + public List getAllReports() { + return reportService.findAll(); + } +} diff --git a/src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java b/src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java new file mode 100644 index 0000000..f17f43e --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java @@ -0,0 +1,4 @@ +package com.app.sellerretailreports.dto.report; + +public class ReportRequestDto { +} diff --git a/src/main/java/com/app/sellerretailreports/dto/report/ReportResponseDto.java b/src/main/java/com/app/sellerretailreports/dto/report/ReportResponseDto.java new file mode 100644 index 0000000..491bb34 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/report/ReportResponseDto.java @@ -0,0 +1,12 @@ +package com.app.sellerretailreports.dto.report; + +import java.util.List; +import lombok.Data; + +@Data +public class ReportResponseDto { + private String id; + private ReportSpecificationDto reportSpecification; + private List salesAndTrafficByDate; + private List salesAndTrafficByAsin; +} diff --git a/src/main/java/com/app/sellerretailreports/dto/report/ReportSpecificationDto.java b/src/main/java/com/app/sellerretailreports/dto/report/ReportSpecificationDto.java new file mode 100644 index 0000000..a9027ec --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/report/ReportSpecificationDto.java @@ -0,0 +1,19 @@ +package com.app.sellerretailreports.dto.report; + +import com.app.sellerretailreports.entity.report.ReportOption; +import com.app.sellerretailreports.entity.report.ReportSpecification.ReportType; +import java.time.LocalDate; +import java.util.List; +import lombok.Data; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.FieldType; + +@Data +public class ReportSpecificationDto { + @Field(targetType = FieldType.STRING) + private ReportType reportType; + private ReportOption reportOptions; + private LocalDate dataStartTime; + private LocalDate dataEndTime; + private List marketplaceIds; +} diff --git a/src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByAsinDto.java b/src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByAsinDto.java new file mode 100644 index 0000000..2690691 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByAsinDto.java @@ -0,0 +1,12 @@ +package com.app.sellerretailreports.dto.report; + +import com.app.sellerretailreports.entity.report.SalesByAsin; +import com.app.sellerretailreports.entity.report.TrafficByAsin; +import lombok.Data; + +@Data +public class SalesAndTrafficByAsinDto { + private String parentAsin; + private SalesByAsin salesByAsin; + private TrafficByAsin trafficByAsin; +} diff --git a/src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByDateDto.java b/src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByDateDto.java new file mode 100644 index 0000000..4114b27 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/dto/report/SalesAndTrafficByDateDto.java @@ -0,0 +1,13 @@ +package com.app.sellerretailreports.dto.report; + +import com.app.sellerretailreports.entity.report.SalesByDate; +import com.app.sellerretailreports.entity.report.TrafficByDate; +import java.time.LocalDate; +import lombok.Data; + +@Data +public class SalesAndTrafficByDateDto { + private LocalDate date; + private SalesByDate salesByDate; + private TrafficByDate trafficByDate; +} diff --git a/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java b/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java new file mode 100644 index 0000000..d1a08ca --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java @@ -0,0 +1,21 @@ +package com.app.sellerretailreports.mapper; + +import com.app.sellerretailreports.config.MapperConfig; +import com.app.sellerretailreports.dto.report.ReportRequestDto; +import com.app.sellerretailreports.dto.report.ReportResponseDto; +import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; +import org.mapstruct.Mapper; + +@Mapper( + config = MapperConfig.class, + uses = { + ReportSpecificationMapper.class, + SalesAndTrafficByDateMapper.class, + SalesAndTrafficByAsinMapper.class + } +) +public interface ReportMapper { + ReportResponseDto toDto(SalesAndTrafficReport salesAndTrafficReport); + + SalesAndTrafficReport toEntity(ReportRequestDto requestDto); +} diff --git a/src/main/java/com/app/sellerretailreports/mapper/ReportSpecificationMapper.java b/src/main/java/com/app/sellerretailreports/mapper/ReportSpecificationMapper.java new file mode 100644 index 0000000..d48cb54 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/mapper/ReportSpecificationMapper.java @@ -0,0 +1,13 @@ +package com.app.sellerretailreports.mapper; + +import com.app.sellerretailreports.config.MapperConfig; +import com.app.sellerretailreports.dto.report.ReportSpecificationDto; +import com.app.sellerretailreports.entity.report.ReportSpecification; +import org.mapstruct.Mapper; + +@Mapper(config = MapperConfig.class) +public interface ReportSpecificationMapper { + ReportSpecification toEntity(ReportSpecificationDto reportSpecificationDto); + + ReportSpecificationDto toDto(ReportSpecification reportSpecification); +} diff --git a/src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByAsinMapper.java b/src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByAsinMapper.java new file mode 100644 index 0000000..f4b5800 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByAsinMapper.java @@ -0,0 +1,13 @@ +package com.app.sellerretailreports.mapper; + +import com.app.sellerretailreports.config.MapperConfig; +import com.app.sellerretailreports.dto.report.SalesAndTrafficByAsinDto; +import com.app.sellerretailreports.entity.report.SalesAndTrafficByAsin; +import org.mapstruct.Mapper; + +@Mapper(config = MapperConfig.class) +public interface SalesAndTrafficByAsinMapper { + SalesAndTrafficByAsin toEntity(SalesAndTrafficByAsinDto salesAndTrafficByAsinDto); + + SalesAndTrafficByAsinDto toDto(SalesAndTrafficByAsin salesAndTrafficByAsin); +} diff --git a/src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByDateMapper.java b/src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByDateMapper.java new file mode 100644 index 0000000..953c2d2 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/mapper/SalesAndTrafficByDateMapper.java @@ -0,0 +1,13 @@ +package com.app.sellerretailreports.mapper; + +import com.app.sellerretailreports.config.MapperConfig; +import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import com.app.sellerretailreports.entity.report.SalesAndTrafficByDate; +import org.mapstruct.Mapper; + +@Mapper(config = MapperConfig.class) +public interface SalesAndTrafficByDateMapper { + SalesAndTrafficByDate toEntity(SalesAndTrafficByDateDto salesAndTrafficByDateDto); + + SalesAndTrafficByDateDto toDto(SalesAndTrafficByDate salesAndTrafficByDate); +} diff --git a/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java similarity index 82% rename from src/main/java/com/app/sellerretailreports/repository/ReportRepository.java rename to src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java index 83d630d..b0b5dec 100644 --- a/src/main/java/com/app/sellerretailreports/repository/ReportRepository.java +++ b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.repository; +package com.app.sellerretailreports.repository.report; import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; import org.springframework.data.mongodb.repository.MongoRepository; diff --git a/src/main/java/com/app/sellerretailreports/service/ReportService.java b/src/main/java/com/app/sellerretailreports/service/ReportService.java deleted file mode 100644 index cf0aa08..0000000 --- a/src/main/java/com/app/sellerretailreports/service/ReportService.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.app.sellerretailreports.service; - -public interface ReportService { -} diff --git a/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java deleted file mode 100644 index c88addb..0000000 --- a/src/main/java/com/app/sellerretailreports/service/ReportServiceImpl.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.app.sellerretailreports.service; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class ReportServiceImpl implements ReportService { -} diff --git a/src/main/java/com/app/sellerretailreports/service/report/ReportService.java b/src/main/java/com/app/sellerretailreports/service/report/ReportService.java new file mode 100644 index 0000000..72af1bd --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/report/ReportService.java @@ -0,0 +1,8 @@ +package com.app.sellerretailreports.service.report; + +import com.app.sellerretailreports.dto.report.ReportResponseDto; +import java.util.List; + +public interface ReportService { + List findAll(); +} diff --git a/src/main/java/com/app/sellerretailreports/service/report/ReportServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/report/ReportServiceImpl.java new file mode 100644 index 0000000..03b2a81 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/report/ReportServiceImpl.java @@ -0,0 +1,22 @@ +package com.app.sellerretailreports.service.report; + +import com.app.sellerretailreports.dto.report.ReportResponseDto; +import com.app.sellerretailreports.mapper.ReportMapper; +import com.app.sellerretailreports.repository.report.ReportRepository; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReportServiceImpl implements ReportService { + private final ReportRepository repository; + private final ReportMapper reportMapper; + + @Override + public List findAll() { + return repository.findAll().stream() + .map(reportMapper::toDto) + .toList(); + } +} From 528a385def971509e26c0867890f1f5b0eb90e2b Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Wed, 28 Feb 2024 21:58:01 +0200 Subject: [PATCH 11/23] in process adding saled layer --- .../controller/ReportController.java | 2 +- .../SalesAndTrafficByDateController.java | 25 +++++++++++++++++++ .../repository/report/ReportRepository.java | 2 ++ .../sales/SalesAndTrafficByDateService.java | 7 ++++++ .../SalesAndTrafficByDateServiceImpl.java | 12 +++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java create mode 100644 src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java diff --git a/src/main/java/com/app/sellerretailreports/controller/ReportController.java b/src/main/java/com/app/sellerretailreports/controller/ReportController.java index 302b9cc..deaabf6 100644 --- a/src/main/java/com/app/sellerretailreports/controller/ReportController.java +++ b/src/main/java/com/app/sellerretailreports/controller/ReportController.java @@ -20,7 +20,7 @@ public class ReportController { @GetMapping(value = "/all") @Operation(summary = "Get reports by all dates") - public List getAllReports() { + public List getAll() { return reportService.findAll(); } } diff --git a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java new file mode 100644 index 0000000..01774ae --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java @@ -0,0 +1,25 @@ +package com.app.sellerretailreports.controller; + +import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import com.app.sellerretailreports.service.sales.SalesAndTrafficByDateService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/sales") +@Tag(name = "Sales management", + description = "Endpoints for managing sales.") +public class SalesAndTrafficByDateController { + private final SalesAndTrafficByDateService salesAndTrafficByDateService; + + @GetMapping(value = "/all-by-date") + @Operation(summary = "Get statistics for all dates") + public SalesAndTrafficByDateDto getAll() { + return salesAndTrafficByDateService.findAll(); + } +} diff --git a/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java index b0b5dec..edc3f8a 100644 --- a/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java +++ b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java @@ -4,6 +4,8 @@ import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface ReportRepository extends MongoRepository { } diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java new file mode 100644 index 0000000..243f878 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java @@ -0,0 +1,7 @@ +package com.app.sellerretailreports.service.sales; + +import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; + +public interface SalesAndTrafficByDateService { + SalesAndTrafficByDateDto findAll(); +} diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java new file mode 100644 index 0000000..c5894f3 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java @@ -0,0 +1,12 @@ +package com.app.sellerretailreports.service.sales; + +import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import org.springframework.stereotype.Service; + +@Service +public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateService { + @Override + public SalesAndTrafficByDateDto findAll() { + return null; + } +} From e98e19a78d5e592fb27dec897e353dde099f38d1 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 09:30:52 +0200 Subject: [PATCH 12/23] added main endpoints --- .../SalesAndTrafficByDateController.java | 25 --------- .../controller/SalesAndTrafficController.java | 52 +++++++++++++++++++ .../repository/report/ReportRepository.java | 2 + .../sales/SalesAndTrafficByDateService.java | 11 +++- .../SalesAndTrafficByDateServiceImpl.java | 47 ++++++++++++++++- 5 files changed, 109 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java create mode 100644 src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java diff --git a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java deleted file mode 100644 index 01774ae..0000000 --- a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficByDateController.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.app.sellerretailreports.controller; - -import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; -import com.app.sellerretailreports.service.sales.SalesAndTrafficByDateService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping(value = "/sales") -@Tag(name = "Sales management", - description = "Endpoints for managing sales.") -public class SalesAndTrafficByDateController { - private final SalesAndTrafficByDateService salesAndTrafficByDateService; - - @GetMapping(value = "/all-by-date") - @Operation(summary = "Get statistics for all dates") - public SalesAndTrafficByDateDto getAll() { - return salesAndTrafficByDateService.findAll(); - } -} diff --git a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java new file mode 100644 index 0000000..bc48bd3 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java @@ -0,0 +1,52 @@ +package com.app.sellerretailreports.controller; + +import com.app.sellerretailreports.dto.report.SalesAndTrafficByAsinDto; +import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import com.app.sellerretailreports.entity.report.SalesAndTrafficByAsin; +import com.app.sellerretailreports.service.sales.SalesAndTrafficByDateService; +import java.time.LocalDate; +import java.util.List; +import lombok.RequiredArgsConstructor; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/sales") +@Tag(name = "Sales management", + description = "Endpoints for managing sales.") +public class SalesAndTrafficController { + private final SalesAndTrafficByDateService salesAndTrafficByDateService; + + @GetMapping(value = "/all-between-dates") + @Operation(summary = "Get statistics between specified dates.") + public List getAllBetweenDates( + @RequestParam("start") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, + @RequestParam("end") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end + ) { + return salesAndTrafficByDateService.findAllBetweenDates(start, end); + } + + @GetMapping(value = "/all-by-specified-asins") + @Operation(summary = "Get statistics by all specified asins.") + public List getAllByAsins(@RequestParam("asins") List asins) { + return salesAndTrafficByDateService.findAllBySpecifiedAsins(asins); + } + + @GetMapping(value = "/all-by-dates") + @Operation(summary = "Get statistics by all dates.") + public List getAllByDates() { + return salesAndTrafficByDateService.findAllByDates(); + } + + @GetMapping(value = "/all-by-asins") + @Operation(summary = "Get statistics by all asins.") + public List getAllByAsins() { + return salesAndTrafficByDateService.findAllByAsins(); + } +} diff --git a/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java index edc3f8a..c5db10e 100644 --- a/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java +++ b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java @@ -1,9 +1,11 @@ package com.app.sellerretailreports.repository.report; +import com.app.sellerretailreports.entity.report.SalesAndTrafficByDate; import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; +import java.time.LocalDate; import java.util.List; @Repository diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java index 243f878..b271171 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java @@ -1,7 +1,16 @@ package com.app.sellerretailreports.service.sales; +import com.app.sellerretailreports.dto.report.SalesAndTrafficByAsinDto; import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import java.time.LocalDate; +import java.util.List; public interface SalesAndTrafficByDateService { - SalesAndTrafficByDateDto findAll(); + List findAllBetweenDates(LocalDate start, LocalDate end); + + List findAllByAsins(); + + List findAllByDates(); + + List findAllBySpecifiedAsins(List asins); } diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java index c5894f3..1810d0b 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java @@ -1,12 +1,55 @@ package com.app.sellerretailreports.service.sales; +import com.app.sellerretailreports.dto.report.SalesAndTrafficByAsinDto; import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; +import com.app.sellerretailreports.mapper.SalesAndTrafficByAsinMapper; +import com.app.sellerretailreports.mapper.SalesAndTrafficByDateMapper; +import com.app.sellerretailreports.repository.report.ReportRepository; +import java.time.LocalDate; +import java.util.List; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service +@RequiredArgsConstructor public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateService { + private final ReportRepository repository; + private final SalesAndTrafficByDateMapper salesAndTrafficByDateMapper; + private final SalesAndTrafficByAsinMapper salesAndTrafficByAsinMapper; + + @Override + public List findAllBetweenDates(LocalDate start, LocalDate end) { + SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + return salesAndTrafficReport.getSalesAndTrafficByDate().stream() + .filter(s -> (s.getDate().isAfter(start) && s.getDate().isBefore(end)) + || (s.getDate().equals(start) || s.getDate().equals(end))) + .map(salesAndTrafficByDateMapper::toDto) + .toList(); + } + + @Override + public List findAllBySpecifiedAsins(List asins) { + SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() + .filter(s -> asins.contains(s.getParentAsin())) + .map(salesAndTrafficByAsinMapper::toDto) + .toList(); + } + + @Override + public List findAllByAsins() { + SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() + .map(salesAndTrafficByAsinMapper::toDto) + .toList(); + } + @Override - public SalesAndTrafficByDateDto findAll() { - return null; + public List findAllByDates() { + SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + return salesAndTrafficReport.getSalesAndTrafficByDate().stream() + .map(salesAndTrafficByDateMapper::toDto) + .toList(); } } From 47e4861332a84da51fef7805e4e85b2fd161cb1c Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 09:37:09 +0200 Subject: [PATCH 13/23] refactored according to checkstyle req --- .../controller/SalesAndTrafficController.java | 11 ++++++----- .../repository/report/ReportRepository.java | 4 ---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java index bc48bd3..5965ba3 100644 --- a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java +++ b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java @@ -2,13 +2,12 @@ import com.app.sellerretailreports.dto.report.SalesAndTrafficByAsinDto; import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; -import com.app.sellerretailreports.entity.report.SalesAndTrafficByAsin; import com.app.sellerretailreports.service.sales.SalesAndTrafficByDateService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -17,7 +16,7 @@ @RestController @RequiredArgsConstructor -@RequestMapping(value = "/sales") +@RequestMapping(value = "/sales-and-traffic") @Tag(name = "Sales management", description = "Endpoints for managing sales.") public class SalesAndTrafficController { @@ -34,7 +33,9 @@ public List getAllBetweenDates( @GetMapping(value = "/all-by-specified-asins") @Operation(summary = "Get statistics by all specified asins.") - public List getAllByAsins(@RequestParam("asins") List asins) { + public List getAllBySpecifiedAsins( + @RequestParam("asins") List asins + ) { return salesAndTrafficByDateService.findAllBySpecifiedAsins(asins); } diff --git a/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java index c5db10e..b0b5dec 100644 --- a/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java +++ b/src/main/java/com/app/sellerretailreports/repository/report/ReportRepository.java @@ -1,13 +1,9 @@ package com.app.sellerretailreports.repository.report; -import com.app.sellerretailreports.entity.report.SalesAndTrafficByDate; import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; -import java.time.LocalDate; -import java.util.List; - @Repository public interface ReportRepository extends MongoRepository { } From 287c7dfd8ef4004cb07a8113e4013049fc91d3e0 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 10:32:39 +0200 Subject: [PATCH 14/23] test updater added --- pom.xml | 4 + .../SellerRetailReportsApplication.java | 4 + .../controller/HealthController.java | 8 + .../entity/report/SalesByDate.java | 3 +- .../service/updater/FileReaderService.java | 32 + .../service/updater/ReportUpdaterService.java | 5 + .../updater/ReportUpdaterServiceImpl.java | 32 + test_report.json | 7380 +++++++++++++++++ 8 files changed, 7467 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java create mode 100644 test_report.json diff --git a/pom.xml b/pom.xml index d340c63..68ae845 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,10 @@ lombok-mapstruct-binding ${lombok.mapstruct.binding.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + diff --git a/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java b/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java index b930c73..1bf186a 100644 --- a/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java +++ b/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java @@ -2,8 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling +@EnableCaching public class SellerRetailReportsApplication { public static void main(String[] args) { SpringApplication.run(SellerRetailReportsApplication.class, args); diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java index 3526c3c..e97ca7d 100644 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -1,5 +1,6 @@ package com.app.sellerretailreports.controller; +import com.app.sellerretailreports.service.updater.ReportUpdaterService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -10,9 +11,16 @@ @RequiredArgsConstructor @Tag(name = "Health Check", description = "Endpoint to check API") public class HealthController { + private final ReportUpdaterService reportUpdaterService; + @GetMapping("/health") @Operation(summary = "Check Health") public String getHealth() { return "API is running..."; } + + @GetMapping("/update") + public void updateDb() { + reportUpdaterService.updateDb(); + } } diff --git a/src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java index 67ca907..9c855ce 100644 --- a/src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesByDate.java @@ -8,7 +8,7 @@ public class SalesByDate { private OrderedProductSales orderedProductSales; private OrderedProductSalesB2B orderedProductSalesB2B; private int unitsOrdered; - private int getUnitsOrderedB2B; + private int unitsOrderedB2B; private int totalOrderItems; private int totalOrderItemsB2B; private AverageSalesPerOrderItem averageSalesPerOrderItem; @@ -20,6 +20,7 @@ public class SalesByDate { private int unitsRefunded; private BigDecimal refundRate; private int claimsGranted; + private ClaimsAmount claimsAmount; private ShippedProductSales shippedProductSales; private int unitsShipped; private int ordersShipped; diff --git a/src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java b/src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java new file mode 100644 index 0000000..13ee979 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java @@ -0,0 +1,32 @@ +package com.app.sellerretailreports.service.updater; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.stream.Collectors; + +public class FileReaderService { + public static String readFile(String fileName) { + + try { + BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(fileName)); + + try { + String str = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator())); + bufferedReader.close(); + return str; + } catch (Throwable throwable) { + try { + bufferedReader.close(); + } catch (Throwable throwable1) { + throwable.addSuppressed(throwable1); + } + throw throwable; + } + } catch (IOException e) { + throw new RuntimeException("Cannot read data from the file " + fileName, e); + } + + } +} diff --git a/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java b/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java new file mode 100644 index 0000000..a9a31cc --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java @@ -0,0 +1,5 @@ +package com.app.sellerretailreports.service.updater; + +public interface ReportUpdaterService { + void updateDb(); +} diff --git a/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java new file mode 100644 index 0000000..7a0013d --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java @@ -0,0 +1,32 @@ +package com.app.sellerretailreports.service.updater; + +import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; +import com.app.sellerretailreports.repository.report.ReportRepository; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReportUpdaterServiceImpl implements ReportUpdaterService { + private final ReportRepository repository; + + @Override + public void updateDb() { + SalesAndTrafficReport report = getReport(); + repository.save(report); + } + + private SalesAndTrafficReport getReport() { + String jsonString = FileReaderService.readFile("test_report.json"); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + try { + return objectMapper.readValue(jsonString, SalesAndTrafficReport.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/test_report.json b/test_report.json new file mode 100644 index 0000000..cf635fb --- /dev/null +++ b/test_report.json @@ -0,0 +1,7380 @@ +{ + "reportSpecification": { + "reportType": "GET_SALES_AND_TRAFFIC_REPORT", + "reportOptions": { + "dateGranularity": "DAY", + "asinGranularity": "PARENT" + }, + "dataStartTime": "2024-02-14", + "dataEndTime": "2024-02-26", + "marketplaceIds": [ + "ATVPDKIKX0DER" + ] + }, + "salesAndTrafficByDate": [ + { + "date": "2024-02-14", + "salesByDate": { + "orderedProductSales": { + "amount": 10614.69, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 204.48, + "currencyCode": "USD" + }, + "unitsOrdered": 526, + "unitsOrderedB2B": 9, + "totalOrderItems": 496, + "totalOrderItemsB2B": 8, + "averageSalesPerOrderItem": { + "amount": 21.4, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 25.56, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.06, + "averageUnitsPerOrderItemB2B": 1.12, + "averageSellingPrice": { + "amount": 20.18, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 22.72, + "currencyCode": "USD" + }, + "unitsRefunded": 14, + "refundRate": 2.66, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 11093.69, + "currencyCode": "USD" + }, + "unitsShipped": 538, + "ordersShipped": 537 + }, + "trafficByDate": { + "browserPageViews": 1721, + "browserPageViewsB2B": 60, + "mobileAppPageViews": 3889, + "mobileAppPageViewsB2B": 79, + "pageViews": 5610, + "pageViewsB2B": 139, + "browserSessions": 1178, + "browserSessionsB2B": 44, + "mobileAppSessions": 1664, + "mobileAppSessionsB2B": 31, + "sessions": 2842, + "sessionsB2B": 75, + "buyBoxPercentage": 98.12, + "buyBoxPercentageB2B": 93.33, + "orderItemSessionPercentage": 17.45, + "orderItemSessionPercentageB2B": 10.67, + "unitSessionPercentage": 18.51, + "unitSessionPercentageB2B": 12, + "averageOfferCount": 232, + "averageParentItems": 128, + "feedbackReceived": 1, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-15", + "salesByDate": { + "orderedProductSales": { + "amount": 11519.48, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 166.2, + "currencyCode": "USD" + }, + "unitsOrdered": 544, + "unitsOrderedB2B": 8, + "totalOrderItems": 516, + "totalOrderItemsB2B": 8, + "averageSalesPerOrderItem": { + "amount": 22.32, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 20.78, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.05, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 21.18, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 20.78, + "currencyCode": "USD" + }, + "unitsRefunded": 13, + "refundRate": 2.39, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 11892.89, + "currencyCode": "USD" + }, + "unitsShipped": 576, + "ordersShipped": 574 + }, + "trafficByDate": { + "browserPageViews": 1825, + "browserPageViewsB2B": 61, + "mobileAppPageViews": 4558, + "mobileAppPageViewsB2B": 32, + "pageViews": 6383, + "pageViewsB2B": 93, + "browserSessions": 1226, + "browserSessionsB2B": 38, + "mobileAppSessions": 1858, + "mobileAppSessionsB2B": 18, + "sessions": 3084, + "sessionsB2B": 56, + "buyBoxPercentage": 98.97, + "buyBoxPercentageB2B": 96.49, + "orderItemSessionPercentage": 16.73, + "orderItemSessionPercentageB2B": 14.29, + "unitSessionPercentage": 17.64, + "unitSessionPercentageB2B": 14.29, + "averageOfferCount": 232, + "averageParentItems": 128, + "feedbackReceived": 3, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-16", + "salesByDate": { + "orderedProductSales": { + "amount": 11028.57, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 218.7, + "currencyCode": "USD" + }, + "unitsOrdered": 517, + "unitsOrderedB2B": 11, + "totalOrderItems": 489, + "totalOrderItemsB2B": 9, + "averageSalesPerOrderItem": { + "amount": 22.55, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 24.3, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.06, + "averageUnitsPerOrderItemB2B": 1.22, + "averageSellingPrice": { + "amount": 21.33, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 19.88, + "currencyCode": "USD" + }, + "unitsRefunded": 13, + "refundRate": 2.51, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 9798.11, + "currencyCode": "USD" + }, + "unitsShipped": 465, + "ordersShipped": 464 + }, + "trafficByDate": { + "browserPageViews": 1723, + "browserPageViewsB2B": 54, + "mobileAppPageViews": 4575, + "mobileAppPageViewsB2B": 56, + "pageViews": 6298, + "pageViewsB2B": 110, + "browserSessions": 1050, + "browserSessionsB2B": 28, + "mobileAppSessions": 1854, + "mobileAppSessionsB2B": 20, + "sessions": 2904, + "sessionsB2B": 48, + "buyBoxPercentage": 99.19, + "buyBoxPercentageB2B": 100, + "orderItemSessionPercentage": 16.84, + "orderItemSessionPercentageB2B": 18.75, + "unitSessionPercentage": 17.8, + "unitSessionPercentageB2B": 22.92, + "averageOfferCount": 230, + "averageParentItems": 128, + "feedbackReceived": 1, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-17", + "salesByDate": { + "orderedProductSales": { + "amount": 11910.43, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 240.77, + "currencyCode": "USD" + }, + "unitsOrdered": 557, + "unitsOrderedB2B": 10, + "totalOrderItems": 543, + "totalOrderItemsB2B": 10, + "averageSalesPerOrderItem": { + "amount": 21.93, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 24.08, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.03, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 21.38, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 24.08, + "currencyCode": "USD" + }, + "unitsRefunded": 16, + "refundRate": 2.87, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 9631.77, + "currencyCode": "USD" + }, + "unitsShipped": 450, + "ordersShipped": 448 + }, + "trafficByDate": { + "browserPageViews": 2707, + "browserPageViewsB2B": 45, + "mobileAppPageViews": 7031, + "mobileAppPageViewsB2B": 398, + "pageViews": 9738, + "pageViewsB2B": 443, + "browserSessions": 1237, + "browserSessionsB2B": 34, + "mobileAppSessions": 2336, + "mobileAppSessionsB2B": 37, + "sessions": 3573, + "sessionsB2B": 71, + "buyBoxPercentage": 99.39, + "buyBoxPercentageB2B": 100, + "orderItemSessionPercentage": 15.2, + "orderItemSessionPercentageB2B": 14.08, + "unitSessionPercentage": 15.59, + "unitSessionPercentageB2B": 14.08, + "averageOfferCount": 229, + "averageParentItems": 127, + "feedbackReceived": 1, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-18", + "salesByDate": { + "orderedProductSales": { + "amount": 14427.6, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 110.15, + "currencyCode": "USD" + }, + "unitsOrdered": 688, + "unitsOrderedB2B": 5, + "totalOrderItems": 644, + "totalOrderItemsB2B": 5, + "averageSalesPerOrderItem": { + "amount": 22.4, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 22.03, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.07, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 20.97, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 22.03, + "currencyCode": "USD" + }, + "unitsRefunded": 6, + "refundRate": 0.87, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 11177.79, + "currencyCode": "USD" + }, + "unitsShipped": 527, + "ordersShipped": 526 + }, + "trafficByDate": { + "browserPageViews": 2259, + "browserPageViewsB2B": 64, + "mobileAppPageViews": 6225, + "mobileAppPageViewsB2B": 59, + "pageViews": 8484, + "pageViewsB2B": 123, + "browserSessions": 1497, + "browserSessionsB2B": 36, + "mobileAppSessions": 2625, + "mobileAppSessionsB2B": 31, + "sessions": 4122, + "sessionsB2B": 67, + "buyBoxPercentage": 99.27, + "buyBoxPercentageB2B": 100, + "orderItemSessionPercentage": 15.62, + "orderItemSessionPercentageB2B": 7.46, + "unitSessionPercentage": 16.69, + "unitSessionPercentageB2B": 7.46, + "averageOfferCount": 229, + "averageParentItems": 126, + "feedbackReceived": 0, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-19", + "salesByDate": { + "orderedProductSales": { + "amount": 12651.3, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 543.03, + "currencyCode": "USD" + }, + "unitsOrdered": 603, + "unitsOrderedB2B": 25, + "totalOrderItems": 570, + "totalOrderItemsB2B": 13, + "averageSalesPerOrderItem": { + "amount": 22.2, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 41.77, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.06, + "averageUnitsPerOrderItemB2B": 1.92, + "averageSellingPrice": { + "amount": 20.98, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 21.72, + "currencyCode": "USD" + }, + "unitsRefunded": 15, + "refundRate": 2.49, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 13521.58, + "currencyCode": "USD" + }, + "unitsShipped": 630, + "ordersShipped": 628 + }, + "trafficByDate": { + "browserPageViews": 2774, + "browserPageViewsB2B": 73, + "mobileAppPageViews": 4967, + "mobileAppPageViewsB2B": 140, + "pageViews": 7741, + "pageViewsB2B": 213, + "browserSessions": 1405, + "browserSessionsB2B": 42, + "mobileAppSessions": 2212, + "mobileAppSessionsB2B": 47, + "sessions": 3617, + "sessionsB2B": 89, + "buyBoxPercentage": 99.41, + "buyBoxPercentageB2B": 96.33, + "orderItemSessionPercentage": 15.76, + "orderItemSessionPercentageB2B": 14.61, + "unitSessionPercentage": 16.67, + "unitSessionPercentageB2B": 28.09, + "averageOfferCount": 231, + "averageParentItems": 127, + "feedbackReceived": 1, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-20", + "salesByDate": { + "orderedProductSales": { + "amount": 10485.75, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 234.2, + "currencyCode": "USD" + }, + "unitsOrdered": 501, + "unitsOrderedB2B": 12, + "totalOrderItems": 482, + "totalOrderItemsB2B": 10, + "averageSalesPerOrderItem": { + "amount": 21.75, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 23.42, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.04, + "averageUnitsPerOrderItemB2B": 1.2, + "averageSellingPrice": { + "amount": 20.93, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 19.52, + "currencyCode": "USD" + }, + "unitsRefunded": 13, + "refundRate": 2.59, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 12366.12, + "currencyCode": "USD" + }, + "unitsShipped": 595, + "ordersShipped": 592 + }, + "trafficByDate": { + "browserPageViews": 2303, + "browserPageViewsB2B": 62, + "mobileAppPageViews": 5595, + "mobileAppPageViewsB2B": 28, + "pageViews": 7898, + "pageViewsB2B": 90, + "browserSessions": 1325, + "browserSessionsB2B": 33, + "mobileAppSessions": 1982, + "mobileAppSessionsB2B": 15, + "sessions": 3307, + "sessionsB2B": 48, + "buyBoxPercentage": 98.62, + "buyBoxPercentageB2B": 94.64, + "orderItemSessionPercentage": 14.58, + "orderItemSessionPercentageB2B": 20.83, + "unitSessionPercentage": 15.15, + "unitSessionPercentageB2B": 25, + "averageOfferCount": 232, + "averageParentItems": 128, + "feedbackReceived": 2, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-21", + "salesByDate": { + "orderedProductSales": { + "amount": 11634.7, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 180.2, + "currencyCode": "USD" + }, + "unitsOrdered": 551, + "unitsOrderedB2B": 8, + "totalOrderItems": 538, + "totalOrderItemsB2B": 8, + "averageSalesPerOrderItem": { + "amount": 21.63, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 22.52, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.02, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 21.12, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 22.52, + "currencyCode": "USD" + }, + "unitsRefunded": 13, + "refundRate": 2.36, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 11564.61, + "currencyCode": "USD" + }, + "unitsShipped": 562, + "ordersShipped": 561 + }, + "trafficByDate": { + "browserPageViews": 2348, + "browserPageViewsB2B": 47, + "mobileAppPageViews": 4122, + "mobileAppPageViewsB2B": 82, + "pageViews": 6470, + "pageViewsB2B": 129, + "browserSessions": 1288, + "browserSessionsB2B": 34, + "mobileAppSessions": 1940, + "mobileAppSessionsB2B": 31, + "sessions": 3228, + "sessionsB2B": 65, + "buyBoxPercentage": 98.75, + "buyBoxPercentageB2B": 89.29, + "orderItemSessionPercentage": 16.67, + "orderItemSessionPercentageB2B": 12.31, + "unitSessionPercentage": 17.07, + "unitSessionPercentageB2B": 12.31, + "averageOfferCount": 230, + "averageParentItems": 127, + "feedbackReceived": 1, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-22", + "salesByDate": { + "orderedProductSales": { + "amount": 11719.22, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 173.38, + "currencyCode": "USD" + }, + "unitsOrdered": 549, + "unitsOrderedB2B": 8, + "totalOrderItems": 535, + "totalOrderItemsB2B": 8, + "averageSalesPerOrderItem": { + "amount": 21.91, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 21.67, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.03, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 21.35, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 21.67, + "currencyCode": "USD" + }, + "unitsRefunded": 12, + "refundRate": 2.19, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 10704.55, + "currencyCode": "USD" + }, + "unitsShipped": 507, + "ordersShipped": 507 + }, + "trafficByDate": { + "browserPageViews": 1995, + "browserPageViewsB2B": 68, + "mobileAppPageViews": 3962, + "mobileAppPageViewsB2B": 47, + "pageViews": 5957, + "pageViewsB2B": 115, + "browserSessions": 1205, + "browserSessionsB2B": 47, + "mobileAppSessions": 1884, + "mobileAppSessionsB2B": 23, + "sessions": 3089, + "sessionsB2B": 70, + "buyBoxPercentage": 98.81, + "buyBoxPercentageB2B": 100, + "orderItemSessionPercentage": 17.32, + "orderItemSessionPercentageB2B": 11.43, + "unitSessionPercentage": 17.77, + "unitSessionPercentageB2B": 11.43, + "averageOfferCount": 230, + "averageParentItems": 127, + "feedbackReceived": 0, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-23", + "salesByDate": { + "orderedProductSales": { + "amount": 9995.56, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 54.79, + "currencyCode": "USD" + }, + "unitsOrdered": 478, + "unitsOrderedB2B": 3, + "totalOrderItems": 466, + "totalOrderItemsB2B": 3, + "averageSalesPerOrderItem": { + "amount": 21.45, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 18.26, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.03, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 20.91, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 18.26, + "currencyCode": "USD" + }, + "unitsRefunded": 13, + "refundRate": 2.72, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 10477.08, + "currencyCode": "USD" + }, + "unitsShipped": 491, + "ordersShipped": 490 + }, + "trafficByDate": { + "browserPageViews": 1921, + "browserPageViewsB2B": 65, + "mobileAppPageViews": 3709, + "mobileAppPageViewsB2B": 52, + "pageViews": 5630, + "pageViewsB2B": 117, + "browserSessions": 1160, + "browserSessionsB2B": 37, + "mobileAppSessions": 1783, + "mobileAppSessionsB2B": 23, + "sessions": 2943, + "sessionsB2B": 60, + "buyBoxPercentage": 98.85, + "buyBoxPercentageB2B": 100, + "orderItemSessionPercentage": 15.83, + "orderItemSessionPercentageB2B": 5, + "unitSessionPercentage": 16.24, + "unitSessionPercentageB2B": 5, + "averageOfferCount": 238, + "averageParentItems": 135, + "feedbackReceived": 1, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-24", + "salesByDate": { + "orderedProductSales": { + "amount": 10844.66, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 198.87, + "currencyCode": "USD" + }, + "unitsOrdered": 531, + "unitsOrderedB2B": 9, + "totalOrderItems": 511, + "totalOrderItemsB2B": 9, + "averageSalesPerOrderItem": { + "amount": 21.22, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 22.1, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.04, + "averageUnitsPerOrderItemB2B": 1, + "averageSellingPrice": { + "amount": 20.42, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 22.1, + "currencyCode": "USD" + }, + "unitsRefunded": 10, + "refundRate": 1.88, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 7532.8, + "currencyCode": "USD" + }, + "unitsShipped": 364, + "ordersShipped": 364 + }, + "trafficByDate": { + "browserPageViews": 2124, + "browserPageViewsB2B": 67, + "mobileAppPageViews": 4332, + "mobileAppPageViewsB2B": 78, + "pageViews": 6456, + "pageViewsB2B": 145, + "browserSessions": 1330, + "browserSessionsB2B": 35, + "mobileAppSessions": 2051, + "mobileAppSessionsB2B": 37, + "sessions": 3381, + "sessionsB2B": 72, + "buyBoxPercentage": 98.76, + "buyBoxPercentageB2B": 95.06, + "orderItemSessionPercentage": 15.11, + "orderItemSessionPercentageB2B": 12.5, + "unitSessionPercentage": 15.71, + "unitSessionPercentageB2B": 12.5, + "averageOfferCount": 238, + "averageParentItems": 133, + "feedbackReceived": 0, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + }, + { + "date": "2024-02-25", + "salesByDate": { + "orderedProductSales": { + "amount": 13236.96, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 225.97, + "currencyCode": "USD" + }, + "unitsOrdered": 639, + "unitsOrderedB2B": 12, + "totalOrderItems": 616, + "totalOrderItemsB2B": 11, + "averageSalesPerOrderItem": { + "amount": 21.49, + "currencyCode": "USD" + }, + "averageSalesPerOrderItemB2B": { + "amount": 20.54, + "currencyCode": "USD" + }, + "averageUnitsPerOrderItem": 1.04, + "averageUnitsPerOrderItemB2B": 1.09, + "averageSellingPrice": { + "amount": 20.72, + "currencyCode": "USD" + }, + "averageSellingPriceB2B": { + "amount": 18.83, + "currencyCode": "USD" + }, + "unitsRefunded": 5, + "refundRate": 0.78, + "claimsGranted": 0, + "claimsAmount": { + "amount": 0, + "currencyCode": "USD" + }, + "shippedProductSales": { + "amount": 10936.66, + "currencyCode": "USD" + }, + "unitsShipped": 517, + "ordersShipped": 517 + }, + "trafficByDate": { + "browserPageViews": 2367, + "browserPageViewsB2B": 34, + "mobileAppPageViews": 5169, + "mobileAppPageViewsB2B": 59, + "pageViews": 7536, + "pageViewsB2B": 93, + "browserSessions": 1399, + "browserSessionsB2B": 26, + "mobileAppSessions": 2387, + "mobileAppSessionsB2B": 26, + "sessions": 3786, + "sessionsB2B": 52, + "buyBoxPercentage": 98.94, + "buyBoxPercentageB2B": 96.72, + "orderItemSessionPercentage": 16.27, + "orderItemSessionPercentageB2B": 21.15, + "unitSessionPercentage": 16.88, + "unitSessionPercentageB2B": 23.08, + "averageOfferCount": 266, + "averageParentItems": 163, + "feedbackReceived": 0, + "negativeFeedbackReceived": 0, + "receivedNegativeFeedbackRate": 0 + } + } + ], + "salesAndTrafficByAsin": [ + { + "parentAsin": "B07JWCZKSJ", + "salesByAsin": { + "unitsOrdered": 4, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 54.9, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 4, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 18, + "browserSessionsB2B": 0, + "mobileAppSessions": 15, + "mobileAppSessionsB2B": 0, + "sessions": 33, + "sessionsB2B": 0, + "browserSessionPercentage": 0.12, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.06, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.08, + "sessionPercentageB2B": 0, + "browserPageViews": 29, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 21, + "mobileAppPageViewsB2B": 0, + "pageViews": 50, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.11, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.06, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 12.12, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B09ZDDDS1X", + "salesByAsin": { + "unitsOrdered": 1, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 14.97, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 1, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 13, + "browserSessionsB2B": 0, + "mobileAppSessions": 10, + "mobileAppSessionsB2B": 0, + "sessions": 23, + "sessionsB2B": 0, + "browserSessionPercentage": 0.08, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.06, + "sessionPercentageB2B": 0, + "browserPageViews": 16, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 10, + "mobileAppPageViewsB2B": 0, + "pageViews": 26, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.06, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 92.31, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 4.35, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0B14B89VH", + "salesByAsin": { + "unitsOrdered": 4, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 53.88, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 3, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 5, + "browserSessionsB2B": 0, + "mobileAppSessions": 10, + "mobileAppSessionsB2B": 0, + "sessions": 15, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 9, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 14, + "mobileAppPageViewsB2B": 0, + "pageViews": 23, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 26.67, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0B43N9JKF", + "salesByAsin": { + "unitsOrdered": 381, + "unitsOrderedB2B": 3, + "orderedProductSales": { + "amount": 5276.48, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 41.01, + "currencyCode": "USD" + }, + "totalOrderItems": 365, + "totalOrderItemsB2B": 3 + }, + "trafficByAsin": { + "browserSessions": 1023, + "browserSessionsB2B": 36, + "mobileAppSessions": 2370, + "mobileAppSessionsB2B": 22, + "sessions": 3393, + "sessionsB2B": 58, + "browserSessionPercentage": 6.69, + "browserSessionPercentageB2B": 8.29, + "mobileAppSessionPercentage": 9.64, + "mobileAppSessionPercentageB2B": 6.49, + "sessionPercentage": 8.51, + "sessionPercentageB2B": 7.5, + "browserPageViews": 1377, + "browserPageViewsB2B": 47, + "mobileAppPageViews": 4478, + "mobileAppPageViewsB2B": 37, + "pageViews": 5855, + "pageViewsB2B": 84, + "browserPageViewsPercentage": 5.28, + "browserPageViewsPercentageB2B": 6.71, + "mobileAppPageViewsPercentage": 7.7, + "mobileAppPageViewsPercentageB2B": 3.33, + "pageViewsPercentage": 6.95, + "pageViewsPercentageB2B": 4.64, + "buyBoxPercentage": 99.56, + "buyBoxPercentageB2B": 84.75, + "unitSessionPercentage": 11.23, + "unitSessionPercentageB2B": 5.17 + } + }, + { + "parentAsin": "B0B71WZ2MF", + "salesByAsin": { + "unitsOrdered": 79, + "unitsOrderedB2B": 1, + "orderedProductSales": { + "amount": 1730.1, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 21.9, + "currencyCode": "USD" + }, + "totalOrderItems": 76, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 187, + "browserSessionsB2B": 2, + "mobileAppSessions": 219, + "mobileAppSessionsB2B": 2, + "sessions": 406, + "sessionsB2B": 4, + "browserSessionPercentage": 1.22, + "browserSessionPercentageB2B": 0.46, + "mobileAppSessionPercentage": 0.89, + "mobileAppSessionPercentageB2B": 0.59, + "sessionPercentage": 1.02, + "sessionPercentageB2B": 0.52, + "browserPageViews": 331, + "browserPageViewsB2B": 7, + "mobileAppPageViews": 574, + "mobileAppPageViewsB2B": 7, + "pageViews": 905, + "pageViewsB2B": 14, + "browserPageViewsPercentage": 1.27, + "browserPageViewsPercentageB2B": 1, + "mobileAppPageViewsPercentage": 0.99, + "mobileAppPageViewsPercentageB2B": 0.63, + "pageViewsPercentage": 1.07, + "pageViewsPercentageB2B": 0.77, + "buyBoxPercentage": 98.67, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 19.46, + "unitSessionPercentageB2B": 25 + } + }, + { + "parentAsin": "B0BHWD3DW6", + "salesByAsin": { + "unitsOrdered": 147, + "unitsOrderedB2B": 2, + "orderedProductSales": { + "amount": 2482.61, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 33.8, + "currencyCode": "USD" + }, + "totalOrderItems": 135, + "totalOrderItemsB2B": 2 + }, + "trafficByAsin": { + "browserSessions": 650, + "browserSessionsB2B": 14, + "mobileAppSessions": 515, + "mobileAppSessionsB2B": 8, + "sessions": 1165, + "sessionsB2B": 22, + "browserSessionPercentage": 4.25, + "browserSessionPercentageB2B": 3.23, + "mobileAppSessionPercentage": 2.1, + "mobileAppSessionPercentageB2B": 2.36, + "sessionPercentage": 2.92, + "sessionPercentageB2B": 2.85, + "browserPageViews": 977, + "browserPageViewsB2B": 20, + "mobileAppPageViews": 952, + "mobileAppPageViewsB2B": 12, + "pageViews": 1929, + "pageViewsB2B": 32, + "browserPageViewsPercentage": 3.75, + "browserPageViewsPercentageB2B": 2.86, + "mobileAppPageViewsPercentage": 1.64, + "mobileAppPageViewsPercentageB2B": 1.08, + "pageViewsPercentage": 2.29, + "pageViewsPercentageB2B": 1.77, + "buyBoxPercentage": 98.31, + "buyBoxPercentageB2B": 96.3, + "unitSessionPercentage": 12.62, + "unitSessionPercentageB2B": 9.09 + } + }, + { + "parentAsin": "B0BHWGQF3B", + "salesByAsin": { + "unitsOrdered": 147, + "unitsOrderedB2B": 4, + "orderedProductSales": { + "amount": 2481.77, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 67.6, + "currencyCode": "USD" + }, + "totalOrderItems": 138, + "totalOrderItemsB2B": 4 + }, + "trafficByAsin": { + "browserSessions": 492, + "browserSessionsB2B": 13, + "mobileAppSessions": 506, + "mobileAppSessionsB2B": 1, + "sessions": 998, + "sessionsB2B": 14, + "browserSessionPercentage": 3.22, + "browserSessionPercentageB2B": 3, + "mobileAppSessionPercentage": 2.06, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 2.5, + "sessionPercentageB2B": 1.81, + "browserPageViews": 857, + "browserPageViewsB2B": 17, + "mobileAppPageViews": 1146, + "mobileAppPageViewsB2B": 3, + "pageViews": 2003, + "pageViewsB2B": 20, + "browserPageViewsPercentage": 3.29, + "browserPageViewsPercentageB2B": 2.43, + "mobileAppPageViewsPercentage": 1.97, + "mobileAppPageViewsPercentageB2B": 0.27, + "pageViewsPercentage": 2.38, + "pageViewsPercentageB2B": 1.1, + "buyBoxPercentage": 98.36, + "buyBoxPercentageB2B": 92.86, + "unitSessionPercentage": 14.73, + "unitSessionPercentageB2B": 28.57 + } + }, + { + "parentAsin": "B0BKLMBFVB", + "salesByAsin": { + "unitsOrdered": 776, + "unitsOrderedB2B": 9, + "orderedProductSales": { + "amount": 11526.8, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 132.02, + "currencyCode": "USD" + }, + "totalOrderItems": 735, + "totalOrderItemsB2B": 8 + }, + "trafficByAsin": { + "browserSessions": 1429, + "browserSessionsB2B": 35, + "mobileAppSessions": 1971, + "mobileAppSessionsB2B": 23, + "sessions": 3400, + "sessionsB2B": 58, + "browserSessionPercentage": 9.34, + "browserSessionPercentageB2B": 8.06, + "mobileAppSessionPercentage": 8.02, + "mobileAppSessionPercentageB2B": 6.78, + "sessionPercentage": 8.53, + "sessionPercentageB2B": 7.5, + "browserPageViews": 3941, + "browserPageViewsB2B": 62, + "mobileAppPageViews": 8321, + "mobileAppPageViewsB2B": 57, + "pageViews": 12262, + "pageViewsB2B": 119, + "browserPageViewsPercentage": 15.12, + "browserPageViewsPercentageB2B": 8.86, + "mobileAppPageViewsPercentage": 14.31, + "mobileAppPageViewsPercentageB2B": 5.14, + "pageViewsPercentage": 14.56, + "pageViewsPercentageB2B": 6.57, + "buyBoxPercentage": 99.26, + "buyBoxPercentageB2B": 94.12, + "unitSessionPercentage": 22.82, + "unitSessionPercentageB2B": 15.52 + } + }, + { + "parentAsin": "B0BM9XXZF9", + "salesByAsin": { + "unitsOrdered": 159, + "unitsOrderedB2B": 2, + "orderedProductSales": { + "amount": 2516.21, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 28.62, + "currencyCode": "USD" + }, + "totalOrderItems": 135, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 307, + "browserSessionsB2B": 12, + "mobileAppSessions": 495, + "mobileAppSessionsB2B": 9, + "sessions": 802, + "sessionsB2B": 21, + "browserSessionPercentage": 2.01, + "browserSessionPercentageB2B": 2.76, + "mobileAppSessionPercentage": 2.01, + "mobileAppSessionPercentageB2B": 2.65, + "sessionPercentage": 2.01, + "sessionPercentageB2B": 2.72, + "browserPageViews": 549, + "browserPageViewsB2B": 21, + "mobileAppPageViews": 1525, + "mobileAppPageViewsB2B": 22, + "pageViews": 2074, + "pageViewsB2B": 43, + "browserPageViewsPercentage": 2.11, + "browserPageViewsPercentageB2B": 3, + "mobileAppPageViewsPercentage": 2.62, + "mobileAppPageViewsPercentageB2B": 1.98, + "pageViewsPercentage": 2.46, + "pageViewsPercentageB2B": 2.38, + "buyBoxPercentage": 99.61, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 19.83, + "unitSessionPercentageB2B": 9.52 + } + }, + { + "parentAsin": "B0BTM7F76V", + "salesByAsin": { + "unitsOrdered": 54, + "unitsOrderedB2B": 1, + "orderedProductSales": { + "amount": 878.8, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 16.9, + "currencyCode": "USD" + }, + "totalOrderItems": 53, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 247, + "browserSessionsB2B": 10, + "mobileAppSessions": 237, + "mobileAppSessionsB2B": 2, + "sessions": 484, + "sessionsB2B": 12, + "browserSessionPercentage": 1.61, + "browserSessionPercentageB2B": 2.3, + "mobileAppSessionPercentage": 0.96, + "mobileAppSessionPercentageB2B": 0.59, + "sessionPercentage": 1.21, + "sessionPercentageB2B": 1.55, + "browserPageViews": 308, + "browserPageViewsB2B": 12, + "mobileAppPageViews": 318, + "mobileAppPageViewsB2B": 2, + "pageViews": 626, + "pageViewsB2B": 14, + "browserPageViewsPercentage": 1.18, + "browserPageViewsPercentageB2B": 1.71, + "mobileAppPageViewsPercentage": 0.55, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.74, + "pageViewsPercentageB2B": 0.77, + "buyBoxPercentage": 99.26, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 11.16, + "unitSessionPercentageB2B": 8.33 + } + }, + { + "parentAsin": "B0BTMKDMYJ", + "salesByAsin": { + "unitsOrdered": 627, + "unitsOrderedB2B": 6, + "orderedProductSales": { + "amount": 13709.4, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 131.4, + "currencyCode": "USD" + }, + "totalOrderItems": 603, + "totalOrderItemsB2B": 6 + }, + "trafficByAsin": { + "browserSessions": 1210, + "browserSessionsB2B": 31, + "mobileAppSessions": 2348, + "mobileAppSessionsB2B": 28, + "sessions": 3558, + "sessionsB2B": 59, + "browserSessionPercentage": 7.91, + "browserSessionPercentageB2B": 7.14, + "mobileAppSessionPercentage": 9.55, + "mobileAppSessionPercentageB2B": 8.26, + "sessionPercentage": 8.92, + "sessionPercentageB2B": 7.63, + "browserPageViews": 1600, + "browserPageViewsB2B": 40, + "mobileAppPageViews": 3111, + "mobileAppPageViewsB2B": 35, + "pageViews": 4711, + "pageViewsB2B": 75, + "browserPageViewsPercentage": 6.14, + "browserPageViewsPercentageB2B": 5.71, + "mobileAppPageViewsPercentage": 5.35, + "mobileAppPageViewsPercentageB2B": 3.15, + "pageViewsPercentage": 5.59, + "pageViewsPercentageB2B": 4.14, + "buyBoxPercentage": 99.91, + "buyBoxPercentageB2B": 95.31, + "unitSessionPercentage": 17.62, + "unitSessionPercentageB2B": 10.17 + } + }, + { + "parentAsin": "B0BV743RJS", + "salesByAsin": { + "unitsOrdered": 97, + "unitsOrderedB2B": 1, + "orderedProductSales": { + "amount": 2338.35, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 23.9, + "currencyCode": "USD" + }, + "totalOrderItems": 87, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 341, + "browserSessionsB2B": 1, + "mobileAppSessions": 503, + "mobileAppSessionsB2B": 11, + "sessions": 844, + "sessionsB2B": 12, + "browserSessionPercentage": 2.23, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 2.05, + "mobileAppSessionPercentageB2B": 3.24, + "sessionPercentage": 2.12, + "sessionPercentageB2B": 1.55, + "browserPageViews": 614, + "browserPageViewsB2B": 3, + "mobileAppPageViews": 1213, + "mobileAppPageViewsB2B": 19, + "pageViews": 1827, + "pageViewsB2B": 22, + "browserPageViewsPercentage": 2.36, + "browserPageViewsPercentageB2B": 0.43, + "mobileAppPageViewsPercentage": 2.09, + "mobileAppPageViewsPercentageB2B": 1.71, + "pageViewsPercentage": 2.17, + "pageViewsPercentageB2B": 1.22, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 11.49, + "unitSessionPercentageB2B": 8.33 + } + }, + { + "parentAsin": "B0BX6HJN28", + "salesByAsin": { + "unitsOrdered": 376, + "unitsOrderedB2B": 10, + "orderedProductSales": { + "amount": 7457.31, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 195.8, + "currencyCode": "USD" + }, + "totalOrderItems": 352, + "totalOrderItemsB2B": 8 + }, + "trafficByAsin": { + "browserSessions": 731, + "browserSessionsB2B": 22, + "mobileAppSessions": 1079, + "mobileAppSessionsB2B": 24, + "sessions": 1810, + "sessionsB2B": 46, + "browserSessionPercentage": 4.78, + "browserSessionPercentageB2B": 5.07, + "mobileAppSessionPercentage": 4.39, + "mobileAppSessionPercentageB2B": 7.08, + "sessionPercentage": 4.54, + "sessionPercentageB2B": 5.95, + "browserPageViews": 1072, + "browserPageViewsB2B": 28, + "mobileAppPageViews": 2208, + "mobileAppPageViewsB2B": 48, + "pageViews": 3280, + "pageViewsB2B": 76, + "browserPageViewsPercentage": 4.11, + "browserPageViewsPercentageB2B": 4, + "mobileAppPageViewsPercentage": 3.8, + "mobileAppPageViewsPercentageB2B": 4.32, + "pageViewsPercentage": 3.9, + "pageViewsPercentageB2B": 4.2, + "buyBoxPercentage": 99.25, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 20.77, + "unitSessionPercentageB2B": 21.74 + } + }, + { + "parentAsin": "B0C5N1GBDL", + "salesByAsin": { + "unitsOrdered": 1616, + "unitsOrderedB2B": 39, + "orderedProductSales": { + "amount": 40040.07, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 891.02, + "currencyCode": "USD" + }, + "totalOrderItems": 1584, + "totalOrderItemsB2B": 30 + }, + "trafficByAsin": { + "browserSessions": 1871, + "browserSessionsB2B": 75, + "mobileAppSessions": 3763, + "mobileAppSessionsB2B": 66, + "sessions": 5634, + "sessionsB2B": 141, + "browserSessionPercentage": 12.23, + "browserSessionPercentageB2B": 17.28, + "mobileAppSessionPercentage": 15.31, + "mobileAppSessionPercentageB2B": 19.47, + "sessionPercentage": 14.13, + "sessionPercentageB2B": 18.24, + "browserPageViews": 3322, + "browserPageViewsB2B": 124, + "mobileAppPageViews": 10344, + "mobileAppPageViewsB2B": 518, + "pageViews": 13666, + "pageViewsB2B": 642, + "browserPageViewsPercentage": 12.74, + "browserPageViewsPercentageB2B": 17.71, + "mobileAppPageViewsPercentage": 17.79, + "mobileAppPageViewsPercentageB2B": 46.67, + "pageViewsPercentage": 16.23, + "pageViewsPercentageB2B": 35.47, + "buyBoxPercentage": 99.48, + "buyBoxPercentageB2B": 96.76, + "unitSessionPercentage": 28.68, + "unitSessionPercentageB2B": 27.66 + } + }, + { + "parentAsin": "B0C72K4WKC", + "salesByAsin": { + "unitsOrdered": 141, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 2348.25, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 133, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 245, + "browserSessionsB2B": 6, + "mobileAppSessions": 501, + "mobileAppSessionsB2B": 7, + "sessions": 746, + "sessionsB2B": 13, + "browserSessionPercentage": 1.6, + "browserSessionPercentageB2B": 1.38, + "mobileAppSessionPercentage": 2.04, + "mobileAppSessionPercentageB2B": 2.06, + "sessionPercentage": 1.87, + "sessionPercentageB2B": 1.68, + "browserPageViews": 302, + "browserPageViewsB2B": 6, + "mobileAppPageViews": 678, + "mobileAppPageViewsB2B": 13, + "pageViews": 980, + "pageViewsB2B": 19, + "browserPageViewsPercentage": 1.16, + "browserPageViewsPercentageB2B": 0.86, + "mobileAppPageViewsPercentage": 1.17, + "mobileAppPageViewsPercentageB2B": 1.17, + "pageViewsPercentage": 1.16, + "pageViewsPercentageB2B": 1.05, + "buyBoxPercentage": 97.88, + "buyBoxPercentageB2B": 94.74, + "unitSessionPercentage": 18.9, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CCF45HVQ", + "salesByAsin": { + "unitsOrdered": 82, + "unitsOrderedB2B": 2, + "orderedProductSales": { + "amount": 1773.9, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 43.8, + "currencyCode": "USD" + }, + "totalOrderItems": 81, + "totalOrderItemsB2B": 2 + }, + "trafficByAsin": { + "browserSessions": 149, + "browserSessionsB2B": 4, + "mobileAppSessions": 291, + "mobileAppSessionsB2B": 5, + "sessions": 440, + "sessionsB2B": 9, + "browserSessionPercentage": 0.97, + "browserSessionPercentageB2B": 0.92, + "mobileAppSessionPercentage": 1.18, + "mobileAppSessionPercentageB2B": 1.47, + "sessionPercentage": 1.1, + "sessionPercentageB2B": 1.16, + "browserPageViews": 178, + "browserPageViewsB2B": 4, + "mobileAppPageViews": 408, + "mobileAppPageViewsB2B": 7, + "pageViews": 586, + "pageViewsB2B": 11, + "browserPageViewsPercentage": 0.68, + "browserPageViewsPercentageB2B": 0.57, + "mobileAppPageViewsPercentage": 0.7, + "mobileAppPageViewsPercentageB2B": 0.63, + "pageViewsPercentage": 0.7, + "pageViewsPercentageB2B": 0.61, + "buyBoxPercentage": 98.7, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 18.64, + "unitSessionPercentageB2B": 22.22 + } + }, + { + "parentAsin": "B0CDGTTG6Y", + "salesByAsin": { + "unitsOrdered": 12, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 200.25, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 11, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 59, + "browserSessionsB2B": 1, + "mobileAppSessions": 67, + "mobileAppSessionsB2B": 0, + "sessions": 126, + "sessionsB2B": 1, + "browserSessionPercentage": 0.39, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.27, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.32, + "sessionPercentageB2B": 0.13, + "browserPageViews": 76, + "browserPageViewsB2B": 1, + "mobileAppPageViews": 93, + "mobileAppPageViewsB2B": 0, + "pageViews": 169, + "pageViewsB2B": 1, + "browserPageViewsPercentage": 0.29, + "browserPageViewsPercentageB2B": 0.14, + "mobileAppPageViewsPercentage": 0.16, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.2, + "pageViewsPercentageB2B": 0.06, + "buyBoxPercentage": 96.27, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 9.52, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CDM9C122", + "salesByAsin": { + "unitsOrdered": 30, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 747, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 27, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 250, + "browserSessionsB2B": 8, + "mobileAppSessions": 281, + "mobileAppSessionsB2B": 2, + "sessions": 531, + "sessionsB2B": 10, + "browserSessionPercentage": 1.63, + "browserSessionPercentageB2B": 1.84, + "mobileAppSessionPercentage": 1.14, + "mobileAppSessionPercentageB2B": 0.59, + "sessionPercentage": 1.33, + "sessionPercentageB2B": 1.29, + "browserPageViews": 302, + "browserPageViewsB2B": 13, + "mobileAppPageViews": 386, + "mobileAppPageViewsB2B": 2, + "pageViews": 688, + "pageViewsB2B": 15, + "browserPageViewsPercentage": 1.16, + "browserPageViewsPercentageB2B": 1.86, + "mobileAppPageViewsPercentage": 0.66, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.82, + "pageViewsPercentageB2B": 0.83, + "buyBoxPercentage": 93.98, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 5.65, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CDXZWVGN", + "salesByAsin": { + "unitsOrdered": 38, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 452.2, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 34, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 180, + "browserSessionsB2B": 4, + "mobileAppSessions": 227, + "mobileAppSessionsB2B": 3, + "sessions": 407, + "sessionsB2B": 7, + "browserSessionPercentage": 1.18, + "browserSessionPercentageB2B": 0.92, + "mobileAppSessionPercentage": 0.92, + "mobileAppSessionPercentageB2B": 0.88, + "sessionPercentage": 1.02, + "sessionPercentageB2B": 0.91, + "browserPageViews": 239, + "browserPageViewsB2B": 4, + "mobileAppPageViews": 284, + "mobileAppPageViewsB2B": 5, + "pageViews": 523, + "pageViewsB2B": 9, + "browserPageViewsPercentage": 0.92, + "browserPageViewsPercentageB2B": 0.57, + "mobileAppPageViewsPercentage": 0.49, + "mobileAppPageViewsPercentageB2B": 0.45, + "pageViewsPercentage": 0.62, + "pageViewsPercentageB2B": 0.5, + "buyBoxPercentage": 96.83, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 9.34, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CF2FCYMZ", + "salesByAsin": { + "unitsOrdered": 25, + "unitsOrderedB2B": 1, + "orderedProductSales": { + "amount": 722.5, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 28.9, + "currencyCode": "USD" + }, + "totalOrderItems": 23, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 232, + "browserSessionsB2B": 4, + "mobileAppSessions": 312, + "mobileAppSessionsB2B": 5, + "sessions": 544, + "sessionsB2B": 9, + "browserSessionPercentage": 1.52, + "browserSessionPercentageB2B": 0.92, + "mobileAppSessionPercentage": 1.27, + "mobileAppSessionPercentageB2B": 1.47, + "sessionPercentage": 1.36, + "sessionPercentageB2B": 1.16, + "browserPageViews": 293, + "browserPageViewsB2B": 4, + "mobileAppPageViews": 437, + "mobileAppPageViewsB2B": 9, + "pageViews": 730, + "pageViewsB2B": 13, + "browserPageViewsPercentage": 1.12, + "browserPageViewsPercentageB2B": 0.57, + "mobileAppPageViewsPercentage": 0.75, + "mobileAppPageViewsPercentageB2B": 0.81, + "pageViewsPercentage": 0.87, + "pageViewsPercentageB2B": 0.72, + "buyBoxPercentage": 99.15, + "buyBoxPercentageB2B": 84.62, + "unitSessionPercentage": 4.6, + "unitSessionPercentageB2B": 11.11 + } + }, + { + "parentAsin": "B0CG4JGTSW", + "salesByAsin": { + "unitsOrdered": 173, + "unitsOrderedB2B": 2, + "orderedProductSales": { + "amount": 4052.96, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 42.56, + "currencyCode": "USD" + }, + "totalOrderItems": 170, + "totalOrderItemsB2B": 2 + }, + "trafficByAsin": { + "browserSessions": 349, + "browserSessionsB2B": 10, + "mobileAppSessions": 730, + "mobileAppSessionsB2B": 12, + "sessions": 1079, + "sessionsB2B": 22, + "browserSessionPercentage": 2.28, + "browserSessionPercentageB2B": 2.3, + "mobileAppSessionPercentage": 2.97, + "mobileAppSessionPercentageB2B": 3.54, + "sessionPercentage": 2.71, + "sessionPercentageB2B": 2.85, + "browserPageViews": 578, + "browserPageViewsB2B": 28, + "mobileAppPageViews": 1657, + "mobileAppPageViewsB2B": 32, + "pageViews": 2235, + "pageViewsB2B": 60, + "browserPageViewsPercentage": 2.22, + "browserPageViewsPercentageB2B": 4, + "mobileAppPageViewsPercentage": 2.85, + "mobileAppPageViewsPercentageB2B": 2.88, + "pageViewsPercentage": 2.65, + "pageViewsPercentageB2B": 3.31, + "buyBoxPercentage": 99.65, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 16.03, + "unitSessionPercentageB2B": 9.09 + } + }, + { + "parentAsin": "B0CGV89ZBG", + "salesByAsin": { + "unitsOrdered": 25, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 249.75, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 20, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 126, + "browserSessionsB2B": 5, + "mobileAppSessions": 82, + "mobileAppSessionsB2B": 1, + "sessions": 208, + "sessionsB2B": 6, + "browserSessionPercentage": 0.82, + "browserSessionPercentageB2B": 1.15, + "mobileAppSessionPercentage": 0.33, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.52, + "sessionPercentageB2B": 0.78, + "browserPageViews": 164, + "browserPageViewsB2B": 5, + "mobileAppPageViews": 149, + "mobileAppPageViewsB2B": 1, + "pageViews": 313, + "pageViewsB2B": 6, + "browserPageViewsPercentage": 0.63, + "browserPageViewsPercentageB2B": 0.71, + "mobileAppPageViewsPercentage": 0.26, + "mobileAppPageViewsPercentageB2B": 0.09, + "pageViewsPercentage": 0.37, + "pageViewsPercentageB2B": 0.33, + "buyBoxPercentage": 98.4, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 12.02, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CK8C6JF9", + "salesByAsin": { + "unitsOrdered": 11, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 11, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 45, + "browserSessionsB2B": 1, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 47, + "sessionsB2B": 1, + "browserSessionPercentage": 0.29, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.12, + "sessionPercentageB2B": 0.13, + "browserPageViews": 54, + "browserPageViewsB2B": 1, + "mobileAppPageViews": 3, + "mobileAppPageViewsB2B": 0, + "pageViews": 57, + "pageViewsB2B": 1, + "browserPageViewsPercentage": 0.21, + "browserPageViewsPercentageB2B": 0.14, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.07, + "pageViewsPercentageB2B": 0.06, + "buyBoxPercentage": 96.49, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 23.4, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CK8CXGZV", + "salesByAsin": { + "unitsOrdered": 9, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 9, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 89, + "browserSessionsB2B": 3, + "mobileAppSessions": 10, + "mobileAppSessionsB2B": 0, + "sessions": 99, + "sessionsB2B": 3, + "browserSessionPercentage": 0.58, + "browserSessionPercentageB2B": 0.69, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.25, + "sessionPercentageB2B": 0.39, + "browserPageViews": 108, + "browserPageViewsB2B": 4, + "mobileAppPageViews": 11, + "mobileAppPageViewsB2B": 0, + "pageViews": 119, + "pageViewsB2B": 4, + "browserPageViewsPercentage": 0.41, + "browserPageViewsPercentageB2B": 0.57, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.14, + "pageViewsPercentageB2B": 0.22, + "buyBoxPercentage": 72.27, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 9.09, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CK8MHBPY", + "salesByAsin": { + "unitsOrdered": 2, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 60, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 2, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 79, + "browserSessionsB2B": 0, + "mobileAppSessions": 67, + "mobileAppSessionsB2B": 0, + "sessions": 146, + "sessionsB2B": 0, + "browserSessionPercentage": 0.52, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.27, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.37, + "sessionPercentageB2B": 0, + "browserPageViews": 112, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 86, + "mobileAppPageViewsB2B": 0, + "pageViews": 198, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.43, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.15, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.24, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 95.83, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 1.37, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CKC3WQVS", + "salesByAsin": { + "unitsOrdered": 56, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 945.55, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 53, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 258, + "browserSessionsB2B": 0, + "mobileAppSessions": 270, + "mobileAppSessionsB2B": 3, + "sessions": 528, + "sessionsB2B": 3, + "browserSessionPercentage": 1.69, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 1.1, + "mobileAppSessionPercentageB2B": 0.88, + "sessionPercentage": 1.32, + "sessionPercentageB2B": 0.39, + "browserPageViews": 381, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 446, + "mobileAppPageViewsB2B": 5, + "pageViews": 827, + "pageViewsB2B": 5, + "browserPageViewsPercentage": 1.46, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.77, + "mobileAppPageViewsPercentageB2B": 0.45, + "pageViewsPercentage": 0.98, + "pageViewsPercentageB2B": 0.28, + "buyBoxPercentage": 97.58, + "buyBoxPercentageB2B": 40, + "unitSessionPercentage": 10.61, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CL4N5NWJ", + "salesByAsin": { + "unitsOrdered": 1, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 14.9, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 1, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 20, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 24, + "sessionsB2B": 0, + "browserSessionPercentage": 0.13, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.06, + "sessionPercentageB2B": 0, + "browserPageViews": 22, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 5, + "mobileAppPageViewsB2B": 0, + "pageViews": 27, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.08, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 85.19, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 4.17, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CMP4D3QW", + "salesByAsin": { + "unitsOrdered": 1377, + "unitsOrderedB2B": 32, + "orderedProductSales": { + "amount": 34087.47, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 766.33, + "currencyCode": "USD" + }, + "totalOrderItems": 1340, + "totalOrderItemsB2B": 27 + }, + "trafficByAsin": { + "browserSessions": 2885, + "browserSessionsB2B": 95, + "mobileAppSessions": 4788, + "mobileAppSessionsB2B": 73, + "sessions": 7673, + "sessionsB2B": 168, + "browserSessionPercentage": 18.86, + "browserSessionPercentageB2B": 21.89, + "mobileAppSessionPercentage": 19.48, + "mobileAppSessionPercentageB2B": 21.53, + "sessionPercentage": 19.24, + "sessionPercentageB2B": 21.73, + "browserPageViews": 5764, + "browserPageViewsB2B": 188, + "mobileAppPageViews": 14513, + "mobileAppPageViewsB2B": 222, + "pageViews": 20277, + "pageViewsB2B": 410, + "browserPageViewsPercentage": 22.11, + "browserPageViewsPercentageB2B": 26.86, + "mobileAppPageViewsPercentage": 24.96, + "mobileAppPageViewsPercentageB2B": 20, + "pageViewsPercentage": 24.08, + "pageViewsPercentageB2B": 22.65, + "buyBoxPercentage": 99.05, + "buyBoxPercentageB2B": 99.48, + "unitSessionPercentage": 17.95, + "unitSessionPercentageB2B": 19.05 + } + }, + { + "parentAsin": "B0CN5MTWQW", + "salesByAsin": { + "unitsOrdered": 79, + "unitsOrderedB2B": 1, + "orderedProductSales": { + "amount": 1335.1, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 16.9, + "currencyCode": "USD" + }, + "totalOrderItems": 73, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 417, + "browserSessionsB2B": 17, + "mobileAppSessions": 500, + "mobileAppSessionsB2B": 3, + "sessions": 917, + "sessionsB2B": 20, + "browserSessionPercentage": 2.73, + "browserSessionPercentageB2B": 3.92, + "mobileAppSessionPercentage": 2.03, + "mobileAppSessionPercentageB2B": 0.88, + "sessionPercentage": 2.3, + "sessionPercentageB2B": 2.59, + "browserPageViews": 517, + "browserPageViewsB2B": 17, + "mobileAppPageViews": 754, + "mobileAppPageViewsB2B": 5, + "pageViews": 1271, + "pageViewsB2B": 22, + "browserPageViewsPercentage": 1.98, + "browserPageViewsPercentageB2B": 2.43, + "mobileAppPageViewsPercentage": 1.3, + "mobileAppPageViewsPercentageB2B": 0.45, + "pageViewsPercentage": 1.51, + "pageViewsPercentageB2B": 1.22, + "buyBoxPercentage": 97.14, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 8.62, + "unitSessionPercentageB2B": 5 + } + }, + { + "parentAsin": "B0CN5PCPM3", + "salesByAsin": { + "unitsOrdered": 14, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 376.6, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 13, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 155, + "browserSessionsB2B": 2, + "mobileAppSessions": 145, + "mobileAppSessionsB2B": 1, + "sessions": 300, + "sessionsB2B": 3, + "browserSessionPercentage": 1.01, + "browserSessionPercentageB2B": 0.46, + "mobileAppSessionPercentage": 0.59, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.75, + "sessionPercentageB2B": 0.39, + "browserPageViews": 195, + "browserPageViewsB2B": 2, + "mobileAppPageViews": 188, + "mobileAppPageViewsB2B": 1, + "pageViews": 383, + "pageViewsB2B": 3, + "browserPageViewsPercentage": 0.75, + "browserPageViewsPercentageB2B": 0.29, + "mobileAppPageViewsPercentage": 0.32, + "mobileAppPageViewsPercentageB2B": 0.09, + "pageViewsPercentage": 0.45, + "pageViewsPercentageB2B": 0.17, + "buyBoxPercentage": 99.44, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 4.67, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CN7983W8", + "salesByAsin": { + "unitsOrdered": 84, + "unitsOrderedB2B": 2, + "orderedProductSales": { + "amount": 1047.84, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 25.89, + "currencyCode": "USD" + }, + "totalOrderItems": 81, + "totalOrderItemsB2B": 2 + }, + "trafficByAsin": { + "browserSessions": 331, + "browserSessionsB2B": 4, + "mobileAppSessions": 720, + "mobileAppSessionsB2B": 9, + "sessions": 1051, + "sessionsB2B": 13, + "browserSessionPercentage": 2.16, + "browserSessionPercentageB2B": 0.92, + "mobileAppSessionPercentage": 2.93, + "mobileAppSessionPercentageB2B": 2.65, + "sessionPercentage": 2.64, + "sessionPercentageB2B": 1.68, + "browserPageViews": 418, + "browserPageViewsB2B": 5, + "mobileAppPageViews": 1021, + "mobileAppPageViewsB2B": 12, + "pageViews": 1439, + "pageViewsB2B": 17, + "browserPageViewsPercentage": 1.6, + "browserPageViewsPercentageB2B": 0.71, + "mobileAppPageViewsPercentage": 1.76, + "mobileAppPageViewsPercentageB2B": 1.08, + "pageViewsPercentage": 1.71, + "pageViewsPercentageB2B": 0.94, + "buyBoxPercentage": 99.34, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 7.99, + "unitSessionPercentageB2B": 15.38 + } + }, + { + "parentAsin": "B0CNTHM63L", + "salesByAsin": { + "unitsOrdered": 39, + "unitsOrderedB2B": 1, + "orderedProductSales": { + "amount": 775.1, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 18.9, + "currencyCode": "USD" + }, + "totalOrderItems": 38, + "totalOrderItemsB2B": 1 + }, + "trafficByAsin": { + "browserSessions": 148, + "browserSessionsB2B": 3, + "mobileAppSessions": 271, + "mobileAppSessionsB2B": 2, + "sessions": 419, + "sessionsB2B": 5, + "browserSessionPercentage": 0.97, + "browserSessionPercentageB2B": 0.69, + "mobileAppSessionPercentage": 1.1, + "mobileAppSessionPercentageB2B": 0.59, + "sessionPercentage": 1.05, + "sessionPercentageB2B": 0.65, + "browserPageViews": 196, + "browserPageViewsB2B": 4, + "mobileAppPageViews": 355, + "mobileAppPageViewsB2B": 3, + "pageViews": 551, + "pageViewsB2B": 7, + "browserPageViewsPercentage": 0.75, + "browserPageViewsPercentageB2B": 0.57, + "mobileAppPageViewsPercentage": 0.61, + "mobileAppPageViewsPercentageB2B": 0.27, + "pageViewsPercentage": 0.65, + "pageViewsPercentageB2B": 0.39, + "buyBoxPercentage": 99.81, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 9.31, + "unitSessionPercentageB2B": 20 + } + }, + { + "parentAsin": "B0CPCX455S", + "salesByAsin": { + "unitsOrdered": 39, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 776.1, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 36, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 302, + "browserSessionsB2B": 5, + "mobileAppSessions": 343, + "mobileAppSessionsB2B": 4, + "sessions": 645, + "sessionsB2B": 9, + "browserSessionPercentage": 1.97, + "browserSessionPercentageB2B": 1.15, + "mobileAppSessionPercentage": 1.4, + "mobileAppSessionPercentageB2B": 1.18, + "sessionPercentage": 1.62, + "sessionPercentageB2B": 1.16, + "browserPageViews": 400, + "browserPageViewsB2B": 5, + "mobileAppPageViews": 477, + "mobileAppPageViewsB2B": 5, + "pageViews": 877, + "pageViewsB2B": 10, + "browserPageViewsPercentage": 1.53, + "browserPageViewsPercentageB2B": 0.71, + "mobileAppPageViewsPercentage": 0.82, + "mobileAppPageViewsPercentageB2B": 0.45, + "pageViewsPercentage": 1.04, + "pageViewsPercentageB2B": 0.55, + "buyBoxPercentage": 96.32, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 6.05, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CQYS6XL6", + "salesByAsin": { + "unitsOrdered": 2, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 19.98, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 2, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 89, + "browserSessionsB2B": 1, + "mobileAppSessions": 187, + "mobileAppSessionsB2B": 2, + "sessions": 276, + "sessionsB2B": 3, + "browserSessionPercentage": 0.58, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.76, + "mobileAppSessionPercentageB2B": 0.59, + "sessionPercentage": 0.69, + "sessionPercentageB2B": 0.39, + "browserPageViews": 111, + "browserPageViewsB2B": 1, + "mobileAppPageViews": 236, + "mobileAppPageViewsB2B": 2, + "pageViews": 347, + "pageViewsB2B": 3, + "browserPageViewsPercentage": 0.43, + "browserPageViewsPercentageB2B": 0.14, + "mobileAppPageViewsPercentage": 0.41, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.41, + "pageViewsPercentageB2B": 0.17, + "buyBoxPercentage": 99.1, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0.72, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0C3DDGHXY", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 15, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 21, + "sessionsB2B": 0, + "browserSessionPercentage": 0.1, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.05, + "sessionPercentageB2B": 0, + "browserPageViews": 15, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 7, + "mobileAppPageViewsB2B": 0, + "pageViews": 22, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.06, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYDPNTZH", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 4, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 3, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8HS6Z3", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0C8Z4B6YM", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 6, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 33.33, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM3JNPFB", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 9, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYDCRZ8R", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF55D81", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX9L6SYS", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 1, + "mobileAppPageViewsB2B": 0, + "pageViews": 1, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF6N6RM", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 1, + "mobileAppPageViewsB2B": 0, + "pageViews": 1, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8449SR", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM26KHRT", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 10, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 7, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 10, + "mobileAppPageViewsB2B": 0, + "pageViews": 17, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXY4Q733", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 7, + "browserSessionsB2B": 0, + "mobileAppSessions": 15, + "mobileAppSessionsB2B": 0, + "sessions": 22, + "sessionsB2B": 0, + "browserSessionPercentage": 0.05, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.06, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.06, + "sessionPercentageB2B": 0, + "browserPageViews": 16, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 34, + "mobileAppPageViewsB2B": 0, + "pageViews": 50, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.06, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.06, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.06, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXKWQPB4", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 5, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 9, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 7, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 5, + "mobileAppPageViewsB2B": 0, + "pageViews": 12, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXLVQDLS", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 10, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXKWVR6C", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 10, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 12, + "sessionsB2B": 0, + "browserSessionPercentage": 0.07, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 13, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 17, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.05, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYDJ1H16", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXL9Z94M", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 4, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 7, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8X83QD", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 8, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 8, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM2664NZ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 5, + "browserSessionsB2B": 0, + "mobileAppSessions": 23, + "mobileAppSessionsB2B": 1, + "sessions": 28, + "sessionsB2B": 1, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.09, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.07, + "sessionPercentageB2B": 0.13, + "browserPageViews": 9, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 46, + "mobileAppPageViewsB2B": 2, + "pageViews": 55, + "pageViewsB2B": 2, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.08, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.07, + "pageViewsPercentageB2B": 0.11, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXB4PN8N", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 7, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 9, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX6YV7F5", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 6, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 8, + "sessionsB2B": 0, + "browserSessionPercentage": 0.04, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 12, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 5, + "mobileAppPageViewsB2B": 0, + "pageViews": 17, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.05, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BNG2FTJW", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 12, + "mobileAppSessionsB2B": 0, + "sessions": 14, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.05, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 27, + "mobileAppPageViewsB2B": 0, + "pageViews": 31, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX6LJY9V", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM3KWYK1", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 7, + "mobileAppSessionsB2B": 0, + "sessions": 10, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.03, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 21, + "mobileAppPageViewsB2B": 0, + "pageViews": 24, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BN8ZC8CD", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 6, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 10, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ511S4C", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 6, + "browserSessionsB2B": 0, + "mobileAppSessions": 9, + "mobileAppSessionsB2B": 0, + "sessions": 15, + "sessionsB2B": 0, + "browserSessionPercentage": 0.04, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 12, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 28, + "mobileAppPageViewsB2B": 0, + "pageViews": 40, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.05, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.05, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BJQLK1BX", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 12, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 14, + "sessionsB2B": 0, + "browserSessionPercentage": 0.08, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 15, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 17, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.06, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 94.12, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXLLQWHH", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 13, + "mobileAppSessionsB2B": 0, + "sessions": 14, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.05, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 30, + "mobileAppPageViewsB2B": 0, + "pageViews": 32, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BY9JV948", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXLJ1RCN", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 8, + "mobileAppSessionsB2B": 0, + "sessions": 8, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.03, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 23, + "mobileAppPageViewsB2B": 0, + "pageViews": 23, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX6VB3BB", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 7, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 7, + "mobileAppPageViewsB2B": 0, + "pageViews": 14, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF3JD67", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8BXKS1", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ4VLP75", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 13, + "browserSessionsB2B": 0, + "mobileAppSessions": 35, + "mobileAppSessionsB2B": 1, + "sessions": 48, + "sessionsB2B": 1, + "browserSessionPercentage": 0.08, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.14, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.12, + "sessionPercentageB2B": 0.13, + "browserPageViews": 25, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 82, + "mobileAppPageViewsB2B": 2, + "pageViews": 107, + "pageViewsB2B": 2, + "browserPageViewsPercentage": 0.1, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.14, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.13, + "pageViewsPercentageB2B": 0.11, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWDZHCV4", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 1, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ838KH6", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 5, + "mobileAppSessionsB2B": 0, + "sessions": 6, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 13, + "mobileAppPageViewsB2B": 0, + "pageViews": 15, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXJ95XC7", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 9, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 9, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BNG36NQ7", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 14, + "mobileAppSessionsB2B": 0, + "sessions": 18, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.06, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.05, + "sessionPercentageB2B": 0, + "browserPageViews": 7, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 30, + "mobileAppPageViewsB2B": 0, + "pageViews": 37, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 95, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BN8VYXLD", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 7, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 9, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYDMCGQG", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 5, + "mobileAppPageViewsB2B": 0, + "pageViews": 5, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 33.33, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF4W99Y", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 3, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BN8PY5JC", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 9, + "browserSessionsB2B": 1, + "mobileAppSessions": 17, + "mobileAppSessionsB2B": 0, + "sessions": 26, + "sessionsB2B": 1, + "browserSessionPercentage": 0.06, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.07, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.07, + "sessionPercentageB2B": 0.13, + "browserPageViews": 22, + "browserPageViewsB2B": 9, + "mobileAppPageViews": 41, + "mobileAppPageViewsB2B": 0, + "pageViews": 63, + "pageViewsB2B": 9, + "browserPageViewsPercentage": 0.08, + "browserPageViewsPercentageB2B": 1.29, + "mobileAppPageViewsPercentage": 0.07, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.07, + "pageViewsPercentageB2B": 0.5, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM3JGCRP", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 5, + "mobileAppSessionsB2B": 0, + "sessions": 7, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 12, + "mobileAppPageViewsB2B": 0, + "pageViews": 15, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM27MD68", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 6, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 8, + "mobileAppPageViewsB2B": 0, + "pageViews": 12, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXJCR4D1", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 8, + "mobileAppSessionsB2B": 0, + "sessions": 10, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.03, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 21, + "mobileAppPageViewsB2B": 0, + "pageViews": 25, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BRKGS7K2", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 14, + "browserSessionsB2B": 1, + "mobileAppSessions": 29, + "mobileAppSessionsB2B": 0, + "sessions": 43, + "sessionsB2B": 1, + "browserSessionPercentage": 0.09, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.12, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.11, + "sessionPercentageB2B": 0.13, + "browserPageViews": 34, + "browserPageViewsB2B": 2, + "mobileAppPageViews": 74, + "mobileAppPageViewsB2B": 0, + "pageViews": 108, + "pageViewsB2B": 2, + "browserPageViewsPercentage": 0.13, + "browserPageViewsPercentageB2B": 0.29, + "mobileAppPageViewsPercentage": 0.13, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.13, + "pageViewsPercentageB2B": 0.11, + "buyBoxPercentage": 98.57, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BNFYSCX8", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 15, + "browserSessionsB2B": 1, + "mobileAppSessions": 36, + "mobileAppSessionsB2B": 1, + "sessions": 51, + "sessionsB2B": 2, + "browserSessionPercentage": 0.1, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.15, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.13, + "sessionPercentageB2B": 0.26, + "browserPageViews": 33, + "browserPageViewsB2B": 2, + "mobileAppPageViews": 103, + "mobileAppPageViewsB2B": 2, + "pageViews": 136, + "pageViewsB2B": 4, + "browserPageViewsPercentage": 0.13, + "browserPageViewsPercentageB2B": 0.29, + "mobileAppPageViewsPercentage": 0.18, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.16, + "pageViewsPercentageB2B": 0.22, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8NSFXT", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 1, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXJDM9M6", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 5, + "mobileAppSessionsB2B": 0, + "sessions": 7, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 5, + "mobileAppPageViewsB2B": 0, + "pageViews": 7, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXP26HY3", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 6, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 12, + "sessionsB2B": 0, + "browserSessionPercentage": 0.04, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 10, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 13, + "mobileAppPageViewsB2B": 0, + "pageViews": 23, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.04, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BJQKBVXF", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 12, + "mobileAppSessionsB2B": 0, + "sessions": 13, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.05, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 27, + "mobileAppPageViewsB2B": 0, + "pageViews": 28, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 93.33, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BNQPYZD7", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 11, + "mobileAppSessionsB2B": 2, + "sessions": 13, + "sessionsB2B": 2, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0.59, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0.26, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 26, + "mobileAppPageViewsB2B": 4, + "pageViews": 30, + "pageViewsB2B": 4, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0.36, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0.22, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BN8RWPZV", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 12, + "browserSessionsB2B": 1, + "mobileAppSessions": 34, + "mobileAppSessionsB2B": 1, + "sessions": 46, + "sessionsB2B": 2, + "browserSessionPercentage": 0.08, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.14, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.12, + "sessionPercentageB2B": 0.26, + "browserPageViews": 21, + "browserPageViewsB2B": 1, + "mobileAppPageViews": 78, + "mobileAppPageViewsB2B": 2, + "pageViews": 99, + "pageViewsB2B": 3, + "browserPageViewsPercentage": 0.08, + "browserPageViewsPercentageB2B": 0.14, + "mobileAppPageViewsPercentage": 0.13, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.12, + "pageViewsPercentageB2B": 0.17, + "buyBoxPercentage": 98.28, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXB44QLH", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX9G2LKR", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 9, + "mobileAppSessionsB2B": 0, + "sessions": 13, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 5, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 22, + "mobileAppPageViewsB2B": 0, + "pageViews": 27, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CT5CJYCN", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ579FDT", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 9, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 6, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 14, + "mobileAppPageViewsB2B": 0, + "pageViews": 20, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BN9DTWQ2", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 4, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 21, + "mobileAppPageViewsB2B": 0, + "pageViews": 21, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BN8WX36F", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 1, + "mobileAppSessions": 9, + "mobileAppSessionsB2B": 1, + "sessions": 11, + "sessionsB2B": 2, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0.26, + "browserPageViews": 7, + "browserPageViewsB2B": 5, + "mobileAppPageViews": 22, + "mobileAppPageViewsB2B": 3, + "pageViews": 29, + "pageViewsB2B": 8, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0.71, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0.27, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0.44, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BKLJCXDL", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 7, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 10, + "sessionsB2B": 0, + "browserSessionPercentage": 0.05, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 19, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 8, + "mobileAppPageViewsB2B": 0, + "pageViews": 27, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.07, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8BRRQK", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 6, + "browserSessionsB2B": 0, + "mobileAppSessions": 11, + "mobileAppSessionsB2B": 0, + "sessions": 17, + "sessionsB2B": 0, + "browserSessionPercentage": 0.04, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 11, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 32, + "mobileAppPageViewsB2B": 0, + "pageViews": 43, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.04, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.06, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.05, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 96.15, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXLK9VZQ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 1, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BK9BPYH6", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 6, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 12, + "sessionsB2B": 0, + "browserSessionPercentage": 0.04, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 21, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 15, + "mobileAppPageViewsB2B": 0, + "pageViews": 36, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.08, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.03, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX61WVKQ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 7, + "mobileAppSessionsB2B": 0, + "sessions": 10, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.03, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 6, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 15, + "mobileAppPageViewsB2B": 0, + "pageViews": 21, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.03, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BPJQ567M", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 10, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 9, + "mobileAppPageViewsB2B": 0, + "pageViews": 13, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ53BPQ8", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 10, + "mobileAppPageViewsB2B": 0, + "pageViews": 13, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF3YWW7", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 6, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX4FSKXQ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 3, + "mobileAppPageViewsB2B": 0, + "pageViews": 7, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 50, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF2QGZX", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 1, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXLDNVSG", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 5, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 7, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ4WGQWZ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 1, + "sessions": 7, + "sessionsB2B": 1, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0.13, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 12, + "mobileAppPageViewsB2B": 4, + "pageViews": 16, + "pageViewsB2B": 4, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0.36, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0.22, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BPJYBZG6", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXB51Q6N", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 5, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 14, + "mobileAppPageViewsB2B": 0, + "pageViews": 14, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 85.71, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXPS88XZ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 11, + "mobileAppSessionsB2B": 0, + "sessions": 15, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 9, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 21, + "mobileAppPageViewsB2B": 0, + "pageViews": 30, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXY5BC6K", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 7, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 14, + "mobileAppPageViewsB2B": 0, + "pageViews": 18, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BK98D4YR", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 6, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 8, + "mobileAppPageViewsB2B": 0, + "pageViews": 11, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF4LDVM", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 1, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 1, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0.13, + "browserPageViews": 1, + "browserPageViewsB2B": 1, + "mobileAppPageViews": 2, + "mobileAppPageViewsB2B": 0, + "pageViews": 3, + "pageViewsB2B": 1, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0.14, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0.06, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXPLWSMD", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 4, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 6, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 3, + "mobileAppPageViewsB2B": 0, + "pageViews": 9, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYK4K8R8", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 5, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ4XS3JH", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 1, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 9, + "sessionsB2B": 1, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0.13, + "browserPageViews": 3, + "browserPageViewsB2B": 1, + "mobileAppPageViews": 14, + "mobileAppPageViewsB2B": 0, + "pageViews": 17, + "pageViewsB2B": 1, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0.14, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0.06, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8L314V", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 5, + "mobileAppSessionsB2B": 0, + "sessions": 5, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 11, + "mobileAppPageViewsB2B": 0, + "pageViews": 11, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXSWCL7X", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 9, + "browserSessionsB2B": 0, + "mobileAppSessions": 8, + "mobileAppSessionsB2B": 0, + "sessions": 17, + "sessionsB2B": 0, + "browserSessionPercentage": 0.06, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.03, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 12, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 18, + "mobileAppPageViewsB2B": 0, + "pageViews": 30, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.05, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.03, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BNQS12XM", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 1, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 3, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 3, + "mobileAppPageViewsB2B": 0, + "pageViews": 6, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8589HQ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 4, + "mobileAppPageViewsB2B": 0, + "pageViews": 4, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYDKZFS2", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 7, + "mobileAppPageViewsB2B": 0, + "pageViews": 7, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8VG2JR", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 5, + "browserSessionsB2B": 0, + "mobileAppSessions": 10, + "mobileAppSessionsB2B": 0, + "sessions": 15, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0, + "browserPageViews": 10, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 22, + "mobileAppPageViewsB2B": 0, + "pageViews": 32, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.04, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX64DX15", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 1, + "mobileAppSessions": 17, + "mobileAppSessionsB2B": 0, + "sessions": 21, + "sessionsB2B": 1, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.07, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.05, + "sessionPercentageB2B": 0.13, + "browserPageViews": 8, + "browserPageViewsB2B": 2, + "mobileAppPageViews": 41, + "mobileAppPageViewsB2B": 0, + "pageViews": 49, + "pageViewsB2B": 2, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0.29, + "mobileAppPageViewsPercentage": 0.07, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.06, + "pageViewsPercentageB2B": 0.11, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ8W2GTZ", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 6, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 10, + "mobileAppPageViewsB2B": 0, + "pageViews": 14, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ81GPXT", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 8, + "browserSessionsB2B": 0, + "mobileAppSessions": 4, + "mobileAppSessionsB2B": 0, + "sessions": 12, + "sessionsB2B": 0, + "browserSessionPercentage": 0.05, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 12, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 12, + "mobileAppPageViewsB2B": 0, + "pageViews": 24, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.05, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.02, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX6R3KNR", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 4, + "browserSessionsB2B": 0, + "mobileAppSessions": 18, + "mobileAppSessionsB2B": 1, + "sessions": 22, + "sessionsB2B": 1, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.07, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.06, + "sessionPercentageB2B": 0.13, + "browserPageViews": 6, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 44, + "mobileAppPageViewsB2B": 2, + "pageViews": 50, + "pageViewsB2B": 2, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.08, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.06, + "pageViewsPercentageB2B": 0.11, + "buyBoxPercentage": 93.1, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM26W8F3", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 31, + "mobileAppSessionsB2B": 0, + "sessions": 34, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.13, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.09, + "sessionPercentageB2B": 0, + "browserPageViews": 8, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 70, + "mobileAppPageViewsB2B": 0, + "pageViews": 78, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.12, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.09, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF23L25", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 1, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 1, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CWF3BKH1", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 0, + "mobileAppSessionsB2B": 0, + "sessions": 1, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 0, + "mobileAppPageViewsB2B": 0, + "pageViews": 2, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX66BD7S", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 11, + "browserSessionsB2B": 1, + "mobileAppSessions": 12, + "mobileAppSessionsB2B": 0, + "sessions": 23, + "sessionsB2B": 1, + "browserSessionPercentage": 0.07, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.05, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.06, + "sessionPercentageB2B": 0.13, + "browserPageViews": 26, + "browserPageViewsB2B": 2, + "mobileAppPageViews": 28, + "mobileAppPageViewsB2B": 0, + "pageViews": 54, + "pageViewsB2B": 2, + "browserPageViewsPercentage": 0.1, + "browserPageViewsPercentageB2B": 0.29, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.06, + "pageViewsPercentageB2B": 0.11, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXJCTN5Q", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 14, + "mobileAppSessionsB2B": 1, + "sessions": 17, + "sessionsB2B": 1, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.06, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.04, + "sessionPercentageB2B": 0.13, + "browserPageViews": 8, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 41, + "mobileAppPageViewsB2B": 3, + "pageViews": 49, + "pageViewsB2B": 3, + "browserPageViewsPercentage": 0.03, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.07, + "mobileAppPageViewsPercentageB2B": 0.27, + "pageViewsPercentage": 0.06, + "pageViewsPercentageB2B": 0.17, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0CM26HCRN", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 2, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 4, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 10, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BX99CYSM", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 25, + "browserSessionsB2B": 1, + "mobileAppSessions": 63, + "mobileAppSessionsB2B": 1, + "sessions": 88, + "sessionsB2B": 2, + "browserSessionPercentage": 0.16, + "browserSessionPercentageB2B": 0.23, + "mobileAppSessionPercentage": 0.26, + "mobileAppSessionPercentageB2B": 0.29, + "sessionPercentage": 0.22, + "sessionPercentageB2B": 0.26, + "browserPageViews": 54, + "browserPageViewsB2B": 2, + "mobileAppPageViews": 150, + "mobileAppPageViewsB2B": 2, + "pageViews": 204, + "pageViewsB2B": 4, + "browserPageViewsPercentage": 0.21, + "browserPageViewsPercentageB2B": 0.29, + "mobileAppPageViewsPercentage": 0.26, + "mobileAppPageViewsPercentageB2B": 0.18, + "pageViewsPercentage": 0.24, + "pageViewsPercentageB2B": 0.22, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 100, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BYDS6D3X", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 3, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 8, + "mobileAppPageViewsB2B": 0, + "pageViews": 8, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXB5Q8WW", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 3, + "browserSessionsB2B": 0, + "mobileAppSessions": 8, + "mobileAppSessionsB2B": 0, + "sessions": 11, + "sessionsB2B": 0, + "browserSessionPercentage": 0.02, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.03, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.03, + "sessionPercentageB2B": 0, + "browserPageViews": 4, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 18, + "mobileAppPageViewsB2B": 0, + "pageViews": 22, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.03, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.03, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0C3DF873W", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 5, + "browserSessionsB2B": 0, + "mobileAppSessions": 3, + "mobileAppSessionsB2B": 0, + "sessions": 8, + "sessionsB2B": 0, + "browserSessionPercentage": 0.03, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 6, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 6, + "mobileAppPageViewsB2B": 0, + "pageViews": 12, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.02, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0C3D76JQH", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 12, + "browserSessionsB2B": 0, + "mobileAppSessions": 15, + "mobileAppSessionsB2B": 0, + "sessions": 27, + "sessionsB2B": 0, + "browserSessionPercentage": 0.08, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.06, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.07, + "sessionPercentageB2B": 0, + "browserPageViews": 13, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 30, + "mobileAppPageViewsB2B": 0, + "pageViews": 43, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.05, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.05, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.05, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXP5VVJ1", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 0, + "browserSessionsB2B": 0, + "mobileAppSessions": 2, + "mobileAppSessionsB2B": 0, + "sessions": 2, + "sessionsB2B": 0, + "browserSessionPercentage": 0, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.01, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.01, + "sessionPercentageB2B": 0, + "browserPageViews": 0, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 5, + "mobileAppPageViewsB2B": 0, + "pageViews": 5, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.01, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.01, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BXL8CHYL", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 1, + "browserSessionsB2B": 0, + "mobileAppSessions": 6, + "mobileAppSessionsB2B": 0, + "sessions": 7, + "sessionsB2B": 0, + "browserSessionPercentage": 0.01, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.02, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.02, + "sessionPercentageB2B": 0, + "browserPageViews": 2, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 18, + "mobileAppPageViewsB2B": 0, + "pageViews": 20, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.01, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.03, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.02, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 92.31, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + }, + { + "parentAsin": "B0BZ4WH3M5", + "salesByAsin": { + "unitsOrdered": 0, + "unitsOrderedB2B": 0, + "orderedProductSales": { + "amount": 0, + "currencyCode": "USD" + }, + "orderedProductSalesB2B": { + "amount": 0, + "currencyCode": "USD" + }, + "totalOrderItems": 0, + "totalOrderItemsB2B": 0 + }, + "trafficByAsin": { + "browserSessions": 8, + "browserSessionsB2B": 0, + "mobileAppSessions": 11, + "mobileAppSessionsB2B": 0, + "sessions": 19, + "sessionsB2B": 0, + "browserSessionPercentage": 0.05, + "browserSessionPercentageB2B": 0, + "mobileAppSessionPercentage": 0.04, + "mobileAppSessionPercentageB2B": 0, + "sessionPercentage": 0.05, + "sessionPercentageB2B": 0, + "browserPageViews": 11, + "browserPageViewsB2B": 0, + "mobileAppPageViews": 23, + "mobileAppPageViewsB2B": 0, + "pageViews": 34, + "pageViewsB2B": 0, + "browserPageViewsPercentage": 0.04, + "browserPageViewsPercentageB2B": 0, + "mobileAppPageViewsPercentage": 0.04, + "mobileAppPageViewsPercentageB2B": 0, + "pageViewsPercentage": 0.04, + "pageViewsPercentageB2B": 0, + "buyBoxPercentage": 100, + "buyBoxPercentageB2B": 0, + "unitSessionPercentage": 0, + "unitSessionPercentageB2B": 0 + } + } + ] +} \ No newline at end of file From 097833805fc2471785f62113e115d0d1c2be3597 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 10:55:43 +0200 Subject: [PATCH 15/23] added initializer --- .../controller/HealthController.java | 6 +-- .../{updater => file}/FileReaderService.java | 5 +- .../initializer/ReportInitializerService.java | 7 +++ .../initializer/ReportUpdaterServiceImpl.java | 54 +++++++++++++++++++ .../service/updater/ReportUpdaterService.java | 5 -- .../updater/ReportUpdaterServiceImpl.java | 32 ----------- .../main/resources/db/json/test_report.json | 0 7 files changed, 67 insertions(+), 42 deletions(-) rename src/main/java/com/app/sellerretailreports/service/{updater => file}/FileReaderService.java (80%) create mode 100644 src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java create mode 100644 src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java delete mode 100644 src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java delete mode 100644 src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java rename test_report.json => src/main/resources/db/json/test_report.json (100%) diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java index e97ca7d..41df52d 100644 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ b/src/main/java/com/app/sellerretailreports/controller/HealthController.java @@ -1,6 +1,6 @@ package com.app.sellerretailreports.controller; -import com.app.sellerretailreports.service.updater.ReportUpdaterService; +import com.app.sellerretailreports.service.initializer.ReportInitializerService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -11,7 +11,7 @@ @RequiredArgsConstructor @Tag(name = "Health Check", description = "Endpoint to check API") public class HealthController { - private final ReportUpdaterService reportUpdaterService; + private final ReportInitializerService reportUpdaterService; @GetMapping("/health") @Operation(summary = "Check Health") @@ -21,6 +21,6 @@ public String getHealth() { @GetMapping("/update") public void updateDb() { - reportUpdaterService.updateDb(); + reportUpdaterService.update(); } } diff --git a/src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java b/src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java similarity index 80% rename from src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java rename to src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java index 13ee979..3ac4e3d 100644 --- a/src/main/java/com/app/sellerretailreports/service/updater/FileReaderService.java +++ b/src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java @@ -1,4 +1,4 @@ -package com.app.sellerretailreports.service.updater; +package com.app.sellerretailreports.service.file; import java.io.BufferedReader; import java.io.IOException; @@ -13,7 +13,8 @@ public static String readFile(String fileName) { BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(fileName)); try { - String str = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator())); + String str = bufferedReader.lines() + .collect(Collectors.joining(System.lineSeparator())); bufferedReader.close(); return str; } catch (Throwable throwable) { diff --git a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java new file mode 100644 index 0000000..0c95bcc --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java @@ -0,0 +1,7 @@ +package com.app.sellerretailreports.service.initializer; + +public interface ReportInitializerService { + void initialize(); + + void update(); +} diff --git a/src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java new file mode 100644 index 0000000..652f86a --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java @@ -0,0 +1,54 @@ +package com.app.sellerretailreports.service.initializer; + +import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; +import com.app.sellerretailreports.repository.report.ReportRepository; +import com.app.sellerretailreports.service.file.FileReaderService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import jakarta.annotation.PostConstruct; +import java.io.File; +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReportUpdaterServiceImpl implements ReportInitializerService { + private static final String INITIALIZE_JSON_PATH = + "src\\main\\resources\\db\\json\\test_report.json"; + private static final String UPDATE_JSON_PATH = + "src\\main\\resources\\db\\json\\db_report.json"; + private final ReportRepository repository; + + @Override + @PostConstruct + public void initialize() { + SalesAndTrafficReport report = getReport(INITIALIZE_JSON_PATH); + SalesAndTrafficReport saved = repository.save(report); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + try { + objectMapper.writeValue(new File(UPDATE_JSON_PATH), saved); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void update() { + SalesAndTrafficReport report = getReport("src\\main\\resources\\db\\json\\db_report.json"); + repository.save(report); + } + + private SalesAndTrafficReport getReport(String fileName) { + String jsonString = FileReaderService.readFile(fileName); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + try { + return objectMapper.readValue(jsonString, SalesAndTrafficReport.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java b/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java deleted file mode 100644 index a9a31cc..0000000 --- a/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.app.sellerretailreports.service.updater; - -public interface ReportUpdaterService { - void updateDb(); -} diff --git a/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java deleted file mode 100644 index 7a0013d..0000000 --- a/src/main/java/com/app/sellerretailreports/service/updater/ReportUpdaterServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.app.sellerretailreports.service.updater; - -import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; -import com.app.sellerretailreports.repository.report.ReportRepository; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class ReportUpdaterServiceImpl implements ReportUpdaterService { - private final ReportRepository repository; - - @Override - public void updateDb() { - SalesAndTrafficReport report = getReport(); - repository.save(report); - } - - private SalesAndTrafficReport getReport() { - String jsonString = FileReaderService.readFile("test_report.json"); - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - try { - return objectMapper.readValue(jsonString, SalesAndTrafficReport.class); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } -} diff --git a/test_report.json b/src/main/resources/db/json/test_report.json similarity index 100% rename from test_report.json rename to src/main/resources/db/json/test_report.json From 5a3f73642fd9b8ce5b3762f3333ce4834465366e Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 11:03:35 +0200 Subject: [PATCH 16/23] stable version --- .../app/sellerretailreports/dto/report/ReportRequestDto.java | 4 ---- .../java/com/app/sellerretailreports/mapper/ReportMapper.java | 3 --- ...aterServiceImpl.java => ReportInitializerServiceImpl.java} | 4 +++- 3 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java rename src/main/java/com/app/sellerretailreports/service/initializer/{ReportUpdaterServiceImpl.java => ReportInitializerServiceImpl.java} (88%) diff --git a/src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java b/src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java deleted file mode 100644 index f17f43e..0000000 --- a/src/main/java/com/app/sellerretailreports/dto/report/ReportRequestDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.app.sellerretailreports.dto.report; - -public class ReportRequestDto { -} diff --git a/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java b/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java index d1a08ca..20e11a6 100644 --- a/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java +++ b/src/main/java/com/app/sellerretailreports/mapper/ReportMapper.java @@ -1,7 +1,6 @@ package com.app.sellerretailreports.mapper; import com.app.sellerretailreports.config.MapperConfig; -import com.app.sellerretailreports.dto.report.ReportRequestDto; import com.app.sellerretailreports.dto.report.ReportResponseDto; import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; import org.mapstruct.Mapper; @@ -16,6 +15,4 @@ ) public interface ReportMapper { ReportResponseDto toDto(SalesAndTrafficReport salesAndTrafficReport); - - SalesAndTrafficReport toEntity(ReportRequestDto requestDto); } diff --git a/src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java similarity index 88% rename from src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java rename to src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java index 652f86a..b75fbea 100644 --- a/src/main/java/com/app/sellerretailreports/service/initializer/ReportUpdaterServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java @@ -10,11 +10,12 @@ import java.io.File; import java.io.IOException; import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor -public class ReportUpdaterServiceImpl implements ReportInitializerService { +public class ReportInitializerServiceImpl implements ReportInitializerService { private static final String INITIALIZE_JSON_PATH = "src\\main\\resources\\db\\json\\test_report.json"; private static final String UPDATE_JSON_PATH = @@ -36,6 +37,7 @@ public void initialize() { } @Override + @Scheduled(fixedRate = 900_000) /* updates data in db every 15 minutes */ public void update() { SalesAndTrafficReport report = getReport("src\\main\\resources\\db\\json\\db_report.json"); repository.save(report); From c590a6f79a644bd6f6b0dd05427f7c8b527ae2af Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 11:10:10 +0200 Subject: [PATCH 17/23] stable version with path check --- .../service/initializer/ReportInitializerServiceImpl.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java index b75fbea..6a32786 100644 --- a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java @@ -9,6 +9,9 @@ import jakarta.annotation.PostConstruct; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -25,6 +28,11 @@ public class ReportInitializerServiceImpl implements ReportInitializerService { @Override @PostConstruct public void initialize() { + Path path = Paths.get(UPDATE_JSON_PATH); + if (Files.exists(path)) { + update(); + return; + } SalesAndTrafficReport report = getReport(INITIALIZE_JSON_PATH); SalesAndTrafficReport saved = repository.save(report); ObjectMapper objectMapper = new ObjectMapper(); From 1cee1dcffc1648391e501c8886141f2c70096b45 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 11:31:59 +0200 Subject: [PATCH 18/23] added one endpoint --- .../controller/SalesAndTrafficController.java | 9 +++++++++ .../sales/SalesAndTrafficByDateService.java | 2 ++ .../SalesAndTrafficByDateServiceImpl.java | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java index 5965ba3..071da12 100644 --- a/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java +++ b/src/main/java/com/app/sellerretailreports/controller/SalesAndTrafficController.java @@ -31,6 +31,15 @@ public List getAllBetweenDates( return salesAndTrafficByDateService.findAllBetweenDates(start, end); } + @GetMapping(value = "/by-date") + @Operation(summary = "Get statistics by specified date.") + public SalesAndTrafficByDateDto getBySpecifiedDate( + @RequestParam("date") + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date + ) { + return salesAndTrafficByDateService.findBySpecifiedDate(date); + } + @GetMapping(value = "/all-by-specified-asins") @Operation(summary = "Get statistics by all specified asins.") public List getAllBySpecifiedAsins( diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java index b271171..5fe00a4 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateService.java @@ -8,6 +8,8 @@ public interface SalesAndTrafficByDateService { List findAllBetweenDates(LocalDate start, LocalDate end); + SalesAndTrafficByDateDto findBySpecifiedDate(LocalDate localDate); + List findAllByAsins(); List findAllByDates(); diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java index 1810d0b..2eb3b0b 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java @@ -2,6 +2,7 @@ import com.app.sellerretailreports.dto.report.SalesAndTrafficByAsinDto; import com.app.sellerretailreports.dto.report.SalesAndTrafficByDateDto; +import com.app.sellerretailreports.entity.report.SalesAndTrafficByDate; import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; import com.app.sellerretailreports.mapper.SalesAndTrafficByAsinMapper; import com.app.sellerretailreports.mapper.SalesAndTrafficByDateMapper; @@ -9,6 +10,7 @@ import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service @@ -19,6 +21,7 @@ public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateSe private final SalesAndTrafficByAsinMapper salesAndTrafficByAsinMapper; @Override + @Cacheable("salesAndTrafficByDateDto") public List findAllBetweenDates(LocalDate start, LocalDate end) { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByDate().stream() @@ -29,6 +32,20 @@ public List findAllBetweenDates(LocalDate start, Local } @Override + public SalesAndTrafficByDateDto findBySpecifiedDate(LocalDate localDate) { + SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + SalesAndTrafficByDate salesAndTrafficByDate = salesAndTrafficReport + .getSalesAndTrafficByDate().stream() + .filter(s -> s.getDate().isEqual(localDate)) + .findFirst() + .orElseThrow( + () -> new RuntimeException("Can't find sales in traffic by " + localDate) + ); + return salesAndTrafficByDateMapper.toDto(salesAndTrafficByDate); + } + + @Override + @Cacheable("salesAndTrafficByAsinDto") public List findAllBySpecifiedAsins(List asins) { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() @@ -38,6 +55,7 @@ public List findAllBySpecifiedAsins(List asins } @Override + @Cacheable("salesAndTrafficByAsinDto") public List findAllByAsins() { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() From caa7b1a2bfa681796d7521ef33e7461cf405af70 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 11:54:15 +0200 Subject: [PATCH 19/23] added caching --- .../cache/SpringCacheCustomizer.java | 21 ++++++++++++++++ .../cache/SpringCachingConfig.java | 16 +++++++++++++ .../SalesAndTrafficByDateServiceImpl.java | 24 ++++++++++++++++--- src/main/resources/application.properties | 1 + 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java create mode 100644 src/main/java/com/app/sellerretailreports/cache/SpringCachingConfig.java diff --git a/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java b/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java new file mode 100644 index 0000000..f75462d --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java @@ -0,0 +1,21 @@ +package com.app.sellerretailreports.cache; + +import java.util.List; +import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.stereotype.Component; + +@Component +public class SpringCacheCustomizer implements CacheManagerCustomizer { + @Override + public void customize(ConcurrentMapCacheManager cacheManager) { + cacheManager.setCacheNames(List.of( + "salesAndTrafficByDatesBetween", + "salesAndTrafficBySpecifiedDate", + "salesAndTrafficBySpecifiedAsins", + "salesAndTrafficByAsins", + "salesAndTrafficByDates" + ) + ); + } +} diff --git a/src/main/java/com/app/sellerretailreports/cache/SpringCachingConfig.java b/src/main/java/com/app/sellerretailreports/cache/SpringCachingConfig.java new file mode 100644 index 0000000..0b3e952 --- /dev/null +++ b/src/main/java/com/app/sellerretailreports/cache/SpringCachingConfig.java @@ -0,0 +1,16 @@ +package com.app.sellerretailreports.cache; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +public class SpringCachingConfig { + @Bean + public CacheManager cacheManager() { + return new ConcurrentMapCacheManager(); + } +} diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java index 2eb3b0b..f8eceef 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java @@ -10,7 +10,9 @@ import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service @@ -21,7 +23,7 @@ public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateSe private final SalesAndTrafficByAsinMapper salesAndTrafficByAsinMapper; @Override - @Cacheable("salesAndTrafficByDateDto") + @Cacheable("salesAndTrafficByDatesBetween") public List findAllBetweenDates(LocalDate start, LocalDate end) { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByDate().stream() @@ -32,6 +34,7 @@ public List findAllBetweenDates(LocalDate start, Local } @Override + @Cacheable("salesAndTrafficBySpecifiedDate") public SalesAndTrafficByDateDto findBySpecifiedDate(LocalDate localDate) { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); SalesAndTrafficByDate salesAndTrafficByDate = salesAndTrafficReport @@ -45,7 +48,7 @@ public SalesAndTrafficByDateDto findBySpecifiedDate(LocalDate localDate) { } @Override - @Cacheable("salesAndTrafficByAsinDto") + @Cacheable("salesAndTrafficBySpecifiedAsins") public List findAllBySpecifiedAsins(List asins) { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() @@ -55,7 +58,7 @@ public List findAllBySpecifiedAsins(List asins } @Override - @Cacheable("salesAndTrafficByAsinDto") + @Cacheable("salesAndTrafficByAsins") public List findAllByAsins() { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() @@ -64,10 +67,25 @@ public List findAllByAsins() { } @Override + @Cacheable("salesAndTrafficByDates") public List findAllByDates() { SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); return salesAndTrafficReport.getSalesAndTrafficByDate().stream() .map(salesAndTrafficByDateMapper::toDto) .toList(); } + + @CacheEvict( + value = { + "salesAndTrafficByDatesBetween", + "salesAndTrafficBySpecifiedDate", + "salesAndTrafficBySpecifiedAsins", + "salesAndTrafficByAsins", + "salesAndTrafficByDates" + }, + allEntries = true + ) + @Scheduled(fixedRateString = "${caching.spring.TTL}") + public void emptyHotelsCache() { + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index fc58ea5..380f4e6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,6 +4,7 @@ spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.password=${MANGODB_PASSWORD} spring.data.mongodb.database=report_db +caching.spring.TTL=420000 jwt.expiration=${JWT_EXPIRATION} jwt.secret=${JWT_SECRET} From 7182267caaa70acd004cf3ecdb557e7996196161 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 12:03:23 +0200 Subject: [PATCH 20/23] refactored --- .../entity/report/SalesAndTrafficReport.java | 2 +- .../sales/SalesAndTrafficByDateServiceImpl.java | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java index 64c156f..5adf559 100644 --- a/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java +++ b/src/main/java/com/app/sellerretailreports/entity/report/SalesAndTrafficReport.java @@ -6,7 +6,7 @@ import org.springframework.data.mongodb.core.mapping.Document; @Data -@Document(collection = "objects") +@Document(collection = "sales_and_traffic_reports") public class SalesAndTrafficReport { @Id private String id; diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java index f8eceef..c782ec9 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java @@ -18,6 +18,7 @@ @Service @RequiredArgsConstructor public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateService { + private static final int FIRST_ELEMENT_INDEX = 0; private final ReportRepository repository; private final SalesAndTrafficByDateMapper salesAndTrafficByDateMapper; private final SalesAndTrafficByAsinMapper salesAndTrafficByAsinMapper; @@ -25,7 +26,7 @@ public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateSe @Override @Cacheable("salesAndTrafficByDatesBetween") public List findAllBetweenDates(LocalDate start, LocalDate end) { - SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + SalesAndTrafficReport salesAndTrafficReport = findReport(); return salesAndTrafficReport.getSalesAndTrafficByDate().stream() .filter(s -> (s.getDate().isAfter(start) && s.getDate().isBefore(end)) || (s.getDate().equals(start) || s.getDate().equals(end))) @@ -36,7 +37,7 @@ public List findAllBetweenDates(LocalDate start, Local @Override @Cacheable("salesAndTrafficBySpecifiedDate") public SalesAndTrafficByDateDto findBySpecifiedDate(LocalDate localDate) { - SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + SalesAndTrafficReport salesAndTrafficReport = findReport(); SalesAndTrafficByDate salesAndTrafficByDate = salesAndTrafficReport .getSalesAndTrafficByDate().stream() .filter(s -> s.getDate().isEqual(localDate)) @@ -50,7 +51,7 @@ public SalesAndTrafficByDateDto findBySpecifiedDate(LocalDate localDate) { @Override @Cacheable("salesAndTrafficBySpecifiedAsins") public List findAllBySpecifiedAsins(List asins) { - SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + SalesAndTrafficReport salesAndTrafficReport = findReport(); return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() .filter(s -> asins.contains(s.getParentAsin())) .map(salesAndTrafficByAsinMapper::toDto) @@ -60,7 +61,7 @@ public List findAllBySpecifiedAsins(List asins @Override @Cacheable("salesAndTrafficByAsins") public List findAllByAsins() { - SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + SalesAndTrafficReport salesAndTrafficReport = findReport(); return salesAndTrafficReport.getSalesAndTrafficByAsin().stream() .map(salesAndTrafficByAsinMapper::toDto) .toList(); @@ -69,7 +70,7 @@ public List findAllByAsins() { @Override @Cacheable("salesAndTrafficByDates") public List findAllByDates() { - SalesAndTrafficReport salesAndTrafficReport = repository.findAll().get(0); + SalesAndTrafficReport salesAndTrafficReport = findReport(); return salesAndTrafficReport.getSalesAndTrafficByDate().stream() .map(salesAndTrafficByDateMapper::toDto) .toList(); @@ -88,4 +89,8 @@ public List findAllByDates() { @Scheduled(fixedRateString = "${caching.spring.TTL}") public void emptyHotelsCache() { } + + private SalesAndTrafficReport findReport() { + return repository.findAll().get(FIRST_ELEMENT_INDEX); + } } From 02fd4844aec0871ec1848a1aadada4b698b7f02c Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 12:54:33 +0200 Subject: [PATCH 21/23] deleted health controller --- .../controller/HealthController.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/main/java/com/app/sellerretailreports/controller/HealthController.java diff --git a/src/main/java/com/app/sellerretailreports/controller/HealthController.java b/src/main/java/com/app/sellerretailreports/controller/HealthController.java deleted file mode 100644 index 41df52d..0000000 --- a/src/main/java/com/app/sellerretailreports/controller/HealthController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.app.sellerretailreports.controller; - -import com.app.sellerretailreports.service.initializer.ReportInitializerService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@Tag(name = "Health Check", description = "Endpoint to check API") -public class HealthController { - private final ReportInitializerService reportUpdaterService; - - @GetMapping("/health") - @Operation(summary = "Check Health") - public String getHealth() { - return "API is running..."; - } - - @GetMapping("/update") - public void updateDb() { - reportUpdaterService.update(); - } -} From 196d30c519cb67cfd729ca16ad0da8f7081ae079 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 15:48:31 +0200 Subject: [PATCH 22/23] fixed minor issues --- .../SellerRetailReportsApplication.java | 2 - .../cache/SpringCacheCustomizer.java | 21 ++++-- .../controller/ReportController.java | 6 +- .../service/file/FileReaderService.java | 23 ++----- .../initializer/ReportInitializerService.java | 61 +++++++++++++++++- .../ReportInitializerServiceImpl.java | 64 ------------------- .../SalesAndTrafficByDateServiceImpl.java | 22 +++++-- src/main/resources/application.properties | 2 + 8 files changed, 99 insertions(+), 102 deletions(-) delete mode 100644 src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java diff --git a/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java b/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java index 1bf186a..5afa83b 100644 --- a/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java +++ b/src/main/java/com/app/sellerretailreports/SellerRetailReportsApplication.java @@ -2,12 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling -@EnableCaching public class SellerRetailReportsApplication { public static void main(String[] args) { SpringApplication.run(SellerRetailReportsApplication.class, args); diff --git a/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java b/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java index f75462d..b23c7ae 100644 --- a/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java +++ b/src/main/java/com/app/sellerretailreports/cache/SpringCacheCustomizer.java @@ -7,14 +7,25 @@ @Component public class SpringCacheCustomizer implements CacheManagerCustomizer { + private static final String SALES_AND_TRAFFIC_BY_DATES_BETWEEN = + "salesAndTrafficByDatesBetween"; + private static final String SALES_AND_TRAFFIC_BY_SPECIFIED_DATE = + "salesAndTrafficBySpecifiedDate"; + private static final String SALES_AND_TRAFFIC_BY_SPECIFIED_ASINS = + "salesAndTrafficBySpecifiedAsins"; + private static final String SALES_AND_TRAFFIC_BY_ASINS = + "salesAndTrafficByAsins"; + private static final String SALES_AND_TRAFFIC_BY_DATES = + "salesAndTrafficByDates"; + @Override public void customize(ConcurrentMapCacheManager cacheManager) { cacheManager.setCacheNames(List.of( - "salesAndTrafficByDatesBetween", - "salesAndTrafficBySpecifiedDate", - "salesAndTrafficBySpecifiedAsins", - "salesAndTrafficByAsins", - "salesAndTrafficByDates" + SALES_AND_TRAFFIC_BY_DATES_BETWEEN, + SALES_AND_TRAFFIC_BY_SPECIFIED_DATE, + SALES_AND_TRAFFIC_BY_SPECIFIED_ASINS, + SALES_AND_TRAFFIC_BY_ASINS, + SALES_AND_TRAFFIC_BY_DATES ) ); } diff --git a/src/main/java/com/app/sellerretailreports/controller/ReportController.java b/src/main/java/com/app/sellerretailreports/controller/ReportController.java index deaabf6..1ab90a1 100644 --- a/src/main/java/com/app/sellerretailreports/controller/ReportController.java +++ b/src/main/java/com/app/sellerretailreports/controller/ReportController.java @@ -7,18 +7,16 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor -@RequestMapping(value = "/report") @Tag(name = "Report management", - description = "Endpoints for managing reports.") + description = "Endpoints for getting reports.") public class ReportController { private final ReportService reportService; - @GetMapping(value = "/all") + @GetMapping(value = "/reports") @Operation(summary = "Get reports by all dates") public List getAll() { return reportService.findAll(); diff --git a/src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java b/src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java index 3ac4e3d..55c1163 100644 --- a/src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java +++ b/src/main/java/com/app/sellerretailreports/service/file/FileReaderService.java @@ -8,26 +8,13 @@ public class FileReaderService { public static String readFile(String fileName) { - - try { - BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(fileName)); - - try { - String str = bufferedReader.lines() - .collect(Collectors.joining(System.lineSeparator())); - bufferedReader.close(); - return str; - } catch (Throwable throwable) { - try { - bufferedReader.close(); - } catch (Throwable throwable1) { - throwable.addSuppressed(throwable1); - } - throw throwable; - } + try (BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(fileName))) { + String str = bufferedReader.lines() + .collect(Collectors.joining(System.lineSeparator())); + bufferedReader.close(); + return str; } catch (IOException e) { throw new RuntimeException("Cannot read data from the file " + fileName, e); } - } } diff --git a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java index 0c95bcc..664baad 100644 --- a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java +++ b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerService.java @@ -1,7 +1,62 @@ package com.app.sellerretailreports.service.initializer; -public interface ReportInitializerService { - void initialize(); +import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; +import com.app.sellerretailreports.repository.report.ReportRepository; +import com.app.sellerretailreports.service.file.FileReaderService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import jakarta.annotation.PostConstruct; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; - void update(); +@Service +@RequiredArgsConstructor +class ReportInitializerService { + private static final String INITIALIZE_JSON_PATH = + "src\\main\\resources\\db\\json\\test_report.json"; + private static final String UPDATE_JSON_PATH = + "src\\main\\resources\\db\\json\\db_report.json"; + private final ReportRepository repository; + + @PostConstruct + public void initialize() { + Path path = Paths.get(UPDATE_JSON_PATH); + if (Files.exists(path)) { + update(); + return; + } + SalesAndTrafficReport report = getReport(INITIALIZE_JSON_PATH); + SalesAndTrafficReport saved = repository.save(report); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + try { + objectMapper.writeValue(new File(UPDATE_JSON_PATH), saved); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Scheduled(fixedRate = 900_000) /* updates data in db every 15 minutes */ + public void update() { + SalesAndTrafficReport report = getReport("src\\main\\resources\\db\\json\\db_report.json"); + repository.save(report); + } + + private SalesAndTrafficReport getReport(String fileName) { + String jsonString = FileReaderService.readFile(fileName); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + try { + return objectMapper.readValue(jsonString, SalesAndTrafficReport.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } } diff --git a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java deleted file mode 100644 index 6a32786..0000000 --- a/src/main/java/com/app/sellerretailreports/service/initializer/ReportInitializerServiceImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.app.sellerretailreports.service.initializer; - -import com.app.sellerretailreports.entity.report.SalesAndTrafficReport; -import com.app.sellerretailreports.repository.report.ReportRepository; -import com.app.sellerretailreports.service.file.FileReaderService; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import jakarta.annotation.PostConstruct; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import lombok.RequiredArgsConstructor; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class ReportInitializerServiceImpl implements ReportInitializerService { - private static final String INITIALIZE_JSON_PATH = - "src\\main\\resources\\db\\json\\test_report.json"; - private static final String UPDATE_JSON_PATH = - "src\\main\\resources\\db\\json\\db_report.json"; - private final ReportRepository repository; - - @Override - @PostConstruct - public void initialize() { - Path path = Paths.get(UPDATE_JSON_PATH); - if (Files.exists(path)) { - update(); - return; - } - SalesAndTrafficReport report = getReport(INITIALIZE_JSON_PATH); - SalesAndTrafficReport saved = repository.save(report); - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - try { - objectMapper.writeValue(new File(UPDATE_JSON_PATH), saved); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - @Scheduled(fixedRate = 900_000) /* updates data in db every 15 minutes */ - public void update() { - SalesAndTrafficReport report = getReport("src\\main\\resources\\db\\json\\db_report.json"); - repository.save(report); - } - - private SalesAndTrafficReport getReport(String fileName) { - String jsonString = FileReaderService.readFile(fileName); - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - try { - return objectMapper.readValue(jsonString, SalesAndTrafficReport.class); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java index c782ec9..4405442 100644 --- a/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java +++ b/src/main/java/com/app/sellerretailreports/service/sales/SalesAndTrafficByDateServiceImpl.java @@ -18,6 +18,16 @@ @Service @RequiredArgsConstructor public class SalesAndTrafficByDateServiceImpl implements SalesAndTrafficByDateService { + private static final String SALES_AND_TRAFFIC_BY_DATES_BETWEEN = + "salesAndTrafficByDatesBetween"; + private static final String SALES_AND_TRAFFIC_BY_SPECIFIED_DATE = + "salesAndTrafficBySpecifiedDate"; + private static final String SALES_AND_TRAFFIC_BY_SPECIFIED_ASINS = + "salesAndTrafficBySpecifiedAsins"; + private static final String SALES_AND_TRAFFIC_BY_ASINS = + "salesAndTrafficByAsins"; + private static final String SALES_AND_TRAFFIC_BY_DATES = + "salesAndTrafficByDates"; private static final int FIRST_ELEMENT_INDEX = 0; private final ReportRepository repository; private final SalesAndTrafficByDateMapper salesAndTrafficByDateMapper; @@ -78,16 +88,16 @@ public List findAllByDates() { @CacheEvict( value = { - "salesAndTrafficByDatesBetween", - "salesAndTrafficBySpecifiedDate", - "salesAndTrafficBySpecifiedAsins", - "salesAndTrafficByAsins", - "salesAndTrafficByDates" + SALES_AND_TRAFFIC_BY_DATES_BETWEEN, + SALES_AND_TRAFFIC_BY_SPECIFIED_DATE, + SALES_AND_TRAFFIC_BY_SPECIFIED_ASINS, + SALES_AND_TRAFFIC_BY_ASINS, + SALES_AND_TRAFFIC_BY_DATES }, allEntries = true ) @Scheduled(fixedRateString = "${caching.spring.TTL}") - public void emptyHotelsCache() { + public void emptyCache() { } private SalesAndTrafficReport findReport() { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 380f4e6..def7318 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,3 +8,5 @@ caching.spring.TTL=420000 jwt.expiration=${JWT_EXPIRATION} jwt.secret=${JWT_SECRET} + +logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG From cdb6c87af6ce507f9b68e3ba6f85556db0d735a6 Mon Sep 17 00:00:00 2001 From: Valerii Fedorovych Date: Thu, 29 Feb 2024 15:49:43 +0200 Subject: [PATCH 23/23] added readme --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..3028865 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Seller Retail Reports API + +This Spring Boot project helps in managing of Amazon seller reports. It can work with a big amount of data and different fields of statistics. + + + +## Demo + +[Watch video of working API --- YouTube Link](https://www.youtube.com/embed/7ooeL1PQU1Q?si=OUybXtMFl6JrWSrU) + +![Swagger UI API demonstration](images/swagger-ui.jpg) + + +## Tech Stack + +Technologies that used to create an efficient and well-organized environment for the development and management of the Reports API. + +**Java 17** + +**Spring Boot** + +**Spring Security** + +**Spring Cache** + +**Spring Data MongoDB** + +**MongoDB** + +**API Documentation:** Swagger + +**Build Tool:** Maven + + + +## Run Locally + +**This API requires JDK 17 and MongoDB Compass** + +Clone the project + +``` +git clone https://github.com/fedorovychh/seller-retail-reports.git +``` + +Open project in Inteliji IDEA + +Load Maven dependencies + +Define properties in application.properties file to match your need + +Open address http://localhost:8081/swagger-ui/index.html in your browser + +Success!!! You can start the project.