diff --git a/README.md b/README.md index c9b583db..9cb8535a 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,7 @@ var reimbursementsOrder = reportManager.GetReimbursementsOrder(180); //GET_FBA_R var feedbacks = reportManager.GetFeedbackFromDays(180); //GET_SELLER_FEEDBACK_DATA var LedgerDetails = reportManager.GetLedgerDetailAsync(10); //GET_LEDGER_DETAIL_VIEW_DATA var UnsuppressedInventory = reportManager.GetUnsuppressedInventoryDataAsync().ConfigureAwait(false).GetAwaiter().GetResult(); //GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA +var sellerPerformance = reportManager.GetSellerPerformance(); //GET_V2_SELLER_PERFORMANCE_REPORT ``` diff --git a/Source/FikaAmazonAPI/ReportGeneration/ReportManager.cs b/Source/FikaAmazonAPI/ReportGeneration/ReportManager.cs index fbe61b73..ce1d45b5 100644 --- a/Source/FikaAmazonAPI/ReportGeneration/ReportManager.cs +++ b/Source/FikaAmazonAPI/ReportGeneration/ReportManager.cs @@ -558,5 +558,36 @@ await amazonConnection.Reports.CreateReportAndDownloadFileStreamAsync( } #endregion + + #region Performance + + /// + /// Gets the seller performance report for the current marketplace, containing account health status + /// and performance metrics such as order defect rate, late shipment rate, and policy violations. + /// + /// A containing account status and performance metrics. + public SellerPerformanceReport GetSellerPerformance() => + Task.Run(() => GetSellerPerformanceAsync()).ConfigureAwait(false).GetAwaiter().GetResult(); + + /// + /// Gets the seller performance report asynchronously for the current marketplace, containing account health status + /// and performance metrics such as order defect rate, late shipment rate, and policy violations. + /// + /// A cancellation token that can be used to cancel the request. + /// A task that resolves to a containing account status and performance metrics. + public async Task GetSellerPerformanceAsync(CancellationToken cancellationToken = default) + { + var path = await GetSellerPerformanceAsync(_amazonConnection, cancellationToken); + return new SellerPerformanceReport(path, _amazonConnection.RefNumber); + } + + private async Task GetSellerPerformanceAsync(AmazonConnection amazonConnection, CancellationToken cancellationToken = default) + { + return await amazonConnection.Reports.CreateReportAndDownloadFileAsync( + ReportTypes.GET_V2_SELLER_PERFORMANCE_REPORT, + cancellationToken: cancellationToken); + } + + #endregion } -} \ No newline at end of file +} diff --git a/Source/FikaAmazonAPI/ReportGeneration/SellerPerformanceReport.cs b/Source/FikaAmazonAPI/ReportGeneration/SellerPerformanceReport.cs new file mode 100644 index 00000000..138a6c90 --- /dev/null +++ b/Source/FikaAmazonAPI/ReportGeneration/SellerPerformanceReport.cs @@ -0,0 +1,685 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Newtonsoft.Json; + +namespace FikaAmazonAPI.ReportGeneration +{ + /// + /// Represents a Seller Performance report from Amazon Selling Partner API + /// + public class SellerPerformanceReport + { + /// + /// Represents the collection of account status objects + /// for each marketplace identified in the Seller Performance report. + /// + public List AccountStatuses { get; set; } + + /// + /// Collection of marketplace-specific performance data + /// + public List Metrics { get; set; } = new List(); + + /// + /// Creates a new instance of SellerPerformanceReport from a JSON file + /// + /// Path to the JSON file + /// Reference number for the report + public SellerPerformanceReport(string jsonFilePath, string refNumber) + { + if (string.IsNullOrEmpty(jsonFilePath)) + return; + + Parse(File.ReadAllText(jsonFilePath), refNumber); + } + + /// + /// Creates a new instance of SellerPerformanceReport from a stream + /// + /// Stream containing the JSON report data + /// Reference number for the report + public SellerPerformanceReport(Stream stream, string refNumber) + { + if (stream == null) + return; + + using (var reader = new StreamReader(stream)) + { + Parse(reader.ReadToEnd(), refNumber); + } + } + + private void Parse(string jsonContent, string refNumber) + { + var performanceData = JsonConvert.DeserializeObject(jsonContent); + + if (performanceData?.AccountStatuses != null) + { + AccountStatuses = performanceData.AccountStatuses; + } + + if (performanceData?.PerformanceMetrics != null) + { + foreach (var metric in performanceData.PerformanceMetrics) + { + Metrics.Add(new SellerPerformanceMetrics + { + MarketplaceId = metric.MarketplaceId, + RefNumber = refNumber, + SnapshotDate = DateTime.UtcNow, + + // Account Health Rating + AccountHealthStatus = metric.AccountHealthRating?.AhrStatus, + AccountHealthScore = metric.AccountHealthRating?.AhrScore, + + // Order Defect Rate - AFN (FBA) + OrderDefectRateAFN = metric.OrderDefectRate?.Afn?.Rate, + OrderDefectRateTargetAFN = metric.OrderDefectRate?.Afn?.TargetValue, + OrderCountAFN = metric.OrderDefectRate?.Afn?.OrderCount, + OrdersWithDefectsCountAFN = metric.OrderDefectRate?.Afn?.OrderWithDefects?.Count, + ClaimsCountAFN = metric.OrderDefectRate?.Afn?.Claims?.Count, + ChargebackCountAFN = metric.OrderDefectRate?.Afn?.Chargebacks?.Count, + NegativeFeedbackCountAFN = metric.OrderDefectRate?.Afn?.NegativeFeedback?.Count, + + // Order Defect Rate - MFN (FBM) + OrderDefectRateMFN = metric.OrderDefectRate?.Mfn?.Rate, + OrderDefectRateTargetMFN = metric.OrderDefectRate?.Mfn?.TargetValue, + OrderCountMFN = metric.OrderDefectRate?.Mfn?.OrderCount, + OrdersWithDefectsCountMFN = metric.OrderDefectRate?.Mfn?.OrderWithDefects?.Count, + ClaimsCountMFN = metric.OrderDefectRate?.Mfn?.Claims?.Count, + ChargebackCountMFN = metric.OrderDefectRate?.Mfn?.Chargebacks?.Count, + NegativeFeedbackCountMFN = metric.OrderDefectRate?.Mfn?.NegativeFeedback?.Count, + + // Late Shipment Rate + LateShipmentRate = metric.LateShipmentRate?.Rate, + LateShipmentRateTarget = metric.LateShipmentRate?.TargetValue, + LateShipmentCount = metric.LateShipmentRate?.LateShipmentCount, + + // Pre-fulfillment Cancellation Rate + PreFulfillmentCancelRate = metric.PreFulfillmentCancellationRate?.Rate, + PreFulfillmentCancelRateTarget = metric.PreFulfillmentCancellationRate?.TargetValue, + PreFulfillmentCanceledOrderCount = metric.PreFulfillmentCancellationRate?.CancellationCount, + + // Valid Tracking Rate + ValidTrackingRate = metric.ValidTrackingRate?.Rate, + ValidTrackingRateTarget = metric.ValidTrackingRate?.TargetValue, + + // On-Time Delivery Rate + OnTimeDeliveryRate = metric.OnTimeDeliveryRate?.Rate, + OnTimeDeliveryRateTarget = metric.OnTimeDeliveryRate?.TargetValue, + + // Invoice Defect Rate + InvoiceDefectRate = metric.InvoiceDefectRate?.Rate, + InvoiceDefectRateTarget = metric.InvoiceDefectRate?.TargetValue, + + // Policy Violations + ListingPolicyViolationsCount = metric.ListingPolicyViolations?.DefectsCount, + ProductAuthenticityComplaintsCount = metric.ProductAuthenticityCustomerComplaints?.DefectsCount, + ProductConditionComplaintsCount = metric.ProductConditionCustomerComplaints?.DefectsCount, + ProductSafetyComplaintsCount = metric.ProductSafetyCustomerComplaints?.DefectsCount, + IntellectualPropertyComplaintsCount = metric.ReceivedIntellectualPropertyComplaints?.DefectsCount, + SuspectedIPViolationsCount = metric.SuspectedIntellectualPropertyViolations?.DefectsCount, + PolicyViolationWarningsCount = metric.PolicyViolationWarnings?.WarningsCount + }); + } + } + } + } + + /// + /// Represents a row of data in the Seller Performance report + /// + public class SellerPerformanceMetrics + { + /// + /// Amazon Marketplace ID + /// + public string MarketplaceId { get; set; } + + /// + /// Date of the report + /// + public DateTime? SnapshotDate { get; set; } + + /// + /// Account health status (GREAT, GOOD, FAIR, AT_RISK) + /// + public string AccountHealthStatus { get; set; } + + /// + /// Account health score + /// + public decimal? AccountHealthScore { get; set; } + + #region Order Defect Rate - AFN (FBA) + + /// + /// Order defect rate percentage for AFN (FBA) orders + /// + public decimal? OrderDefectRateAFN { get; set; } + + /// + /// Target order defect rate percentage for AFN (FBA) orders + /// + public decimal? OrderDefectRateTargetAFN { get; set; } + + /// + /// Total AFN (FBA) order count + /// + public int? OrderCountAFN { get; set; } + + /// + /// Number of AFN (FBA) orders with defects + /// + public int? OrdersWithDefectsCountAFN { get; set; } + + /// + /// Number of claims for AFN (FBA) orders + /// + public int? ClaimsCountAFN { get; set; } + + /// + /// Number of chargebacks for AFN (FBA) orders + /// + public int? ChargebackCountAFN { get; set; } + + /// + /// Number of negative feedback for AFN (FBA) orders + /// + public int? NegativeFeedbackCountAFN { get; set; } + + #endregion + + #region Order Defect Rate - MFN (FBM) + + /// + /// Order defect rate percentage for MFN (FBM) orders + /// + public decimal? OrderDefectRateMFN { get; set; } + + /// + /// Target order defect rate percentage for MFN (FBM) orders + /// + public decimal? OrderDefectRateTargetMFN { get; set; } + + /// + /// Total MFN (FBM) order count + /// + public int? OrderCountMFN { get; set; } + + /// + /// Number of MFN (FBM) orders with defects + /// + public int? OrdersWithDefectsCountMFN { get; set; } + + /// + /// Number of claims for MFN (FBM) orders + /// + public int? ClaimsCountMFN { get; set; } + + /// + /// Number of chargebacks for MFN (FBM) orders + /// + public int? ChargebackCountMFN { get; set; } + + /// + /// Number of negative feedback for MFN (FBM) orders + /// + public int? NegativeFeedbackCountMFN { get; set; } + + #endregion + + #region Late Shipment Rate + + /// + /// Late shipment rate percentage + /// + public decimal? LateShipmentRate { get; set; } + + /// + /// Target late shipment rate percentage + /// + public decimal? LateShipmentRateTarget { get; set; } + + /// + /// Number of late shipments + /// + public int? LateShipmentCount { get; set; } + + #endregion + + #region Pre-fulfillment Cancellation Rate + + /// + /// Pre-fulfillment cancel rate percentage + /// + public decimal? PreFulfillmentCancelRate { get; set; } + + /// + /// Target pre-fulfillment cancel rate percentage + /// + public decimal? PreFulfillmentCancelRateTarget { get; set; } + + /// + /// Number of orders canceled before fulfillment + /// + public int? PreFulfillmentCanceledOrderCount { get; set; } + + #endregion + + #region Valid Tracking Rate + + /// + /// Valid tracking rate percentage + /// + public decimal? ValidTrackingRate { get; set; } + + /// + /// Target valid tracking rate percentage + /// + public decimal? ValidTrackingRateTarget { get; set; } + + #endregion + + #region On-Time Delivery Rate + + /// + /// On-time delivery rate percentage + /// + public decimal? OnTimeDeliveryRate { get; set; } + + /// + /// Target on-time delivery rate percentage + /// + public decimal? OnTimeDeliveryRateTarget { get; set; } + + #endregion + + #region Invoice Defect Rate + + /// + /// Invoice defect rate percentage + /// + public decimal? InvoiceDefectRate { get; set; } + + /// + /// Target invoice defect rate percentage + /// + public decimal? InvoiceDefectRateTarget { get; set; } + + #endregion + + #region Policy Violations + + /// + /// Number of listing policy violations + /// + public int? ListingPolicyViolationsCount { get; set; } + + /// + /// Number of product authenticity complaints + /// + public int? ProductAuthenticityComplaintsCount { get; set; } + + /// + /// Number of product condition complaints + /// + public int? ProductConditionComplaintsCount { get; set; } + + /// + /// Number of product safety complaints + /// + public int? ProductSafetyComplaintsCount { get; set; } + + /// + /// Number of intellectual property complaints + /// + public int? IntellectualPropertyComplaintsCount { get; set; } + + /// + /// Number of suspected intellectual property violations + /// + public int? SuspectedIPViolationsCount { get; set; } + + /// + /// Number of policy violation warnings + /// + public int? PolicyViolationWarningsCount { get; set; } + + #endregion + + /// + /// Reference number for the report + /// + public string RefNumber { get; set; } + } + + /// + /// Helper classes for deserializing the JSON response + /// + internal class SellerPerformanceData + { + [JsonProperty("accountStatuses")] + public List AccountStatuses { get; set; } + + [JsonProperty("performanceMetrics")] + public List PerformanceMetrics { get; set; } + } + + public class AccountStatus + { + [JsonProperty("marketplaceId")] + public string MarketplaceId { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + } + + internal class PerformanceMetrics + { + [JsonProperty("marketplaceId")] + public string MarketplaceId { get; set; } + + [JsonProperty("lateShipmentRate")] + public LateShipmentRateMetric LateShipmentRate { get; set; } + + [JsonProperty("lateShipmentRateList")] + public List LateShipmentRateList { get; set; } + + [JsonProperty("invoiceDefectRate")] + public InvoiceDefectRateMetric InvoiceDefectRate { get; set; } + + [JsonProperty("orderDefectRate")] + public OrderDefectRateMetrics OrderDefectRate { get; set; } + + [JsonProperty("onTimeDeliveryRate")] + public OnTimeDeliveryRateMetric OnTimeDeliveryRate { get; set; } + + [JsonProperty("validTrackingRate")] + public ValidTrackingRateMetric ValidTrackingRate { get; set; } + + [JsonProperty("preFulfillmentCancellationRate")] + public PreFulfillmentCancellationRateMetric PreFulfillmentCancellationRate { get; set; } + + [JsonProperty("warningStates")] + public List WarningStates { get; set; } + + [JsonProperty("accountHealthRating")] + public AccountHealthRating AccountHealthRating { get; set; } + + // Policy violations + [JsonProperty("listingPolicyViolations")] + public PolicyViolationMetric ListingPolicyViolations { get; set; } + + [JsonProperty("productAuthenticityCustomerComplaints")] + public PolicyViolationMetric ProductAuthenticityCustomerComplaints { get; set; } + + [JsonProperty("productConditionCustomerComplaints")] + public PolicyViolationMetric ProductConditionCustomerComplaints { get; set; } + + [JsonProperty("productSafetyCustomerComplaints")] + public PolicyViolationMetric ProductSafetyCustomerComplaints { get; set; } + + [JsonProperty("receivedIntellectualPropertyComplaints")] + public PolicyViolationMetric ReceivedIntellectualPropertyComplaints { get; set; } + + [JsonProperty("restrictedProductPolicyViolations")] + public PolicyViolationMetric RestrictedProductPolicyViolations { get; set; } + + [JsonProperty("suspectedIntellectualPropertyViolations")] + public PolicyViolationMetric SuspectedIntellectualPropertyViolations { get; set; } + + [JsonProperty("foodAndProductSafetyIssues")] + public PolicyViolationMetric FoodAndProductSafetyIssues { get; set; } + + [JsonProperty("customerProductReviewsPolicyViolations")] + public PolicyViolationMetric CustomerProductReviewsPolicyViolations { get; set; } + + [JsonProperty("otherPolicyViolations")] + public PolicyViolationMetric OtherPolicyViolations { get; set; } + + [JsonProperty("documentRequests")] + public PolicyViolationMetric DocumentRequests { get; set; } + + [JsonProperty("policyViolationWarnings")] + public PolicyViolationWarnings PolicyViolationWarnings { get; set; } + } + + internal class ReportingDateRange + { + [JsonProperty("reportingDateFrom")] + public string ReportingDateFrom { get; set; } + + [JsonProperty("reportingDateTo")] + public string ReportingDateTo { get; set; } + } + + internal class LateShipmentRateMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("orderCount")] + public int OrderCount { get; set; } + + [JsonProperty("lateShipmentCount")] + public int LateShipmentCount { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + } + + internal class InvoiceDefectRateMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("invoiceDefect")] + public InvoiceDefect InvoiceDefect { get; set; } + + [JsonProperty("missingInvoice")] + public InvoiceDefect MissingInvoice { get; set; } + + [JsonProperty("lateInvoice")] + public InvoiceDefect LateInvoice { get; set; } + + [JsonProperty("orderCount")] + public int OrderCount { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + } + + internal class InvoiceDefect + { + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("count")] + public int Count { get; set; } + } + + internal class OrderDefectRateMetrics + { + [JsonProperty("afn")] + public OrderDefectRateMetric Afn { get; set; } + + [JsonProperty("mfn")] + public OrderDefectRateMetric Mfn { get; set; } + } + + internal class OrderDefectRateMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("orderWithDefects")] + public DefectCount OrderWithDefects { get; set; } + + [JsonProperty("claims")] + public DefectCount Claims { get; set; } + + [JsonProperty("chargebacks")] + public DefectCount Chargebacks { get; set; } + + [JsonProperty("negativeFeedback")] + public DefectCount NegativeFeedback { get; set; } + + [JsonProperty("orderCount")] + public int OrderCount { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + + [JsonProperty("fulfillmentType")] + public string FulfillmentType { get; set; } + } + + internal class DefectCount + { + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("count")] + public int Count { get; set; } + } + + internal class OnTimeDeliveryRateMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("shipmentCountWithValidTracking")] + public int ShipmentCountWithValidTracking { get; set; } + + [JsonProperty("onTimeDeliveryCount")] + public int OnTimeDeliveryCount { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + } + + internal class ValidTrackingRateMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("shipmentCount")] + public int ShipmentCount { get; set; } + + [JsonProperty("validTrackingCount")] + public int ValidTrackingCount { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + } + + internal class PreFulfillmentCancellationRateMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("orderCount")] + public int OrderCount { get; set; } + + [JsonProperty("cancellationCount")] + public int CancellationCount { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + } + + internal class AccountHealthRating + { + [JsonProperty("ahrStatus")] + public string AhrStatus { get; set; } + + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("ahrScore")] + public decimal AhrScore { get; set; } + } + + internal class PolicyViolationMetric + { + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + + [JsonProperty("targetValue")] + public decimal TargetValue { get; set; } + + [JsonProperty("targetCondition")] + public string TargetCondition { get; set; } + + [JsonProperty("defectsCount")] + public int DefectsCount { get; set; } + } + + internal class PolicyViolationWarnings + { + [JsonProperty("warningsCount")] + public int WarningsCount { get; set; } + + [JsonProperty("reportingDateRange")] + public ReportingDateRange ReportingDateRange { get; set; } + } +} \ No newline at end of file