diff --git a/ShopAPI/ShopAPI/Controllers/OrderController.cs b/ShopAPI/ShopAPI/Controllers/OrderController.cs index 3760b90..3c80895 100644 --- a/ShopAPI/ShopAPI/Controllers/OrderController.cs +++ b/ShopAPI/ShopAPI/Controllers/OrderController.cs @@ -1,6 +1,88 @@ -namespace ShopAPI.Controllers +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using ShopAPI.DTOs; +using ShopAPI.Models; +using ShopAPI.Services; +using System.Security.Claims; +namespace ShopAPI.Controllers { - public class OrderController + [Authorize] + [ApiController] + [Route("api/[controller]")] + public class OrderController : ControllerBase { + private readonly OrderService _orderService; + + public OrderController(OrderService orderService) + { + _orderService = orderService; + } + + // hilfsmethode - eingeloggten User ID bekommen + private int GetUserId() => int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!); + + // Get api/order (Admin -> alle Bestellungen) + [HttpGet] + [Authorize(Roles = "Admin")] + public async Task GetAll() + { + var orders = await _orderService.GetAllAsync(); + return Ok(orders); + } + + // Get api/order/my (Customer -> meine Bestellungen) + [HttpGet("my")] + public async Task GetMyOrders() + { + var orders = await _orderService.GetMyOrderAsync(GetUserId()); + return Ok(orders); + } + + // Get api/order/{id} + [HttpGet("{id}")] + public async Task GetById(int id) + { + var order = await _orderService.GetByIdAsync(id); + if(order == null) return NotFound(new {message = "Bestellung nicht gefunden"}); + return Ok(order); + } + + [HttpPost] + public async Task Create(OrderDto dto) + { + try + { + var order = await _orderService.CreateAsync(GetUserId(), dto); + return CreatedAtAction(nameof(GetById), new { id = order.Id }, order); + } + catch (Exception ex) + { + return BadRequest(new { message = ex.Message }); + } + } + + [HttpPut("{id}/cancel")] + public async Task Cancel(int id) + { + try + { + var order = await _orderService.CancelAsync(id, GetUserId()); + if (order == null) return NotFound(new { message = "Bestellung nicht gefunden" }); + return Ok(order); + } + catch (Exception ex) + { + return BadRequest(new { message = ex.Message }); + } + } + + [HttpPut("{id}/status")] + [Authorize(Roles = "Admin")] + public async Task UpdateStatus(int id, UpdateStatusDto dto) + { + var order = await _orderService.UpdatesStatusAsync(id, dto.Status); + if (order == null) return NotFound(new { message = "Bestellung nicht gefunden" }); + return Ok(order); + } + } } -} diff --git a/ShopAPI/ShopAPI/Controllers/PaymentController.cs b/ShopAPI/ShopAPI/Controllers/PaymentController.cs index 21854bb..85cbd6f 100644 --- a/ShopAPI/ShopAPI/Controllers/PaymentController.cs +++ b/ShopAPI/ShopAPI/Controllers/PaymentController.cs @@ -1,7 +1,37 @@ -namespace ShopAPI.Controllers +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using ShopAPI.DTOs; +using ShopAPI.Services; +using System.Security.Claims; +namespace ShopAPI.Controllers { - public class PaymentController + [Authorize] + [ApiController] + [Route("api/[controller]")] + public class PaymentController : ControllerBase { + private readonly PaymentService _paymentService; + public PaymentController(PaymentService paymentService) + { + _paymentService = paymentService; + } + + private int GetUserId() => int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!); + + // Post api/payment/pay/{orderId} (Bestellung bezahlen) + [HttpPost("pay/{orderId}")] + public async Task Pay(int orderId, PaymentDto dto) + { + try + { + var payment = await _paymentService.PayAsync(orderId, GetUserId(), dto); + return Ok(payment); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } } } diff --git a/ShopAPI/ShopAPI/DTOs/OrderDto.cs b/ShopAPI/ShopAPI/DTOs/OrderDto.cs index f56a799..3062a48 100644 --- a/ShopAPI/ShopAPI/DTOs/OrderDto.cs +++ b/ShopAPI/ShopAPI/DTOs/OrderDto.cs @@ -1,6 +1,9 @@ -namespace ShopAPI.DTOs +using ShopAPI.Models; + +namespace ShopAPI.DTOs { public class OrderDto { + public List Items { get; set; } = new(); } } diff --git a/ShopAPI/ShopAPI/DTOs/OrderItemDto.cs b/ShopAPI/ShopAPI/DTOs/OrderItemDto.cs new file mode 100644 index 0000000..0c79730 --- /dev/null +++ b/ShopAPI/ShopAPI/DTOs/OrderItemDto.cs @@ -0,0 +1,8 @@ +namespace ShopAPI.DTOs +{ + public class OrderItemDto + { + public int ProductId { get; set; } + public int Quantity { get; set; } + } +} diff --git a/ShopAPI/ShopAPI/DTOs/PaymentDto.cs b/ShopAPI/ShopAPI/DTOs/PaymentDto.cs new file mode 100644 index 0000000..5e2bb10 --- /dev/null +++ b/ShopAPI/ShopAPI/DTOs/PaymentDto.cs @@ -0,0 +1,7 @@ +namespace ShopAPI.DTOs +{ + public class PaymentDto + { + public string Method { get; set; } = string.Empty; // "CreditCard", "PayPal", "Cach". + } +} diff --git a/ShopAPI/ShopAPI/DTOs/UpdateStatusDto.cs b/ShopAPI/ShopAPI/DTOs/UpdateStatusDto.cs new file mode 100644 index 0000000..01216b4 --- /dev/null +++ b/ShopAPI/ShopAPI/DTOs/UpdateStatusDto.cs @@ -0,0 +1,7 @@ +namespace ShopAPI.DTOs +{ + public class UpdateStatusDto + { + public string Status { get; set; } = string.Empty; + } +} diff --git a/ShopAPI/ShopAPI/Program.cs b/ShopAPI/ShopAPI/Program.cs index 37c9a6c..03c8d51 100644 --- a/ShopAPI/ShopAPI/Program.cs +++ b/ShopAPI/ShopAPI/Program.cs @@ -40,13 +40,19 @@ namespace ShopAPI }); builder.Services.AddAuthorization(); - builder.Services.AddControllers(); + builder.Services.AddControllers() + .AddJsonOptions(options => + { + options.JsonSerializerOptions.ReferenceHandler = + System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles; + }); // Hier: jeder benutzer bekommt nur seine Daten , und keine vermischung zwischen Requests builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - + builder.Services.AddScoped(); + builder.Services.AddScoped(); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); diff --git a/ShopAPI/ShopAPI/Services/OrderService.cs b/ShopAPI/ShopAPI/Services/OrderService.cs index 61d5c26..9b76c2f 100644 --- a/ShopAPI/ShopAPI/Services/OrderService.cs +++ b/ShopAPI/ShopAPI/Services/OrderService.cs @@ -1,6 +1,141 @@ -namespace ShopAPI.Services + +using Microsoft.EntityFrameworkCore; +using ShopAPI.Data; +using ShopAPI.DTOs; +using ShopAPI.Models; +namespace ShopAPI.Services { public class OrderService { + public readonly AppDbContext _db; + + public OrderService(AppDbContext db) + { + _db = db; + } + + // Get ALL Orders for a User + public async Task> GetAllAsync() + { + return await _db.Orders + .Include(o => o.User) + .Include(o => o.OrderItems) + .ThenInclude(oi => oi.Product) + .Include(o => o.Payment) + .ToListAsync(); + } + + // Get My Orders (Customer) : Gib mir alle Bestellungen von diesem User + public async Task> GetMyOrderAsync(int userId) + { + return await _db.Orders + .Where(o => o.UserId == userId) + .Include(o => o.OrderItems) + .ThenInclude(oi => oi.Product) + .Include(o => o.Payment) + .ToListAsync(); + } + + // Get By ID : Gib mir Die eine Bestellung mit dieser ID + public async Task GetByIdAsync(int id) + { + return await _db.Orders + .Include(o => o.User) + .Include(o => o.OrderItems) + .ThenInclude(oi => oi.Product) + .Include(o => o.Payment) + .FirstOrDefaultAsync(o => o.Id == id); + } + + // Create Order + public async Task CreateAsync(int userId, OrderDto dto) + { + foreach (var item in dto.Items) + { + var product = await _db.Products.FindAsync(item.ProductId); + if (product == null) + { + throw new Exception($"Produkt {item.ProductId} nciht gefunden"); + } + + if (product.Stock < item.Quantity) + { + throw new Exception($"Nicht genung lager für {product.Name}"); + } + } + + // Bestellung erstellen + var order = new Order + { + UserId = userId, + Createdat = DateTime.UtcNow, + Status = "Pending" + }; + + _db.Orders.Add(order); + await _db.SaveChangesAsync(); + + // OrderItems + decimal total = 0; + foreach (var item in dto.Items) + { + var product = await _db.Products.FindAsync(item.ProductId); + + var orderItem = new OrderItem + { + OrderId = order.Id, + ProductId = item.ProductId, + Quantity = item.Quantity, + UnitPrice = product!.Price + }; + + product.Stock -= item.Quantity; // Lager aktualisieren + + _db.OrderItems.Add(orderItem); + } + + await _db.SaveChangesAsync(); + return await GetByIdAsync(order.Id) ?? order; + } + + // Cancel order + public async Task CancelAsync(int id, int userId) + { + var order = await _db.Orders + .Include(o => o.OrderItems) + .FirstOrDefaultAsync(o => o.Id == id && o.UserId == userId); + + if (order == null) return null; + if (order.Status == "Shipped") + throw new Exception("Versendete Bestellung kann nicht storniert werden"); + + // lager zurückgeben + foreach (var item in order.OrderItems) + { + var product = await _db.Products.FindAsync(item.ProductId); + if(product != null) + { + product.Stock += item.Quantity; + } + } + + order.Status = "Cancelled"; + await _db.SaveChangesAsync(); + return order; + + } + + // Update status (Admin) + public async Task UpdatesStatusAsync(int id, string status) + { + var order = await _db.Orders.FindAsync(id); + if(order == null) return null; + + order.Status = status; + await _db.SaveChangesAsync(); + return order; + } + + } } diff --git a/ShopAPI/ShopAPI/Services/PaymentService.cs b/ShopAPI/ShopAPI/Services/PaymentService.cs new file mode 100644 index 0000000..3b4cb30 --- /dev/null +++ b/ShopAPI/ShopAPI/Services/PaymentService.cs @@ -0,0 +1,53 @@ +using Microsoft.EntityFrameworkCore; +using ShopAPI.Data; +using ShopAPI.DTOs; +using ShopAPI.Models; + +namespace ShopAPI.Services +{ + public class PaymentService + { + public readonly AppDbContext _db; + + public PaymentService(AppDbContext db) + { + _db = db; + } + + // Pay Order + public async Task PayAsync(int orderId, int uderId, PaymentDto dto) + { + var order = await _db.Orders + .Include(o => o.OrderItems) + .FirstOrDefaultAsync(o => o.Id == orderId && o.UserId == uderId); + + if(order == null) + throw new Exception("Order not found"); + if(order.Status == "Cancelled") + throw new Exception("Stornierte Bestellung kann nciht bezahlt werden"); + + // Prüfen ob schon bezahlt + var existing = await _db.Payments.FirstOrDefaultAsync(p => p.OrderId == orderId); + if(existing != null) + throw new Exception("Bestellung wurde bereits bezahlt"); + + // Gesamtbetrag berechnen + var amount = order.OrderItems.Sum(oi => oi.Quantity * oi.UnitPrice); + + var payment = new Payment + { + + OrderId = orderId, + Amount = amount, + Method = dto.Method, + Status = "Paid", + PaidAt = DateTime.UtcNow + }; + + order.Status = "Paid"; + _db.Payments.Add(payment); + await _db.SaveChangesAsync(); + return payment; + } + } +} diff --git a/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.dll b/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.dll index 86ce899..fb1accc 100644 Binary files a/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.dll and b/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.dll differ diff --git a/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.exe b/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.exe index d593a7f..bbbb849 100644 Binary files a/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.exe and b/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.exe differ diff --git a/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.pdb b/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.pdb index f2b0973..688fe53 100644 Binary files a/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.pdb and b/ShopAPI/ShopAPI/bin/Debug/net8.0/ShopAPI.pdb differ diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfo.cs b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfo.cs index 4d14d52..0effa11 100644 --- a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfo.cs +++ b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfo.cs @@ -15,7 +15,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("ShopAPI")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+384d7e0287f40c1ce9e61d3123377dc5917ef6b6")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d297055cc4ab7e3c8a93d2b98beca4da08aba908")] [assembly: System.Reflection.AssemblyProductAttribute("ShopAPI")] [assembly: System.Reflection.AssemblyTitleAttribute("ShopAPI")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfoInputs.cache b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfoInputs.cache index 4f9432b..64228f5 100644 --- a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfoInputs.cache +++ b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.AssemblyInfoInputs.cache @@ -1 +1 @@ -e04359f0bf9216ce6ea4f06fefbd8b64b5dbf14e78bc9a52d8c538097c953810 +4ace5e3dd2679b7f8d6ba402a9a151576ba9bd2f4940c60938bf7c3a5fa4b2f7 diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.csproj.CoreCompileInputs.cache b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.csproj.CoreCompileInputs.cache index 9f60069..ec31e5f 100644 --- a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.csproj.CoreCompileInputs.cache +++ b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -76e1eaf859bca5d672b1fac1789f7abe6bda99f7cc154bb78899e5780554f7a0 +4ae0a6b08c2111e583c69b63b26d342f1e34844cf7b3ca861744608079c9e142 diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.dll b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.dll index 86ce899..fb1accc 100644 Binary files a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.dll and b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.dll differ diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.pdb b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.pdb index f2b0973..688fe53 100644 Binary files a/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.pdb and b/ShopAPI/ShopAPI/obj/Debug/net8.0/ShopAPI.pdb differ diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/apphost.exe b/ShopAPI/ShopAPI/obj/Debug/net8.0/apphost.exe index d593a7f..bbbb849 100644 Binary files a/ShopAPI/ShopAPI/obj/Debug/net8.0/apphost.exe and b/ShopAPI/ShopAPI/obj/Debug/net8.0/apphost.exe differ diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/ref/ShopAPI.dll b/ShopAPI/ShopAPI/obj/Debug/net8.0/ref/ShopAPI.dll index 6437771..09cd9ad 100644 Binary files a/ShopAPI/ShopAPI/obj/Debug/net8.0/ref/ShopAPI.dll and b/ShopAPI/ShopAPI/obj/Debug/net8.0/ref/ShopAPI.dll differ diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/refint/ShopAPI.dll b/ShopAPI/ShopAPI/obj/Debug/net8.0/refint/ShopAPI.dll index 6437771..09cd9ad 100644 Binary files a/ShopAPI/ShopAPI/obj/Debug/net8.0/refint/ShopAPI.dll and b/ShopAPI/ShopAPI/obj/Debug/net8.0/refint/ShopAPI.dll differ diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmcshtml.dswa.cache.json b/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmcshtml.dswa.cache.json index 75fed3d..ebcbae8 100644 --- a/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmcshtml.dswa.cache.json +++ b/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmcshtml.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"UbUS1vR6wGATGwMhgD7zMeswN1vTEJ19YTFurt+qa38=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["qXK9XBukmOKR4bC0/OSWUQmD7NVDnODrTNbVfODoSOA=","RsfaIcSdxUsyxkHT0X7TBDvWAE\u002BekQ7N\u002BCKYPxhpGog=","q4x5tw5ZdEVI3wN3ORljilxzvA3pVT3snlXNH\u002Bh3MZw=","hqxvnAagyda0d6U9WqiUEHNFsi/9qmMo9aedinq8ZQA=","TRUWKVmfrqI3Da5OlFteES1pBI/d\u002Bef88\u002BcbmmwH4mw=","AMewKZACPMF34A9M/c\u002BnjYkuddQPOVXhAdpXf\u002BloS2s=","GrwxjTxxr29ICyUcOpweOHua4V5l\u002BtKseEVsI30NOeU="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"UbUS1vR6wGATGwMhgD7zMeswN1vTEJ19YTFurt+qa38=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["qXK9XBukmOKR4bC0/OSWUQmD7NVDnODrTNbVfODoSOA=","RsfaIcSdxUsyxkHT0X7TBDvWAE\u002BekQ7N\u002BCKYPxhpGog=","mwxpKH5s5WhH59E7QrRxfDY8/18lLYY3KNsyd1uFNcs=","q4x5tw5ZdEVI3wN3ORljilxzvA3pVT3snlXNH\u002Bh3MZw=","hqxvnAagyda0d6U9WqiUEHNFsi/9qmMo9aedinq8ZQA=","TRUWKVmfrqI3Da5OlFteES1pBI/d\u002Bef88\u002BcbmmwH4mw=","AMewKZACPMF34A9M/c\u002BnjYkuddQPOVXhAdpXf\u002BloS2s=","jLjjNkMAcR6ICPvLUJeO8hvccCstVj2PSPKA7Fc04j0="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmrazor.dswa.cache.json b/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmrazor.dswa.cache.json index f398fcd..df6e8bd 100644 --- a/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmrazor.dswa.cache.json +++ b/ShopAPI/ShopAPI/obj/Debug/net8.0/rjsmrazor.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"8Bes/LQh4hq2du9moDLYcP3dWOcm8118awBX2grZ2jA=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["qXK9XBukmOKR4bC0/OSWUQmD7NVDnODrTNbVfODoSOA=","RsfaIcSdxUsyxkHT0X7TBDvWAE\u002BekQ7N\u002BCKYPxhpGog=","q4x5tw5ZdEVI3wN3ORljilxzvA3pVT3snlXNH\u002Bh3MZw=","hqxvnAagyda0d6U9WqiUEHNFsi/9qmMo9aedinq8ZQA=","TRUWKVmfrqI3Da5OlFteES1pBI/d\u002Bef88\u002BcbmmwH4mw=","AMewKZACPMF34A9M/c\u002BnjYkuddQPOVXhAdpXf\u002BloS2s=","GrwxjTxxr29ICyUcOpweOHua4V5l\u002BtKseEVsI30NOeU="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"8Bes/LQh4hq2du9moDLYcP3dWOcm8118awBX2grZ2jA=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["qXK9XBukmOKR4bC0/OSWUQmD7NVDnODrTNbVfODoSOA=","RsfaIcSdxUsyxkHT0X7TBDvWAE\u002BekQ7N\u002BCKYPxhpGog=","mwxpKH5s5WhH59E7QrRxfDY8/18lLYY3KNsyd1uFNcs=","q4x5tw5ZdEVI3wN3ORljilxzvA3pVT3snlXNH\u002Bh3MZw=","hqxvnAagyda0d6U9WqiUEHNFsi/9qmMo9aedinq8ZQA=","TRUWKVmfrqI3Da5OlFteES1pBI/d\u002Bef88\u002BcbmmwH4mw=","AMewKZACPMF34A9M/c\u002BnjYkuddQPOVXhAdpXf\u002BloS2s=","jLjjNkMAcR6ICPvLUJeO8hvccCstVj2PSPKA7Fc04j0="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file