diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminMetricsController.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminMetricsController.cs index b248c813..6dd9a441 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminMetricsController.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminMetricsController.cs @@ -74,7 +74,7 @@ public class AdminMetricsController : ControllerBase _logger.LogInformation("Generated platform overview for period {Start} to {End}", start, end); - return Ok(overview); + return Ok(new { success = true, data = overview }); } /// @@ -89,7 +89,7 @@ public class AdminMetricsController : ControllerBase { var validMetrics = new[] { "spend", "impressions", "clicks", "revenue", "roas" }; if (!validMetrics.Contains(metric.ToLower())) - return BadRequest(new { message = $"Invalid metric. Valid options: {string.Join(", ", validMetrics)}" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = $"Invalid metric. Valid options: {string.Join(", ", validMetrics)}" } }); // EN: Get metrics from last 30 days // VI: Lấy metrics 30 ngày gần nhất @@ -129,7 +129,7 @@ c.TotalClicks, "Clicks")).ToList(), _logger.LogInformation("Generated top {Limit} campaigns by {Metric}", limit, metric); - return Ok(topCampaigns); + return Ok(new { success = true, data = topCampaigns }); } /// @@ -142,6 +142,6 @@ c.TotalClicks, "Clicks")).ToList(), { _logger.LogWarning("GetAnomalies not yet implemented"); return StatusCode(StatusCodes.Status501NotImplemented, - new { message = "Anomaly detection will be implemented in future version with ML models" }); + new { success = false, error = new { code = "NOT_IMPLEMENTED", message = "Anomaly detection will be implemented in future version with ML models" } }); } } diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminReportsController.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminReportsController.cs index 829cf801..10b39356 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminReportsController.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/Admin/AdminReportsController.cs @@ -53,7 +53,7 @@ public class AdminReportsController : ControllerBase _logger.LogInformation("Admin retrieved {Count} reports", reports.Count); - return Ok(reports); + return Ok(new { success = true, data = reports }); } /// @@ -68,7 +68,7 @@ public class AdminReportsController : ControllerBase var report = await _context.Reports.FindAsync(id); if (report == null) - return NotFound(new { message = $"Report {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Report {id} not found" } }); _context.Reports.Remove(report); await _context.SaveChangesAsync(); diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/BreakdownController.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/BreakdownController.cs index bd3162c3..6b78c75b 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/BreakdownController.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/BreakdownController.cs @@ -37,11 +37,11 @@ public class BreakdownController : ControllerBase [FromQuery] DateTime? endDate = null) { if (string.IsNullOrWhiteSpace(by)) - return BadRequest(new { message = "Breakdown dimension 'by' is required" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Breakdown dimension 'by' is required" } }); var validDimensions = new[] { "age", "gender", "device", "placement" }; if (!validDimensions.Contains(by.ToLower())) - return BadRequest(new { message = $"Invalid dimension. Valid options: {string.Join(", ", validDimensions)}" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = $"Invalid dimension. Valid options: {string.Join(", ", validDimensions)}" } }); // EN: Return mock data (full implementation requires event tracking data) // VI: Trả về mock data (triển khai đầy đủ cần dữ liệu tracking) @@ -50,7 +50,7 @@ public class BreakdownController : ControllerBase _logger.LogInformation("Generated mock breakdown data for campaign {CampaignId} by {Dimension}", id, by); - return Ok(mockBreakdown); + return Ok(new { success = true, data = mockBreakdown }); } private CampaignBreakdownDto GenerateMockBreakdown(Guid campaignId, string dimension) diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/InsightsController.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/InsightsController.cs index 75b8db9e..87d67f09 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/InsightsController.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/InsightsController.cs @@ -46,7 +46,7 @@ public class InsightsController : ControllerBase _logger.LogInformation("Generated audience insights for campaign {CampaignId}", campaignId); - return Ok(insights); + return Ok(new { success = true, data = insights }); } /// @@ -83,6 +83,6 @@ public class InsightsController : ControllerBase _logger.LogInformation("Generated performance insights for advertiser {AdvertiserId}", advertiserId); - return Ok(insights); + return Ok(new { success = true, data = insights }); } } diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/MetricsController.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/MetricsController.cs index 20782430..898b5cb1 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/MetricsController.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/MetricsController.cs @@ -57,9 +57,9 @@ public class MetricsController : ControllerBase var metrics = await _mediator.Send(query); if (metrics == null) - return NotFound(new { message = $"No metrics found for campaign {id}" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"No metrics found for campaign {id}" } }); - return Ok(metrics); + return Ok(new { success = true, data = metrics }); } /// @@ -71,8 +71,8 @@ public class MetricsController : ControllerBase public IActionResult GetAdSetMetrics(Guid id) { _logger.LogWarning("AdSet metrics not yet implemented"); - return StatusCode(StatusCodes.Status501NotImplemented, - new { message = "AdSet metrics endpoint not yet implemented" }); + return StatusCode(StatusCodes.Status501NotImplemented, + new { success = false, error = new { code = "NOT_IMPLEMENTED", message = "AdSet metrics endpoint not yet implemented" } }); } /// @@ -84,7 +84,7 @@ public class MetricsController : ControllerBase public IActionResult GetAdMetrics(Guid id) { _logger.LogWarning("Ad metrics not yet implemented"); - return StatusCode(StatusCodes.Status501NotImplemented, - new { message = "Ad metrics endpoint not yet implemented" }); + return StatusCode(StatusCodes.Status501NotImplemented, + new { success = false, error = new { code = "NOT_IMPLEMENTED", message = "Ad metrics endpoint not yet implemented" } }); } } diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/ReportsController.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/ReportsController.cs index 0dd9827d..34e718cd 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/ReportsController.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.API/Controllers/ReportsController.cs @@ -48,7 +48,7 @@ public class ReportsController : ControllerBase }; var reports = await _mediator.Send(query); - return Ok(reports); + return Ok(new { success = true, data = reports }); } /// @@ -63,10 +63,10 @@ public class ReportsController : ControllerBase [FromQuery] Guid advertiserId) { if (string.IsNullOrWhiteSpace(request.Name)) - return BadRequest(new { message = "Report name is required" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Report name is required" } }); if (!Enum.TryParse(request.ReportType, out var reportType)) - return BadRequest(new { message = "Invalid report type" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Invalid report type" } }); var command = new CreateReportCommand { @@ -79,7 +79,7 @@ public class ReportsController : ControllerBase var reportId = await _mediator.Send(command); - return CreatedAtAction(nameof(GetReportById), new { id = reportId }, reportId); + return CreatedAtAction(nameof(GetReportById), new { id = reportId }, new { success = true, data = reportId }); } /// @@ -92,7 +92,7 @@ public class ReportsController : ControllerBase { _logger.LogWarning("GetReportById not yet fully implemented"); return StatusCode(StatusCodes.Status501NotImplemented, - new { message = "Get report by ID endpoint not yet implemented" }); + new { success = false, error = new { code = "NOT_IMPLEMENTED", message = "Get report by ID endpoint not yet implemented" } }); } /// @@ -105,7 +105,7 @@ public class ReportsController : ControllerBase { _logger.LogWarning("ScheduleReport not yet implemented"); return StatusCode(StatusCodes.Status501NotImplemented, - new { message = "Schedule report endpoint will be implemented in future version" }); + new { success = false, error = new { code = "NOT_IMPLEMENTED", message = "Schedule report endpoint will be implemented in future version" } }); } /// @@ -118,6 +118,6 @@ public class ReportsController : ControllerBase { _logger.LogWarning("ExportReport not yet implemented"); return StatusCode(StatusCodes.Status501NotImplemented, - new { message = "Export report endpoint will be implemented in future version" }); + new { success = false, error = new { code = "NOT_IMPLEMENTED", message = "Export report endpoint will be implemented in future version" } }); } } diff --git a/services/ads-analytics-service-net/src/AdsAnalyticsService.Infrastructure/DependencyInjection.cs b/services/ads-analytics-service-net/src/AdsAnalyticsService.Infrastructure/DependencyInjection.cs index 669242df..0f1f99c0 100644 --- a/services/ads-analytics-service-net/src/AdsAnalyticsService.Infrastructure/DependencyInjection.cs +++ b/services/ads-analytics-service-net/src/AdsAnalyticsService.Infrastructure/DependencyInjection.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using AdsAnalyticsService.Infrastructure.Idempotency; namespace AdsAnalyticsService.Infrastructure; @@ -30,7 +29,9 @@ public static class DependencyInjection } }); - services.AddScoped(); + // EN: Idempotency services not registered — no handler uses IRequestManager + // VI: Idempotency services không được đăng ký — không có handler nào dùng IRequestManager + return services; } } diff --git a/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/BillingAccountsController.cs b/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/BillingAccountsController.cs index 22c57cad..506348e8 100644 --- a/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/BillingAccountsController.cs +++ b/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/BillingAccountsController.cs @@ -38,7 +38,7 @@ public class BillingAccountsController : ControllerBase var accountId = await _mediator.Send(command); - return CreatedAtAction(nameof(GetBillingAccount), new { id = accountId }, accountId); + return CreatedAtAction(nameof(GetBillingAccount), new { id = accountId }, new { success = true, data = accountId }); } /// @@ -57,10 +57,10 @@ public class BillingAccountsController : ControllerBase if (account == null) { - return NotFound(new { message = $"Billing account {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account {id} not found" } }); } - return Ok(account); + return Ok(new { success = true, data = account }); } /// @@ -77,7 +77,7 @@ public class BillingAccountsController : ControllerBase if (request.Amount <= 0) { - return BadRequest(new { message = "Amount must be positive" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Amount must be positive" } }); } var command = new AddFundsCommand(id, request.Amount); @@ -85,10 +85,10 @@ public class BillingAccountsController : ControllerBase if (!success) { - return NotFound(new { message = $"Billing account {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account {id} not found" } }); } - return Ok(new { accountId = id, amountAdded = request.Amount }); + return Ok(new { success = true, data = new { accountId = id, amountAdded = request.Amount } }); } /// @@ -107,10 +107,10 @@ public class BillingAccountsController : ControllerBase if (balance == null) { - return NotFound(new { message = $"Billing account {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account {id} not found" } }); } - return Ok(new { accountId = id, balance = balance.Value }); + return Ok(new { success = true, data = new { accountId = id, balance = balance.Value } }); } } diff --git a/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/CreditLinesController.cs b/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/CreditLinesController.cs index 7da65c5f..35ff6fc9 100644 --- a/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/CreditLinesController.cs +++ b/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/CreditLinesController.cs @@ -43,14 +43,14 @@ public class CreditLinesController : ControllerBase if (account == null) { - return NotFound(new { message = $"Billing account for advertiser {advertiserId} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account for advertiser {advertiserId} not found" } }); } var availableCredit = account.CreditLimit <= 0 ? 0m : Math.Max(0m, account.CreditLimit - account.Balance); - return Ok(new + return Ok(new { success = true, data = new { advertiserId, accountId = account.Id, @@ -59,7 +59,7 @@ public class CreditLinesController : ControllerBase availableCredit, paymentMethod = account.PaymentMethod.ToString(), status = account.Status.ToString() - }); + } }); } /// @@ -78,7 +78,7 @@ public class CreditLinesController : ControllerBase if (request.RequestedAmount <= 0) { - return BadRequest(new { message = "Requested amount must be positive" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Requested amount must be positive" } }); } var account = await _context.BillingAccounts @@ -86,14 +86,14 @@ public class CreditLinesController : ControllerBase if (account == null) { - return NotFound(new { message = $"Billing account for advertiser {request.AdvertiserId} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account for advertiser {request.AdvertiserId} not found" } }); } var oldCreditLimit = account.CreditLimit; account.SetCreditLimit(oldCreditLimit + request.RequestedAmount); await _context.SaveEntitiesAsync(cancellationToken); - return Accepted(new + return Accepted(new { success = true, data = new { advertiserId = request.AdvertiserId, accountId = account.Id, @@ -102,7 +102,7 @@ public class CreditLinesController : ControllerBase newCreditLimit = account.CreditLimit, status = account.Status.ToString(), message = "Credit limit increased successfully" - }); + } }); } } diff --git a/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/InvoicesController.cs b/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/InvoicesController.cs index 91849614..63f589ee 100644 --- a/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/InvoicesController.cs +++ b/services/ads-billing-service-net/src/AdsBillingService.API/Controllers/InvoicesController.cs @@ -42,13 +42,13 @@ public class InvoicesController : ControllerBase var query = new GetInvoicesQuery(billingAccountId, status, pageNumber, pageSize); var invoices = await _mediator.Send(query); - return Ok(new - { + return Ok(new { success = true, data = new + { pageNumber, pageSize, total = invoices.Count, - data = invoices - }); + items = invoices + } }); } /// @@ -67,10 +67,10 @@ public class InvoicesController : ControllerBase if (invoice == null) { - return NotFound(new { message = $"Invoice {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Invoice {id} not found" } }); } - return Ok(invoice); + return Ok(new { success = true, data = invoice }); } /// @@ -90,7 +90,7 @@ public class InvoicesController : ControllerBase if (invoice == null) { - return NotFound(new { message = $"Invoice {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Invoice {id} not found" } }); } var lineItemsContent = invoice.LineItems.Any() diff --git a/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/EntityConfigurations/InvoiceEntityTypeConfiguration.cs b/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/EntityConfigurations/InvoiceEntityTypeConfiguration.cs index b0635e5a..a42b6352 100644 --- a/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/EntityConfigurations/InvoiceEntityTypeConfiguration.cs +++ b/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/EntityConfigurations/InvoiceEntityTypeConfiguration.cs @@ -67,14 +67,15 @@ public class InvoiceEntityTypeConfiguration : IEntityTypeConfiguration .HasColumnType("decimal(18,2)") .IsRequired(); - // EN: Line items as collection / VI: Các dòng chi tiết - builder.HasMany() + // EN: Line items as owned collection via navigation property + // VI: Các dòng chi tiết qua navigation property + // NOTE: Must use the navigation expression to avoid EF creating a shadow InvoiceId1 FK + var navigation = builder.Metadata.FindNavigation(nameof(Invoice.LineItems))!; + navigation.SetPropertyAccessMode(PropertyAccessMode.Field); + + builder.HasMany(i => i.LineItems) .WithOne() .HasForeignKey("InvoiceId") .OnDelete(DeleteBehavior.Cascade); - - // EN: Metadata / VI: Ignore navigation property for EF Core - builder.Metadata.FindNavigation(nameof(Invoice.LineItems))! - .SetPropertyAccessMode(PropertyAccessMode.Field); } } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdSetsController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdSetsController.cs index 2a114722..0af8ed3f 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdSetsController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdSetsController.cs @@ -38,7 +38,7 @@ public class AdSetsController : ControllerBase var adSetId = await _mediator.Send(command); - return CreatedAtAction(nameof(GetAdSetById), new { id = adSetId }, adSetId); + return CreatedAtAction(nameof(GetAdSetById), new { id = adSetId }, new { success = true, data = adSetId }); } /// @@ -53,8 +53,8 @@ public class AdSetsController : ControllerBase var adSet = await _mediator.Send(new GetAdSetByIdQuery { AdSetId = id }); if (adSet == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Ad set not found" } }); - return Ok(adSet); + return Ok(new { success = true, data = adSet }); } } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminAdsController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminAdsController.cs index ad32b272..45b9c85b 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminAdsController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminAdsController.cs @@ -41,7 +41,7 @@ public class AdminAdsController : ControllerBase PageSize = pageSize }); - return Ok(ads); + return Ok(new { success = true, data = ads }); } /// @@ -58,7 +58,7 @@ public class AdminAdsController : ControllerBase var result = await _mediator.Send(new ApproveAdCommand { AdId = id }); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Ad not found" } }); return NoContent(); } @@ -81,7 +81,7 @@ public class AdminAdsController : ControllerBase }); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Ad not found" } }); return NoContent(); } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminCampaignsController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminCampaignsController.cs index 55b55364..8f2a5767 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminCampaignsController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminCampaignsController.cs @@ -43,7 +43,7 @@ public class AdminCampaignsController : ControllerBase }; var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -55,7 +55,7 @@ public class AdminCampaignsController : ControllerBase public async Task> GetCampaignStats() { var stats = await _mediator.Send(new GetCampaignStatsQuery()); - return Ok(stats); + return Ok(new { success = true, data = stats }); } } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminReportsController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminReportsController.cs index a6373902..1eea0d92 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminReportsController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdminReportsController.cs @@ -32,7 +32,7 @@ public class AdminReportsController : ControllerBase public async Task>> GetTopAdvertisers([FromQuery] int limit = 10) { var advertisers = await _mediator.Send(new GetTopAdvertisersQuery { Limit = limit }); - return Ok(advertisers); + return Ok(new { success = true, data = advertisers }); } /// @@ -51,7 +51,7 @@ public class AdminReportsController : ControllerBase EndDate = endDate }); - return Ok(analytics); + return Ok(new { success = true, data = analytics }); } } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdsController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdsController.cs index c51d81ba..829fae4f 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdsController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AdsController.cs @@ -38,7 +38,7 @@ public class AdsController : ControllerBase var adId = await _mediator.Send(command); - return CreatedAtAction(nameof(GetAdById), new { id = adId }, adId); + return CreatedAtAction(nameof(GetAdById), new { id = adId }, new { success = true, data = adId }); } /// @@ -53,9 +53,9 @@ public class AdsController : ControllerBase var ad = await _mediator.Send(new GetAdByIdQuery { AdId = id }); if (ad == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Ad not found" } }); - return Ok(ad); + return Ok(new { success = true, data = ad }); } /// @@ -72,7 +72,7 @@ public class AdsController : ControllerBase var result = await _mediator.Send(new SubmitAdForReviewCommand { AdId = id }); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Ad not found" } }); return NoContent(); } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AudiencesController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AudiencesController.cs index 08e3a7d5..ed3951aa 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AudiencesController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/AudiencesController.cs @@ -36,7 +36,7 @@ public class AudiencesController : ControllerBase var audiences = await _mediator.Send(new ListAudiencesQuery { AdvertiserId = advertiserId }); - return Ok(audiences); + return Ok(new { success = true, data = audiences }); } /// @@ -51,9 +51,9 @@ public class AudiencesController : ControllerBase var audience = await _mediator.Send(new GetAudienceByIdQuery { AudienceId = id }); if (audience == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Audience not found" } }); - return Ok(audience); + return Ok(new { success = true, data = audience }); } } diff --git a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/CampaignsController.cs b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/CampaignsController.cs index 38f3abb8..99e786fb 100644 --- a/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/CampaignsController.cs +++ b/services/ads-manager-service-net/src/AdsManagerService.API/Controllers/CampaignsController.cs @@ -38,7 +38,7 @@ public class CampaignsController : ControllerBase var campaignId = await _mediator.Send(command); - return CreatedAtAction(nameof(GetCampaignById), new { id = campaignId }, campaignId); + return CreatedAtAction(nameof(GetCampaignById), new { id = campaignId }, new { success = true, data = campaignId }); } /// @@ -66,7 +66,7 @@ public class CampaignsController : ControllerBase }; var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -81,9 +81,9 @@ public class CampaignsController : ControllerBase var campaign = await _mediator.Send(new GetCampaignByIdQuery { CampaignId = id }); if (campaign == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Campaign not found" } }); - return Ok(campaign); + return Ok(new { success = true, data = campaign }); } /// @@ -105,7 +105,7 @@ public class CampaignsController : ControllerBase var result = await _mediator.Send(command); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Campaign not found" } }); return NoContent(); } @@ -124,7 +124,7 @@ public class CampaignsController : ControllerBase var result = await _mediator.Send(new ActivateCampaignCommand { CampaignId = id }); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Campaign not found" } }); return NoContent(); } @@ -143,7 +143,7 @@ public class CampaignsController : ControllerBase var result = await _mediator.Send(new PauseCampaignCommand { CampaignId = id }); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Campaign not found" } }); return NoContent(); } @@ -162,7 +162,7 @@ public class CampaignsController : ControllerBase var result = await _mediator.Send(new DeleteCampaignCommand { CampaignId = id }); if (!result) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Campaign not found" } }); return NoContent(); } diff --git a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminAuctionsController.cs b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminAuctionsController.cs index 7709729c..9e3b3eb9 100644 --- a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminAuctionsController.cs +++ b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminAuctionsController.cs @@ -49,7 +49,7 @@ public class AdminAuctionsController : ControllerBase }; var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -62,6 +62,6 @@ public class AdminAuctionsController : ControllerBase { _logger.LogInformation("Auction statistics requested"); var statistics = await _mediator.Send(new GetAuctionStatisticsQuery()); - return Ok(statistics); + return Ok(new { success = true, data = statistics }); } } diff --git a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminBudgetController.cs b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminBudgetController.cs index 07ec136b..50fe1a18 100644 --- a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminBudgetController.cs +++ b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminBudgetController.cs @@ -50,7 +50,7 @@ public class AdminBudgetController : ControllerBase }; var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -78,9 +78,9 @@ public class AdminBudgetController : ControllerBase .FirstOrDefaultAsync(); if (pacer == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Budget pacer not found for this campaign" } }); - return Ok(pacer); + return Ok(new { success = true, data = pacer }); } /// @@ -97,13 +97,13 @@ public class AdminBudgetController : ControllerBase .FirstOrDefaultAsync(); if (pacer == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Budget pacer not found for this campaign" } }); pacer.ResetDailySpend(); await _context.SaveChangesAsync(); _logger.LogInformation("Manual budget reset for Campaign {CampaignId}", campaignId); - return Ok(); + return Ok(new { success = true, data = new { message = "Budget reset successfully" } }); } /// @@ -132,6 +132,6 @@ public class AdminBudgetController : ControllerBase CampaignsExceeded = stats.Count(s => s.Utilization >= 100) }; - return Ok(result); + return Ok(new { success = true, data = result }); } } diff --git a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminFrequencyController.cs b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminFrequencyController.cs index 498b3816..b4104981 100644 --- a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminFrequencyController.cs +++ b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdminFrequencyController.cs @@ -48,7 +48,7 @@ public class AdminFrequencyController : ControllerBase }) .ToListAsync(); - return Ok(caps); + return Ok(new { success = true, data = caps }); } /// @@ -72,9 +72,9 @@ public class AdminFrequencyController : ControllerBase .FirstOrDefaultAsync(); if (cap == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Frequency cap not found" } }); - return Ok(cap); + return Ok(new { success = true, data = cap }); } /// @@ -87,7 +87,7 @@ public class AdminFrequencyController : ControllerBase public async Task> CreateFrequencyCap([FromBody] CreateFrequencyCapRequest request) { if (!Enum.TryParse(request.Window, out var window)) - return BadRequest("Invalid frequency window"); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Invalid frequency window" } }); var cap = new FrequencyCap(request.AdId, request.MaxImpressionsPerUser, window); @@ -104,7 +104,7 @@ public class AdminFrequencyController : ControllerBase _logger.LogInformation("Created frequency cap {Id} for Ad {AdId}", cap.Id, request.AdId); - return CreatedAtAction(nameof(GetFrequencyCap), new { id = cap.Id }, dto); + return CreatedAtAction(nameof(GetFrequencyCap), new { id = cap.Id }, new { success = true, data = dto }); } /// @@ -119,7 +119,7 @@ public class AdminFrequencyController : ControllerBase var cap = await _context.FrequencyCaps.FindAsync(id); if (cap == null) - return NotFound(); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Frequency cap not found" } }); _context.FrequencyCaps.Remove(cap); await _context.SaveChangesAsync(); diff --git a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdsController.cs b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdsController.cs index 12ff3461..ccc360d0 100644 --- a/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdsController.cs +++ b/services/ads-serving-service-net/src/AdsServingService.API/Controllers/AdsController.cs @@ -51,7 +51,7 @@ public class AdsController : ControllerBase if (result == null) return NoContent(); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -73,7 +73,7 @@ public class AdsController : ControllerBase }, HttpContext.RequestAborted); - return Accepted(); + return Accepted(new { success = true, data = new { message = "Impression tracked" } }); } /// @@ -95,7 +95,7 @@ public class AdsController : ControllerBase }, HttpContext.RequestAborted); - return Accepted(); + return Accepted(new { success = true, data = new { message = "Click tracked" } }); } } diff --git a/services/ads-serving-service-net/src/AdsServingService.Infrastructure/DependencyInjection.cs b/services/ads-serving-service-net/src/AdsServingService.Infrastructure/DependencyInjection.cs index 212165df..dca1b55d 100644 --- a/services/ads-serving-service-net/src/AdsServingService.Infrastructure/DependencyInjection.cs +++ b/services/ads-serving-service-net/src/AdsServingService.Infrastructure/DependencyInjection.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using AdsServingService.Infrastructure.Idempotency; namespace AdsServingService.Infrastructure; @@ -41,8 +40,8 @@ public static class DependencyInjection // Register repositories (when needed) // services.AddScoped(); - // Register idempotency services - services.AddScoped(); + // EN: Idempotency services not registered — no handler uses IRequestManager + // VI: Idempotency services không được đăng ký — không có handler nào dùng IRequestManager return services; } diff --git a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminAttributionController.cs b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminAttributionController.cs index 49f84f7c..8b644126 100644 --- a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminAttributionController.cs +++ b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminAttributionController.cs @@ -46,7 +46,7 @@ public class AdminAttributionController : ControllerBase ); _logger.LogInformation("Admin: Retrieved attribution stats"); - return Ok(stats); + return Ok(new { success = true, data = stats }); } /// @@ -78,7 +78,7 @@ public class AdminAttributionController : ControllerBase ); _logger.LogInformation("Admin: Retrieved attribution report for campaign {CampaignId}", campaignId); - return Ok(report); + return Ok(new { success = true, data = report }); } } diff --git a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminConversionsController.cs b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminConversionsController.cs index a6a41d7e..c0ff4730 100644 --- a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminConversionsController.cs +++ b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminConversionsController.cs @@ -51,7 +51,7 @@ public class AdminConversionsController : ControllerBase var result = await _mediator.Send(query, ct); _logger.LogInformation("Admin: Listed {Count} conversions", result.Count()); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -78,7 +78,7 @@ public class AdminConversionsController : ControllerBase ); _logger.LogInformation("Admin: Retrieved conversion stats"); - return Ok(stats); + return Ok(new { success = true, data = stats }); } /// @@ -107,7 +107,7 @@ public class AdminConversionsController : ControllerBase ); _logger.LogInformation("Admin: Retrieved conversion details for {ConversionId}", id); - return Ok(detail); + return Ok(new { success = true, data = detail }); } } diff --git a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminPixelsController.cs b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminPixelsController.cs index 9ed4dc16..0e4405aa 100644 --- a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminPixelsController.cs +++ b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/Admin/AdminPixelsController.cs @@ -44,7 +44,7 @@ public class AdminPixelsController : ControllerBase }; _logger.LogInformation("Admin: Listed {Count} pixels", pixels.Count); - return Ok(pixels); + return Ok(new { success = true, data = pixels }); } /// @@ -63,7 +63,7 @@ public class AdminPixelsController : ControllerBase { var events = new List(); _logger.LogInformation("Admin: Listed events for pixel {PixelId}", pixelId); - return Ok(events); + return Ok(new { success = true, data = events }); } /// @@ -90,7 +90,7 @@ public class AdminPixelsController : ControllerBase ); _logger.LogInformation("Admin: Retrieved stats for pixel {PixelId}", pixelId); - return Ok(stats); + return Ok(new { success = true, data = stats }); } /// @@ -105,7 +105,7 @@ public class AdminPixelsController : ControllerBase // EN: Would implement activation logic via Command // VI: Sẽ implement logic kích hoạt qua Command _logger.LogInformation("Admin: Activated pixel {PixelId}", pixelId); - return Ok(new { Message = "Pixel activated successfully" }); + return Ok(new { success = true, data = new { message = "Pixel activated successfully" } }); } /// @@ -120,7 +120,7 @@ public class AdminPixelsController : ControllerBase // EN: Would implement deactivation logic via Command // VI: Sẽ implement logic vô hiệu hóa qua Command _logger.LogInformation("Admin: Deactivated pixel {PixelId}", pixelId); - return Ok(new { Message = "Pixel deactivated successfully" }); + return Ok(new { success = true, data = new { message = "Pixel deactivated successfully" } }); } } diff --git a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/ConversionsController.cs b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/ConversionsController.cs index 9452da29..f9551ec9 100644 --- a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/ConversionsController.cs +++ b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/ConversionsController.cs @@ -73,7 +73,7 @@ public class ConversionsController : ControllerBase var query = new GetConversionsQuery(campaignId, userId, from, to, skip, take); var result = await _mediator.Send(query, ct); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -92,10 +92,10 @@ public class ConversionsController : ControllerBase if (result == null) { - return NotFound(new { Message = "Attribution not found for this conversion" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Attribution not found for this conversion" } }); } - return Ok(result); + return Ok(new { success = true, data = result }); } } diff --git a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/EventsController.cs b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/EventsController.cs index d31acc16..d893f154 100644 --- a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/EventsController.cs +++ b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/EventsController.cs @@ -50,10 +50,10 @@ public class EventsController : ControllerBase if (!success) { - return BadRequest(new { Message = "Invalid pixel code or pixel is not active" }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Invalid pixel code or pixel is not active" } }); } - return Accepted(new { Message = "Event tracked successfully" }); + return Accepted(new { success = true, data = new { message = "Event tracked successfully" } }); } /// @@ -84,7 +84,7 @@ public class EventsController : ControllerBase "Server-side event tracked: AdId={AdId}, UserId={UserId}, EventType={EventType}", request.AdId, request.UserId, request.EventType); - return Accepted(new { Message = "Server-side event tracked successfully" }); + return Accepted(new { success = true, data = new { message = "Server-side event tracked successfully" } }); } } diff --git a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/PixelsController.cs b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/PixelsController.cs index 6c0d3e22..0433310e 100644 --- a/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/PixelsController.cs +++ b/services/ads-tracking-service-net/src/AdsTrackingService.API/Controllers/PixelsController.cs @@ -41,10 +41,10 @@ public class PixelsController : ControllerBase if (result == null) { - return NotFound(new { Message = "Pixel not found for this advertiser" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Pixel not found for this advertiser" } }); } - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -68,7 +68,7 @@ public class PixelsController : ControllerBase return CreatedAtAction( nameof(GetPixelCode), new { advertiserId = request.AdvertiserId }, - result); + new { success = true, data = result }); } } diff --git a/services/booking-service-net/src/BookingService.Infrastructure/DependencyInjection.cs b/services/booking-service-net/src/BookingService.Infrastructure/DependencyInjection.cs index e699b361..470209ce 100644 --- a/services/booking-service-net/src/BookingService.Infrastructure/DependencyInjection.cs +++ b/services/booking-service-net/src/BookingService.Infrastructure/DependencyInjection.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using BookingService.Domain.AggregatesModel.AppointmentAggregate; using BookingService.Domain.AggregatesModel.TherapistAggregate; -using BookingService.Infrastructure.Idempotency; using BookingService.Infrastructure.Repositories; namespace BookingService.Infrastructure; @@ -53,8 +52,8 @@ public static class DependencyInjection services.AddScoped(); services.AddScoped(); - // EN: Register idempotency services / VI: Đăng ký idempotency services - services.AddScoped(); + // EN: Idempotency services not registered — no handler uses IRequestManager + // VI: Idempotency services không được đăng ký — không có handler nào dùng IRequestManager return services; } diff --git a/services/chat-service-net/src/ChatService.API/Controllers/ConversationsController.cs b/services/chat-service-net/src/ChatService.API/Controllers/ConversationsController.cs index 73d93da3..d7b57dca 100644 --- a/services/chat-service-net/src/ChatService.API/Controllers/ConversationsController.cs +++ b/services/chat-service-net/src/ChatService.API/Controllers/ConversationsController.cs @@ -43,11 +43,11 @@ public class ConversationsController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (InvalidOperationException ex) { - return BadRequest(ex.Message); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = ex.Message } }); } } @@ -64,7 +64,7 @@ public class ConversationsController : ControllerBase { var query = new GetConversationsQuery(userId, page, pageSize); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -82,10 +82,10 @@ public class ConversationsController : ControllerBase var conversation = result.Conversations.FirstOrDefault(c => c.Id == conversationId); if (conversation == null) { - return NotFound($"Conversation {conversationId} not found"); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Conversation {conversationId} not found" } }); } - return Ok(conversation); + return Ok(new { success = true, data = conversation }); } } diff --git a/services/chat-service-net/src/ChatService.API/Controllers/KeysController.cs b/services/chat-service-net/src/ChatService.API/Controllers/KeysController.cs index 1e1477fb..3c3ec7f2 100644 --- a/services/chat-service-net/src/ChatService.API/Controllers/KeysController.cs +++ b/services/chat-service-net/src/ChatService.API/Controllers/KeysController.cs @@ -38,7 +38,7 @@ public class KeysController : ControllerBase if (string.IsNullOrEmpty(identityUserId)) { - return Unauthorized("User ID not found in token"); + return Unauthorized(new { success = false, error = new { code = "UNAUTHORIZED", message = "User ID not found in token" } }); } var command = new RegisterUserKeysCommand( @@ -52,7 +52,7 @@ public class KeysController : ControllerBase ); var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -74,11 +74,11 @@ public class KeysController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (InvalidOperationException ex) { - return NotFound(ex.Message); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } } @@ -100,11 +100,11 @@ public class KeysController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (InvalidOperationException ex) { - return NotFound(ex.Message); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } } @@ -122,10 +122,10 @@ public class KeysController : ControllerBase if (result == null) { - return NotFound($"Key bundle not found for user {userId}"); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Key bundle not found for user {userId}" } }); } - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -142,7 +142,7 @@ public class KeysController : ControllerBase if (string.IsNullOrEmpty(identityUserId)) { - return Unauthorized("User ID not found in token"); + return Unauthorized(new { success = false, error = new { code = "UNAUTHORIZED", message = "User ID not found in token" } }); } var query = new GetMyKeyBundleQuery(identityUserId); @@ -150,10 +150,10 @@ public class KeysController : ControllerBase if (result == null) { - return NotFound("Key bundle not registered. Please register your keys first."); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Key bundle not registered. Please register your keys first." } }); } - return Ok(result); + return Ok(new { success = true, data = result }); } } diff --git a/services/chat-service-net/src/ChatService.API/Controllers/MessagesController.cs b/services/chat-service-net/src/ChatService.API/Controllers/MessagesController.cs index 85daed9d..1874ba41 100644 --- a/services/chat-service-net/src/ChatService.API/Controllers/MessagesController.cs +++ b/services/chat-service-net/src/ChatService.API/Controllers/MessagesController.cs @@ -47,11 +47,11 @@ public class MessagesController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (InvalidOperationException ex) { - return NotFound(ex.Message); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } } @@ -74,7 +74,7 @@ public class MessagesController : ControllerBase try { var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (UnauthorizedAccessException ex) { @@ -100,11 +100,11 @@ public class MessagesController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (InvalidOperationException ex) { - return NotFound(ex.Message); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } } } diff --git a/services/membership-service-net/src/MembershipService.API/Controllers/LevelsController.cs b/services/membership-service-net/src/MembershipService.API/Controllers/LevelsController.cs index 38e782de..942f9faa 100644 --- a/services/membership-service-net/src/MembershipService.API/Controllers/LevelsController.cs +++ b/services/membership-service-net/src/MembershipService.API/Controllers/LevelsController.cs @@ -41,7 +41,7 @@ public class LevelsController : ControllerBase { var query = new GetLevelDefinitionsQuery { IncludeInactive = includeInactive }; var levels = await _mediator.Send(query); - return Ok(levels); + return Ok(new { success = true, data = levels }); } /// @@ -62,20 +62,20 @@ public class LevelsController : ControllerBase try { var result = await _mediator.Send(command); - return CreatedAtAction(nameof(GetAll), new { }, result); + return CreatedAtAction(nameof(GetAll), new { }, new { success = true, data = result }); } catch (InvalidOperationException ex) when (ex.Message.Contains("already exists")) { - return Conflict(new { message = ex.Message }); + return Conflict(new { success = false, error = new { code = "CONFLICT", message = ex.Message } }); } catch (ArgumentException ex) { - return BadRequest(new { message = ex.Message }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = ex.Message } }); } catch (Exception ex) { _logger.LogError(ex, "Error creating level definition"); - return StatusCode(500, new { message = "An error occurred while creating level definition" }); + return StatusCode(500, new { success = false, error = new { code = "INTERNAL_ERROR", message = "An error occurred while creating level definition" } }); } } @@ -100,20 +100,20 @@ public class LevelsController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (KeyNotFoundException ex) { - return NotFound(new { message = ex.Message }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } catch (ArgumentException ex) { - return BadRequest(new { message = ex.Message }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = ex.Message } }); } catch (Exception ex) { _logger.LogError(ex, "Error updating level definition {LevelId}", id); - return StatusCode(500, new { message = "An error occurred while updating level definition" }); + return StatusCode(500, new { success = false, error = new { code = "INTERNAL_ERROR", message = "An error occurred while updating level definition" } }); } } @@ -137,16 +137,16 @@ public class LevelsController : ControllerBase } catch (KeyNotFoundException ex) { - return NotFound(new { message = ex.Message }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } catch (ArgumentException ex) { - return BadRequest(new { message = ex.Message }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = ex.Message } }); } catch (Exception ex) { _logger.LogError(ex, "Error deactivating level definition {LevelId}", id); - return StatusCode(500, new { message = "An error occurred while deactivating level definition" }); + return StatusCode(500, new { success = false, error = new { code = "INTERNAL_ERROR", message = "An error occurred while deactivating level definition" } }); } } } diff --git a/services/membership-service-net/src/MembershipService.API/Controllers/MembersController.cs b/services/membership-service-net/src/MembershipService.API/Controllers/MembersController.cs index eabadaf9..ddc8792c 100644 --- a/services/membership-service-net/src/MembershipService.API/Controllers/MembersController.cs +++ b/services/membership-service-net/src/MembershipService.API/Controllers/MembersController.cs @@ -42,9 +42,9 @@ public class MembersController : ControllerBase var member = await _mediator.Send(new GetMemberByIdQuery(id)); if (member == null) { - return NotFound(new { message = $"Member {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Member {id} not found" } }); } - return Ok(member); + return Ok(new { success = true, data = member }); } /// @@ -67,9 +67,9 @@ public class MembersController : ControllerBase var member = await _mediator.Send(new GetMemberByIdQuery(userId.Value)); if (member == null) { - return NotFound(new { message = "Member profile not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Member profile not found" } }); } - return Ok(member); + return Ok(new { success = true, data = member }); } /// @@ -91,7 +91,7 @@ public class MembersController : ControllerBase PageSize = pageSize, SearchTerm = search }); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -109,11 +109,11 @@ public class MembersController : ControllerBase try { var result = await _mediator.Send(command); - return CreatedAtAction(nameof(GetById), new { id = result.MemberId }, result); + return CreatedAtAction(nameof(GetById), new { id = result.MemberId }, new { success = true, data = result }); } catch (InvalidOperationException ex) when (ex.Message.Contains("already exists")) { - return Conflict(new { message = ex.Message }); + return Conflict(new { success = false, error = new { code = "CONFLICT", message = ex.Message } }); } } @@ -136,11 +136,11 @@ public class MembersController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (KeyNotFoundException ex) { - return NotFound(new { message = ex.Message }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } } @@ -163,15 +163,15 @@ public class MembersController : ControllerBase try { var result = await _mediator.Send(command); - return Ok(result); + return Ok(new { success = true, data = result }); } catch (KeyNotFoundException ex) { - return NotFound(new { message = ex.Message }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } }); } catch (ArgumentException ex) { - return BadRequest(new { message = ex.Message }); + return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = ex.Message } }); } } @@ -189,9 +189,9 @@ public class MembersController : ControllerBase var progress = await _mediator.Send(new GetMemberProgressQuery(id)); if (progress == null) { - return NotFound(new { message = $"Member {id} not found" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Member {id} not found" } }); } - return Ok(progress); + return Ok(new { success = true, data = progress }); } /// @@ -208,7 +208,7 @@ public class MembersController : ControllerBase [FromQuery] int pageSize = 20) { var result = await _mediator.Send(new GetExperienceHistoryQuery(id, pageIndex, pageSize)); - return Ok(result); + return Ok(new { success = true, data = result }); } private Guid? GetCurrentUserId() diff --git a/services/mkt-facebook-service-net/src/FacebookService.Infrastructure/DependencyInjection.cs b/services/mkt-facebook-service-net/src/FacebookService.Infrastructure/DependencyInjection.cs index 8f3e5214..c0c00618 100644 --- a/services/mkt-facebook-service-net/src/FacebookService.Infrastructure/DependencyInjection.cs +++ b/services/mkt-facebook-service-net/src/FacebookService.Infrastructure/DependencyInjection.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.DependencyInjection; using FacebookService.Domain.AggregatesModel.CustomerAggregate; using FacebookService.Domain.AggregatesModel.ConversationAggregate; using FacebookService.Domain.AggregatesModel.ChatbotAggregate; -using FacebookService.Infrastructure.Idempotency; using FacebookService.Infrastructure.Repositories; using FacebookService.Infrastructure.ExternalServices; using Polly; @@ -57,8 +56,8 @@ public static class DependencyInjection services.AddScoped(); services.AddScoped(); - // EN: Register idempotency services / VI: Đăng ký idempotency services - services.AddScoped(); + // EN: Idempotency services not registered — no handler uses IRequestManager + // VI: Idempotency services không được đăng ký — không có handler nào dùng IRequestManager // EN: Register Facebook Messenger client / VI: Đăng ký Facebook Messenger client services.AddHttpClient() diff --git a/services/social-service-net/src/SocialService.API/Controllers/AdminController.cs b/services/social-service-net/src/SocialService.API/Controllers/AdminController.cs index 50f96210..82ed5441 100644 --- a/services/social-service-net/src/SocialService.API/Controllers/AdminController.cs +++ b/services/social-service-net/src/SocialService.API/Controllers/AdminController.cs @@ -40,7 +40,7 @@ public class AdminController : ControllerBase { var query = new GetAllRelationshipsQuery(skip, take, status, type); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -56,9 +56,9 @@ public class AdminController : ControllerBase var result = await _mediator.Send(query); if (result == null) - return NotFound(new { error = "Relationship not found" }); - - return Ok(result); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Relationship not found" } }); + + return Ok(new { success = true, data = result }); } /// @@ -74,9 +74,9 @@ public class AdminController : ControllerBase var result = await _mediator.Send(command); if (!result) - return NotFound(new { error = "Relationship not found" }); - - return Ok(new { success = true, message = "Relationship deleted successfully" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Relationship not found" } }); + + return Ok(new { success = true, data = new { message = "Relationship deleted successfully" } }); } #endregion @@ -95,7 +95,7 @@ public class AdminController : ControllerBase { var query = new GetAllBlocksQuery(skip, take); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -111,9 +111,9 @@ public class AdminController : ControllerBase var result = await _mediator.Send(command); if (!result) - return NotFound(new { error = "Block not found" }); - - return Ok(new { success = true, message = "Block deleted successfully" }); + return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Block not found" } }); + + return Ok(new { success = true, data = new { message = "Block deleted successfully" } }); } #endregion @@ -130,7 +130,7 @@ public class AdminController : ControllerBase { var query = new GetSocialStatisticsQuery(); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } #endregion diff --git a/services/social-service-net/src/SocialService.API/Controllers/BlocksController.cs b/services/social-service-net/src/SocialService.API/Controllers/BlocksController.cs index 7559639c..f29d6678 100644 --- a/services/social-service-net/src/SocialService.API/Controllers/BlocksController.cs +++ b/services/social-service-net/src/SocialService.API/Controllers/BlocksController.cs @@ -34,7 +34,7 @@ public class BlocksController : ControllerBase { var command = new BlockUserCommand(request.BlockerId, request.BlockedId, request.Reason); var result = await _mediator.Send(command); - return CreatedAtAction(nameof(GetBlockedUsers), new { userId = request.BlockerId }, result); + return CreatedAtAction(nameof(GetBlockedUsers), new { userId = request.BlockerId }, new { success = true, data = result }); } /// @@ -48,7 +48,7 @@ public class BlocksController : ControllerBase { var command = new UnblockUserCommand(request.BlockerId, request.BlockedId); var result = await _mediator.Send(command); - return Ok(new { success = result }); + return Ok(new { success = true, data = new { unblocked = result } }); } /// @@ -61,7 +61,7 @@ public class BlocksController : ControllerBase { var query = new GetBlockedUsersQuery(userId, skip, take); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } } diff --git a/services/social-service-net/src/SocialService.API/Controllers/RelationshipsController.cs b/services/social-service-net/src/SocialService.API/Controllers/RelationshipsController.cs index 78eadb2f..c3924201 100644 --- a/services/social-service-net/src/SocialService.API/Controllers/RelationshipsController.cs +++ b/services/social-service-net/src/SocialService.API/Controllers/RelationshipsController.cs @@ -36,7 +36,7 @@ public class RelationshipsController : ControllerBase { var query = new GetFriendsQuery(userId, skip, take); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -50,7 +50,7 @@ public class RelationshipsController : ControllerBase { var command = new SendFriendRequestCommand(request.RequesterId, request.AddresseeId); var result = await _mediator.Send(command); - return CreatedAtAction(nameof(GetFriends), new { userId = request.RequesterId }, result); + return CreatedAtAction(nameof(GetFriends), new { userId = request.RequesterId }, new { success = true, data = result }); } /// @@ -65,7 +65,7 @@ public class RelationshipsController : ControllerBase { var command = new RespondToFriendRequestCommand(relationshipId, request.UserId, request.Accept); var result = await _mediator.Send(command); - return Ok(new { success = result }); + return Ok(new { success = true, data = new { accepted = result } }); } /// @@ -78,7 +78,7 @@ public class RelationshipsController : ControllerBase { var query = new GetMutualFriendsQuery(userId1, userId2); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } /// @@ -91,7 +91,7 @@ public class RelationshipsController : ControllerBase { var query = new GetFriendSuggestionsQuery(userId, limit); var result = await _mediator.Send(query); - return Ok(result); + return Ok(new { success = true, data = result }); } #endregion @@ -109,7 +109,7 @@ public class RelationshipsController : ControllerBase { var command = new FollowUserCommand(request.FollowerId, request.FolloweeId); var result = await _mediator.Send(command); - return CreatedAtAction(nameof(GetFriends), new { userId = request.FollowerId }, result); + return CreatedAtAction(nameof(GetFriends), new { userId = request.FollowerId }, new { success = true, data = result }); } /// @@ -123,7 +123,7 @@ public class RelationshipsController : ControllerBase { var command = new UnfollowUserCommand(request.FollowerId, request.FolloweeId); var result = await _mediator.Send(command); - return Ok(new { success = result }); + return Ok(new { success = true, data = new { unfollowed = result } }); } #endregion