Compare commits

..

10 Commits

Author SHA1 Message Date
Tizian.Breuch
03993211f6 new git
All checks were successful
Branch - test - Build and Push Backend API Docker Image / build-and-push (push) Successful in 1m8s
2025-10-23 14:45:24 +02:00
Tizian.Breuch
f7aa22867c migration 2025-10-23 12:16:22 +02:00
Tizian.Breuch
a27d75767f image build 2025-10-23 11:39:24 +02:00
Tizian.Breuch
2e3f04f0be discount beim checkout überarbeitet 2025-10-10 13:45:28 +02:00
Tizian.Breuch
e915d5a105 order service überarbeitet 2025-10-10 13:35:08 +02:00
Tizian.Breuch
abf4be8547 map to dto 2025-10-10 12:01:03 +02:00
Tizian.Breuch
38acb4bbbb adminaddre 2025-10-10 11:29:20 +02:00
Tizian.Breuch
48617f983a controller 2025-10-10 11:18:33 +02:00
Tizian.Breuch
5f8d3c167c admin adress 2025-10-10 11:12:29 +02:00
Tizian.Breuch
7c2521308f cors 2025-10-09 17:12:55 +02:00
11 changed files with 1684 additions and 25 deletions

View File

@@ -0,0 +1,82 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Webshop.Application;
using Webshop.Application.DTOs.Customers;
using Webshop.Application.Services.Admin.Interfaces;
namespace Webshop.Api.Controllers.Admin
{
[ApiController]
[Route("api/v1/admin/[controller]")]
[Authorize(Roles = "Admin")]
public class AdminAddressesController : ControllerBase
{
private readonly IAdminAddressService _adminAddressService;
public AdminAddressesController(IAdminAddressService adminAddressService)
{
_adminAddressService = adminAddressService;
}
[HttpGet]
public async Task<IActionResult> GetAllUnlinkedAddresses()
{
var result = await _adminAddressService.GetAllUnlinkedAddressesAsync();
return Ok(result.Value);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetAddressById(Guid id)
{
var result = await _adminAddressService.GetAddressByIdAsync(id);
return result.Type switch
{
ServiceResultType.Success => Ok(result.Value),
ServiceResultType.Forbidden => Forbid(),
_ => NotFound(new { Message = result.ErrorMessage })
};
}
[HttpPost] // Route vereinfacht, da keine customerId mehr benötigt wird
public async Task<IActionResult> CreateAddress([FromBody] CreateAddressDto addressDto)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _adminAddressService.CreateAddressAsync(addressDto);
return result.Type switch
{
ServiceResultType.Success => CreatedAtAction(nameof(GetAddressById), new { id = result.Value!.Id }, result.Value),
_ => BadRequest(new { Message = result.ErrorMessage })
};
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateAddress(Guid id, [FromBody] UpdateAddressDto addressDto)
{
if (id != addressDto.Id) return BadRequest("ID in URL und Body stimmen nicht überein.");
if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _adminAddressService.UpdateAddressAsync(addressDto);
return result.Type switch
{
ServiceResultType.Success => NoContent(),
ServiceResultType.Forbidden => Forbid(),
_ => NotFound(new { Message = result.ErrorMessage })
};
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteAddress(Guid id)
{
var result = await _adminAddressService.DeleteAddressAsync(id);
return result.Type switch
{
ServiceResultType.Success => NoContent(),
ServiceResultType.Forbidden => Forbid(),
_ => NotFound(new { Message = result.ErrorMessage })
};
}
}
}

View File

@@ -37,7 +37,7 @@ var builder = WebApplication.CreateBuilder(options);
var allowedOrigins = new string[] var allowedOrigins = new string[]
{ {
"https://webshop.tzbre.dev", "https://shopsolution-frontend.tzbre.dev",
"http://localhost:4200" "http://localhost:4200"
}; };
@@ -156,6 +156,7 @@ builder.Services.AddScoped<IReviewService, ReviewService>();
builder.Services.AddScoped<ICustomerReviewService, CustomerReviewService>(); builder.Services.AddScoped<ICustomerReviewService, CustomerReviewService>();
builder.Services.AddScoped<IAdminReviewService, AdminReviewService>(); builder.Services.AddScoped<IAdminReviewService, AdminReviewService>();
builder.Services.AddScoped<IAdminAnalyticsService, AdminAnalyticsService>(); builder.Services.AddScoped<IAdminAnalyticsService, AdminAnalyticsService>();
builder.Services.AddScoped<IAdminAddressService, AdminAddressService>();
// Controller und API-Infrastruktur // Controller und API-Infrastruktur
builder.Services.AddControllers() builder.Services.AddControllers()
@@ -270,7 +271,7 @@ using (var scope = app.Services.CreateScope())
if (customerUser == null) if (customerUser == null)
{ {
customerUser = new ApplicationUser { UserName = "customer@yourwebshop.com", Email = "customer@yourwebshop.com", EmailConfirmed = true, CreatedDate = DateTimeOffset.UtcNow, LastActive = DateTimeOffset.UtcNow }; customerUser = new ApplicationUser { UserName = "customer@yourwebshop.com", Email = "customer@yourwebshop.com", EmailConfirmed = true, CreatedDate = DateTimeOffset.UtcNow, LastActive = DateTimeOffset.UtcNow };
var createCustomerResult = await userManager.CreateAsync(customerUser, "SecureCustomerPass12-3!"); var createCustomerResult = await userManager.CreateAsync(customerUser, "SecureCustomerPass123!");
if (createCustomerResult.Succeeded) if (createCustomerResult.Succeeded)
{ {
await userManager.AddToRoleAsync(customerUser, "Customer"); await userManager.AddToRoleAsync(customerUser, "Customer");
@@ -326,6 +327,6 @@ app.Run();
//new git

View File

@@ -17,5 +17,10 @@ namespace Webshop.Application.DTOs.Customers
[Required] [Required]
public string Country { get; set; } = string.Empty; public string Country { get; set; } = string.Empty;
public AddressType Type { get; set; } public AddressType Type { get; set; }
[Required]
public string FirstName { get; set; } = string.Empty;
[Required]
public string LastName { get; set; } = string.Empty;
} }
} }

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Webshop.Application;
using Webshop.Application.DTOs.Customers;
using Webshop.Application.Services.Admin.Interfaces;
using Webshop.Domain.Entities;
using Webshop.Domain.Interfaces;
namespace Webshop.Application.Services.Admin
{
public class AdminAddressService : IAdminAddressService
{
private readonly IAddressRepository _addressRepository;
public AdminAddressService(IAddressRepository addressRepository)
{
_addressRepository = addressRepository;
}
public async Task<ServiceResult<IEnumerable<AddressDto>>> GetAllUnlinkedAddressesAsync()
{
var addresses = await _addressRepository.GetAllAsync();
// Filtere nur die Adressen, die KEINEM Kunden zugeordnet sind
var unlinkedAddresses = addresses.Where(a => a.CustomerId == null);
return ServiceResult.Ok(unlinkedAddresses.Select(MapToDto));
}
public async Task<ServiceResult<AddressDto>> GetAddressByIdAsync(Guid addressId)
{
var address = await _addressRepository.GetByIdAsync(addressId);
if (address == null)
{
return ServiceResult.Fail<AddressDto>(ServiceResultType.NotFound, $"Adresse mit ID '{addressId}' nicht gefunden.");
}
// Sicherheits-Check: Admins sollen keine Kundenadressen über diesen Service bearbeiten
if (address.CustomerId != null)
{
return ServiceResult.Fail<AddressDto>(ServiceResultType.Forbidden, "Diese Adresse ist einem Kunden zugeordnet und kann hier nicht verwaltet werden.");
}
return ServiceResult.Ok(MapToDto(address));
}
public async Task<ServiceResult<AddressDto>> CreateAddressAsync(CreateAddressDto addressDto)
{
var newAddress = new Address
{
// WICHTIG: CustomerId wird bewusst auf null gesetzt
CustomerId = null,
// Für generische Adressen brauchen wir FirstName/LastName im Create-DTO
FirstName = addressDto.FirstName, // Annahme: DTO wird erweitert
LastName = addressDto.LastName, // Annahme: DTO wird erweitert
Street = addressDto.Street,
HouseNumber = addressDto.HouseNumber,
City = addressDto.City,
PostalCode = addressDto.PostalCode,
Country = addressDto.Country,
Type = addressDto.Type
};
await _addressRepository.AddAsync(newAddress);
return ServiceResult.Ok(MapToDto(newAddress));
}
public async Task<ServiceResult> UpdateAddressAsync(UpdateAddressDto addressDto)
{
var address = await _addressRepository.GetByIdAsync(addressDto.Id);
if (address == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Adresse nicht gefunden.");
// Sicherheits-Check
if (address.CustomerId != null)
{
return ServiceResult.Fail(ServiceResultType.Forbidden, "Kundenadressen können hier nicht bearbeitet werden.");
}
address.FirstName = addressDto.FirstName;
address.LastName = addressDto.LastName;
address.Street = addressDto.Street;
// ... (restliches Mapping)
await _addressRepository.UpdateAsync(address);
return ServiceResult.Ok();
}
public async Task<ServiceResult> DeleteAddressAsync(Guid addressId)
{
var address = await _addressRepository.GetByIdAsync(addressId);
if (address == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Adresse nicht gefunden.");
// Sicherheits-Check
if (address.CustomerId != null)
{
return ServiceResult.Fail(ServiceResultType.Forbidden, "Kundenadressen können hier nicht gelöscht werden.");
}
// Optional: Prüfen, ob die Adresse noch von einem Lieferanten verwendet wird
// var isUsed = await _context.Suppliers.AnyAsync(s => s.AddressId == addressId);
// if(isUsed) return ServiceResult.Fail(ServiceResultType.Conflict, "Adresse wird noch von einem Lieferanten verwendet.");
await _addressRepository.DeleteAsync(addressId);
return ServiceResult.Ok();
}
// MapToDto bleibt gleich
private AddressDto MapToDto(Address address)
{
return new AddressDto
{
Id = address.Id,
FirstName = address.FirstName,
LastName = address.LastName,
Street = address.Street,
HouseNumber = address.HouseNumber,
City = address.City,
PostalCode = address.PostalCode,
Country = address.Country,
Type = address.Type
};
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Webshop.Application;
using Webshop.Application.DTOs.Customers; // Wir können die DTOs wiederverwenden
namespace Webshop.Application.Services.Admin.Interfaces
{
public interface IAdminAddressService
{
// Ruft ALLE Adressen ab, die NICHT an einen Kunden gebunden sind
Task<ServiceResult<IEnumerable<AddressDto>>> GetAllUnlinkedAddressesAsync();
Task<ServiceResult<AddressDto>> GetAddressByIdAsync(Guid addressId);
// Erstellt eine neue, "herrenlose" Adresse
Task<ServiceResult<AddressDto>> CreateAddressAsync(CreateAddressDto addressDto);
Task<ServiceResult> UpdateAddressAsync(UpdateAddressDto addressDto);
Task<ServiceResult> DeleteAddressAsync(Guid addressId);
}
}

View File

@@ -1,4 +1,5 @@
// src/Webshop.Application/Services/Customers/CheckoutService.cs // /src/Webshop.Application/Services/Customers/CheckoutService.cs
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -42,7 +43,7 @@ namespace Webshop.Application.Services.Customers
await using var transaction = await _context.Database.BeginTransactionAsync(); await using var transaction = await _context.Database.BeginTransactionAsync();
try try
{ {
// 1. Validierung von Kunde, Adressen und Methoden // --- 1. Validierung von Kunde, Adressen und Methoden ---
var customer = await _customerRepository.GetByUserIdAsync(userId!); var customer = await _customerRepository.GetByUserIdAsync(userId!);
if (customer == null) if (customer == null)
return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.Unauthorized, "Kundenprofil nicht gefunden."); return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.Unauthorized, "Kundenprofil nicht gefunden.");
@@ -61,7 +62,7 @@ namespace Webshop.Application.Services.Customers
if (paymentMethod == null || !paymentMethod.IsActive) if (paymentMethod == null || !paymentMethod.IsActive)
return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.InvalidInput, "Ungültige oder inaktive Zahlungsmethode."); return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.InvalidInput, "Ungültige oder inaktive Zahlungsmethode.");
// 2. Artikel verarbeiten und Lagerbestand prüfen // --- 2. Artikel verarbeiten und Lagerbestand prüfen ---
var orderItems = new List<OrderItem>(); var orderItems = new List<OrderItem>();
var productIds = orderDto.Items.Select(i => i.ProductId).ToList(); var productIds = orderDto.Items.Select(i => i.ProductId).ToList();
var products = await _context.Products.Where(p => productIds.Contains(p.Id)).ToListAsync(); var products = await _context.Products.Where(p => productIds.Contains(p.Id)).ToListAsync();
@@ -97,18 +98,43 @@ namespace Webshop.Application.Services.Customers
itemsTotal += orderItem.TotalPrice; itemsTotal += orderItem.TotalPrice;
} }
// 3. Preise, Rabatte, Steuern und Gesamtbetrag berechnen // --- 3. Preise, Rabatte, Steuern und Gesamtbetrag berechnen ---
var discountResult = await _discountService.CalculateDiscountAsync(orderItems, orderDto.CouponCode); decimal discountAmount = 0;
decimal discountAmount = discountResult.TotalDiscountAmount; var discountResult = new DiscountCalculationResult();
if (!string.IsNullOrWhiteSpace(orderDto.CouponCode))
{
discountResult = await _discountService.CalculateDiscountAsync(orderItems, orderDto.CouponCode);
discountAmount = discountResult.TotalDiscountAmount;
if (discountAmount <= 0)
{
await transaction.RollbackAsync();
return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.InvalidInput, "Der angegebene Gutscheincode ist ungültig, abgelaufen oder nicht auf die Produkte im Warenkorb anwendbar.");
}
if (discountResult.AppliedDiscountIds.Count > 1)
{
await transaction.RollbackAsync();
return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.Failure, "Es können nicht mehrere Rabatte gleichzeitig angewendet werden.");
}
}
decimal shippingCost = shippingMethod.BaseCost; decimal shippingCost = shippingMethod.BaseCost;
decimal subTotal = itemsTotal + shippingCost - discountAmount; decimal subTotalBeforeDiscount = itemsTotal + shippingCost;
if (subTotal < 0) subTotal = 0;
if (discountAmount > subTotalBeforeDiscount)
{
discountAmount = subTotalBeforeDiscount;
}
decimal subTotalAfterDiscount = subTotalBeforeDiscount - discountAmount;
decimal taxRate = await _settingService.GetSettingValueAsync<decimal>("GlobalTaxRate", 0.19m); decimal taxRate = await _settingService.GetSettingValueAsync<decimal>("GlobalTaxRate", 0.19m);
decimal taxAmount = subTotal * taxRate; decimal taxAmount = subTotalAfterDiscount * taxRate;
decimal orderTotal = subTotal + taxAmount; decimal orderTotal = subTotalAfterDiscount + taxAmount;
// 4. Bestellung erstellen // --- 4. Bestellung erstellen ---
var newOrder = new Order var newOrder = new Order
{ {
CustomerId = customer.Id, CustomerId = customer.Id,
@@ -129,7 +155,7 @@ namespace Webshop.Application.Services.Customers
}; };
await _orderRepository.AddAsync(newOrder); await _orderRepository.AddAsync(newOrder);
// 5. Rabattnutzung erhöhen // --- 5. Rabattnutzung erhöhen ---
if (discountResult.AppliedDiscountIds.Any()) if (discountResult.AppliedDiscountIds.Any())
{ {
var appliedDiscounts = await _context.Discounts.Where(d => discountResult.AppliedDiscountIds.Contains(d.Id)).ToListAsync(); var appliedDiscounts = await _context.Discounts.Where(d => discountResult.AppliedDiscountIds.Contains(d.Id)).ToListAsync();
@@ -139,14 +165,16 @@ namespace Webshop.Application.Services.Customers
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
await transaction.CommitAsync(); await transaction.CommitAsync();
// 6. Erfolgreiche Antwort erstellen // --- 6. Erfolgreiche Antwort erstellen ---
var createdOrder = await _orderRepository.GetByIdAsync(newOrder.Id); var createdOrder = await _orderRepository.GetByIdAsync(newOrder.Id);
return ServiceResult.Ok(MapToOrderDetailDto(createdOrder!)); return ServiceResult.Ok(MapToOrderDetailDto(createdOrder!));
} }
catch (Exception ex) catch (Exception ex)
{ {
await transaction.RollbackAsync(); await transaction.RollbackAsync();
return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.Failure, $"Ein unerwarteter Fehler ist aufgetreten: {ex.Message}"); // Log the full exception for debugging purposes
// _logger.LogError(ex, "An unexpected error occurred in CreateOrderAsync.");
return ServiceResult.Fail<OrderDetailDto>(ServiceResultType.Failure, "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.");
} }
} }
@@ -158,7 +186,7 @@ namespace Webshop.Application.Services.Customers
OrderNumber = order.OrderNumber, OrderNumber = order.OrderNumber,
OrderDate = order.OrderDate, OrderDate = order.OrderDate,
CustomerId = order.CustomerId, CustomerId = order.CustomerId,
Status = Enum.Parse<OrderStatus>(order.OrderStatus), Status = Enum.TryParse<OrderStatus>(order.OrderStatus, true, out var os) ? os : OrderStatus.Pending,
TotalAmount = order.OrderTotal, TotalAmount = order.OrderTotal,
ShippingAddress = new AddressDto ShippingAddress = new AddressDto
{ {
@@ -184,8 +212,8 @@ namespace Webshop.Application.Services.Customers
Country = order.BillingAddress.Country, Country = order.BillingAddress.Country,
Type = order.BillingAddress.Type Type = order.BillingAddress.Type
}, },
PaymentMethod = order.PaymentMethod, PaymentMethod = order.PaymentMethodInfo?.Name,
PaymentStatus = Enum.Parse<PaymentStatus>(order.PaymentStatus), PaymentStatus = Enum.TryParse<PaymentStatus>(order.PaymentStatus, true, out var ps) ? ps : PaymentStatus.Pending,
ShippingTrackingNumber = order.ShippingTrackingNumber, ShippingTrackingNumber = order.ShippingTrackingNumber,
ShippedDate = order.ShippedDate, ShippedDate = order.ShippedDate,
DeliveredDate = order.DeliveredDate, DeliveredDate = order.DeliveredDate,

View File

@@ -30,13 +30,15 @@ namespace Webshop.Application.Services.Customers
var customer = await _customerRepository.GetByUserIdAsync(userId); var customer = await _customerRepository.GetByUserIdAsync(userId);
if (customer == null) if (customer == null)
{ {
// A valid user might not have a customer profile yet. Return empty list.
return ServiceResult.Ok<IEnumerable<OrderSummaryDto>>(new List<OrderSummaryDto>()); return ServiceResult.Ok<IEnumerable<OrderSummaryDto>>(new List<OrderSummaryDto>());
} }
var orders = await _context.Orders var orders = await _context.Orders
.Where(o => o.CustomerId == customer.Id) .Where(o => o.CustomerId == customer.Id)
.OrderByDescending(o => o.OrderDate) .OrderByDescending(o => o.OrderDate)
// +++ KORREKTUR: Verkn<6B>pfte Entit<69>ten explizit laden +++
.Include(o => o.ShippingMethodInfo)
.Include(o => o.PaymentMethodInfo)
.ToListAsync(); .ToListAsync();
var dtos = orders.Select(o => new OrderSummaryDto var dtos = orders.Select(o => new OrderSummaryDto
@@ -47,7 +49,10 @@ namespace Webshop.Application.Services.Customers
CustomerName = $"{customer.FirstName} {customer.LastName}", CustomerName = $"{customer.FirstName} {customer.LastName}",
TotalAmount = o.OrderTotal, TotalAmount = o.OrderTotal,
Status = Enum.TryParse<OrderStatus>(o.OrderStatus, true, out var os) ? os : OrderStatus.Pending, Status = Enum.TryParse<OrderStatus>(o.OrderStatus, true, out var os) ? os : OrderStatus.Pending,
PaymentStatus = Enum.TryParse<PaymentStatus>(o.PaymentStatus, true, out var ps) ? ps : PaymentStatus.Pending PaymentStatus = Enum.TryParse<PaymentStatus>(o.PaymentStatus, true, out var ps) ? ps : PaymentStatus.Pending,
// +++ KORREKTUR: Daten aus den geladenen Entit<69>ten zuweisen +++
ShippingMethodName = o.ShippingMethodInfo?.Name,
PaymentMethodName = o.PaymentMethodInfo?.Name
}).ToList(); }).ToList();
return ServiceResult.Ok<IEnumerable<OrderSummaryDto>>(dtos); return ServiceResult.Ok<IEnumerable<OrderSummaryDto>>(dtos);
@@ -65,6 +70,9 @@ namespace Webshop.Application.Services.Customers
.Include(o => o.BillingAddress) .Include(o => o.BillingAddress)
.Include(o => o.ShippingAddress) .Include(o => o.ShippingAddress)
.Include(o => o.OrderItems) .Include(o => o.OrderItems)
// +++ KORREKTUR: Verkn<6B>pfte Entit<69>ten explizit laden +++
.Include(o => o.ShippingMethodInfo)
.Include(o => o.PaymentMethodInfo)
.FirstOrDefaultAsync(o => o.Id == orderId); .FirstOrDefaultAsync(o => o.Id == orderId);
if (order == null) if (order == null)
@@ -82,6 +90,8 @@ namespace Webshop.Application.Services.Customers
private OrderDetailDto MapToOrderDetailDto(Order order) private OrderDetailDto MapToOrderDetailDto(Order order)
{ {
// Die `MapToDto`-Methode muss die neuen Daten ebenfalls verwenden.
// Die `PaymentMethod`-Eigenschaft in `OrderDetailDto` scheint den Namen zu erwarten.
return new OrderDetailDto return new OrderDetailDto
{ {
Id = order.Id, Id = order.Id,
@@ -98,7 +108,9 @@ namespace Webshop.Application.Services.Customers
City = order.ShippingAddress.City, City = order.ShippingAddress.City,
PostalCode = order.ShippingAddress.PostalCode, PostalCode = order.ShippingAddress.PostalCode,
Country = order.ShippingAddress.Country, Country = order.ShippingAddress.Country,
Type = order.ShippingAddress.Type Type = order.ShippingAddress.Type,
FirstName = order.ShippingAddress.FirstName,
LastName = order.ShippingAddress.LastName
}, },
BillingAddress = new AddressDto BillingAddress = new AddressDto
{ {
@@ -108,9 +120,12 @@ namespace Webshop.Application.Services.Customers
City = order.BillingAddress.City, City = order.BillingAddress.City,
PostalCode = order.BillingAddress.PostalCode, PostalCode = order.BillingAddress.PostalCode,
Country = order.BillingAddress.Country, Country = order.BillingAddress.Country,
Type = order.BillingAddress.Type Type = order.BillingAddress.Type,
FirstName = order.BillingAddress.FirstName,
LastName = order.BillingAddress.LastName
}, },
PaymentMethod = order.PaymentMethod, // +++ KORREKTUR: Den Namen aus der geladenen Entit<69>t verwenden +++
PaymentMethod = order.PaymentMethodInfo?.Name,
PaymentStatus = Enum.TryParse<PaymentStatus>(order.PaymentStatus, true, out var ps) ? ps : PaymentStatus.Pending, PaymentStatus = Enum.TryParse<PaymentStatus>(order.PaymentStatus, true, out var ps) ? ps : PaymentStatus.Pending,
ShippingTrackingNumber = order.ShippingTrackingNumber, ShippingTrackingNumber = order.ShippingTrackingNumber,
ShippedDate = order.ShippedDate, ShippedDate = order.ShippedDate,

View File

@@ -13,5 +13,6 @@ namespace Webshop.Domain.Interfaces
Task AddAsync(Address address); Task AddAsync(Address address);
Task UpdateAsync(Address address); Task UpdateAsync(Address address);
Task DeleteAsync(Guid id); Task DeleteAsync(Guid id);
Task<IEnumerable<Address>> GetAllAsync();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Webshop.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@@ -52,5 +52,9 @@ namespace Webshop.Infrastructure.Repositories
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
} }
} }
public async Task<IEnumerable<Address>> GetAllAsync()
{
return await _context.Addresses.ToListAsync();
}
} }
} }