shop info
This commit is contained in:
40
Webshop.Api/Controllers/Admin/AdminShopInfoController.cs
Normal file
40
Webshop.Api/Controllers/Admin/AdminShopInfoController.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// src/Webshop.Api/Controllers/Admin/AdminShopInfoController.cs
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Application.DTOs.Shop;
|
||||||
|
using Webshop.Application.Services.Admin;
|
||||||
|
|
||||||
|
namespace Webshop.Api.Controllers.Admin
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/v1/admin/[controller]")]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public class AdminShopInfoController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IAdminShopInfoService _shopInfoService;
|
||||||
|
|
||||||
|
public AdminShopInfoController(IAdminShopInfoService shopInfoService)
|
||||||
|
{
|
||||||
|
_shopInfoService = shopInfoService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<AdminShopInfoDto>> GetShopInfo()
|
||||||
|
{
|
||||||
|
var info = await _shopInfoService.GetShopInfoAsync();
|
||||||
|
return Ok(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut]
|
||||||
|
public async Task<IActionResult> UpdateShopInfo([FromBody] AdminShopInfoDto shopInfoDto)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
await _shopInfoService.UpdateShopInfoAsync(shopInfoDto);
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Webshop.Api/Controllers/Public/ShopInfoController.cs
Normal file
29
Webshop.Api/Controllers/Public/ShopInfoController.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// src/Webshop.Api/Controllers/Public/ShopInfoController.cs
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Application.DTOs.Shop;
|
||||||
|
using Webshop.Application.Services.Public;
|
||||||
|
|
||||||
|
namespace Webshop.Api.Controllers.Public
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/v1/public/[]controller")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class ShopInfoController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IShopInfoService _shopInfoService;
|
||||||
|
|
||||||
|
public ShopInfoController(IShopInfoService shopInfoService)
|
||||||
|
{
|
||||||
|
_shopInfoService = shopInfoService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PublicShopInfoDto>> GetPublicShopInfo()
|
||||||
|
{
|
||||||
|
var info = await _shopInfoService.GetPublicShopInfoAsync();
|
||||||
|
return Ok(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,6 +105,7 @@ builder.Services.AddScoped<IAddressRepository, AddressRepository>();
|
|||||||
builder.Services.AddScoped<IDiscountRepository, DiscountRepository>();
|
builder.Services.AddScoped<IDiscountRepository, DiscountRepository>();
|
||||||
builder.Services.AddScoped<IReviewRepository, ReviewRepository>();
|
builder.Services.AddScoped<IReviewRepository, ReviewRepository>();
|
||||||
builder.Services.AddScoped<ISettingRepository, SettingRepository>();
|
builder.Services.AddScoped<ISettingRepository, SettingRepository>();
|
||||||
|
builder.Services.AddScoped<IShopInfoRepository, ShopInfoRepository>();
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
builder.Services.AddScoped<IAuthService, AuthService>();
|
builder.Services.AddScoped<IAuthService, AuthService>();
|
||||||
@@ -125,6 +126,8 @@ builder.Services.AddScoped<IOrderService, OrderService>();
|
|||||||
builder.Services.AddScoped<IAddressService, AddressService>();
|
builder.Services.AddScoped<IAddressService, AddressService>();
|
||||||
builder.Services.AddScoped<ICheckoutService, CheckoutService>();
|
builder.Services.AddScoped<ICheckoutService, CheckoutService>();
|
||||||
builder.Services.AddScoped<IReviewService, ReviewService>();
|
builder.Services.AddScoped<IReviewService, ReviewService>();
|
||||||
|
builder.Services.AddScoped<IAdminShopInfoService, AdminShopInfoService>();
|
||||||
|
builder.Services.AddScoped<IShopInfoService, ShopInfoService>();
|
||||||
|
|
||||||
// Controller und API-Infrastruktur
|
// Controller und API-Infrastruktur
|
||||||
builder.Services.AddControllers()
|
builder.Services.AddControllers()
|
||||||
|
|||||||
47
Webshop.Application/DTOs/Shop/AdminShopInfoDto.cs
Normal file
47
Webshop.Application/DTOs/Shop/AdminShopInfoDto.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// src/Webshop.Application/DTOs/Admin/AdminShopInfoDto.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Webshop.Application.DTOs.Shop
|
||||||
|
{
|
||||||
|
public class AdminShopInfoDto
|
||||||
|
{
|
||||||
|
[Required, MaxLength(255)]
|
||||||
|
public string ShopName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string? Slogan { get; set; }
|
||||||
|
|
||||||
|
[Required, EmailAddress, MaxLength(255)]
|
||||||
|
public string ContactEmail { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Phone, MaxLength(50)]
|
||||||
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? Street { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(20)]
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(50)]
|
||||||
|
public string? VatNumber { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string? CompanyRegistrationNumber { get; set; }
|
||||||
|
|
||||||
|
[Url, MaxLength(255)]
|
||||||
|
public string? FacebookUrl { get; set; }
|
||||||
|
|
||||||
|
[Url, MaxLength(255)]
|
||||||
|
public string? InstagramUrl { get; set; }
|
||||||
|
|
||||||
|
[Url, MaxLength(255)]
|
||||||
|
public string? TwitterUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Webshop.Application/DTOs/Shop/PublicShopInfoDto.cs
Normal file
19
Webshop.Application/DTOs/Shop/PublicShopInfoDto.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// src/Webshop.Application/DTOs/Shop/PublicShopInfoDto.cs
|
||||||
|
namespace Webshop.Application.DTOs.Shop
|
||||||
|
{
|
||||||
|
// Dieses DTO enthält nur die Informationen, die ein normaler Kunde sehen soll.
|
||||||
|
public class PublicShopInfoDto
|
||||||
|
{
|
||||||
|
public string ShopName { get; set; } = string.Empty;
|
||||||
|
public string? Slogan { get; set; }
|
||||||
|
public string ContactEmail { get; set; } = string.Empty;
|
||||||
|
public string? PhoneNumber { get; set; }
|
||||||
|
public string? Street { get; set; }
|
||||||
|
public string? City { get; set; }
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
public string? Country { get; set; }
|
||||||
|
public string? FacebookUrl { get; set; }
|
||||||
|
public string? InstagramUrl { get; set; }
|
||||||
|
public string? TwitterUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Webshop.Application/Services/Admin/AdminShopInfoService.cs
Normal file
74
Webshop.Application/Services/Admin/AdminShopInfoService.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// src/Webshop.Application/Services/Admin/AdminShopInfoService.cs
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Application.DTOs.Shop;
|
||||||
|
using Webshop.Domain.Entities;
|
||||||
|
using Webshop.Domain.Interfaces;
|
||||||
|
|
||||||
|
namespace Webshop.Application.Services.Admin
|
||||||
|
{
|
||||||
|
public class AdminShopInfoService : IAdminShopInfoService
|
||||||
|
{
|
||||||
|
private readonly IShopInfoRepository _shopInfoRepository;
|
||||||
|
|
||||||
|
public AdminShopInfoService(IShopInfoRepository shopInfoRepository)
|
||||||
|
{
|
||||||
|
_shopInfoRepository = shopInfoRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AdminShopInfoDto> GetShopInfoAsync()
|
||||||
|
{
|
||||||
|
var shopInfo = await _shopInfoRepository.GetAsync();
|
||||||
|
|
||||||
|
if (shopInfo == null)
|
||||||
|
{
|
||||||
|
// Erstelle einen Standardeintrag, falls keiner existiert
|
||||||
|
shopInfo = new ShopInfo { Id = Guid.NewGuid(), ShopName = "Mein Webshop", ContactEmail = "admin@example.com" };
|
||||||
|
await _shopInfoRepository.AddAsync(shopInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AdminShopInfoDto
|
||||||
|
{
|
||||||
|
ShopName = shopInfo.ShopName,
|
||||||
|
Slogan = shopInfo.Slogan,
|
||||||
|
ContactEmail = shopInfo.ContactEmail,
|
||||||
|
PhoneNumber = shopInfo.PhoneNumber,
|
||||||
|
Street = shopInfo.Street,
|
||||||
|
City = shopInfo.City,
|
||||||
|
PostalCode = shopInfo.PostalCode,
|
||||||
|
Country = shopInfo.Country,
|
||||||
|
VatNumber = shopInfo.VatNumber,
|
||||||
|
CompanyRegistrationNumber = shopInfo.CompanyRegistrationNumber,
|
||||||
|
FacebookUrl = shopInfo.FacebookUrl,
|
||||||
|
InstagramUrl = shopInfo.InstagramUrl,
|
||||||
|
TwitterUrl = shopInfo.TwitterUrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateShopInfoAsync(AdminShopInfoDto shopInfoDto)
|
||||||
|
{
|
||||||
|
var shopInfo = await _shopInfoRepository.GetAsync();
|
||||||
|
if (shopInfo == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("ShopInfo entity does not exist and cannot be updated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mappe die Werte vom DTO auf die Entität
|
||||||
|
shopInfo.ShopName = shopInfoDto.ShopName;
|
||||||
|
shopInfo.Slogan = shopInfoDto.Slogan;
|
||||||
|
shopInfo.ContactEmail = shopInfoDto.ContactEmail;
|
||||||
|
shopInfo.PhoneNumber = shopInfoDto.PhoneNumber;
|
||||||
|
shopInfo.Street = shopInfoDto.Street;
|
||||||
|
shopInfo.City = shopInfoDto.City;
|
||||||
|
shopInfo.PostalCode = shopInfoDto.PostalCode;
|
||||||
|
shopInfo.Country = shopInfoDto.Country;
|
||||||
|
shopInfo.VatNumber = shopInfoDto.VatNumber;
|
||||||
|
shopInfo.CompanyRegistrationNumber = shopInfoDto.CompanyRegistrationNumber;
|
||||||
|
shopInfo.FacebookUrl = shopInfoDto.FacebookUrl;
|
||||||
|
shopInfo.InstagramUrl = shopInfoDto.InstagramUrl;
|
||||||
|
shopInfo.TwitterUrl = shopInfoDto.TwitterUrl;
|
||||||
|
|
||||||
|
await _shopInfoRepository.UpdateAsync(shopInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// src/Webshop.Application/Services/Admin/IAdminShopInfoService.cs
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Application.DTOs.Shop;
|
||||||
|
|
||||||
|
namespace Webshop.Application.Services.Admin
|
||||||
|
{
|
||||||
|
public interface IAdminShopInfoService
|
||||||
|
{
|
||||||
|
Task<AdminShopInfoDto> GetShopInfoAsync();
|
||||||
|
Task UpdateShopInfoAsync(AdminShopInfoDto shopInfoDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// src/Webshop.Application/Services/Public/IShopInfoService.cs
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Application.DTOs.Shop;
|
||||||
|
|
||||||
|
namespace Webshop.Application.Services.Public
|
||||||
|
{
|
||||||
|
public interface IShopInfoService
|
||||||
|
{
|
||||||
|
Task<PublicShopInfoDto> GetPublicShopInfoAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
43
Webshop.Application/Services/Public/ShopInfoService.cs
Normal file
43
Webshop.Application/Services/Public/ShopInfoService.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// src/Webshop.Application/Services/Public/ShopInfoService.cs
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Application.DTOs.Shop;
|
||||||
|
using Webshop.Domain.Interfaces;
|
||||||
|
|
||||||
|
namespace Webshop.Application.Services.Public
|
||||||
|
{
|
||||||
|
public class ShopInfoService : IShopInfoService
|
||||||
|
{
|
||||||
|
private readonly IShopInfoRepository _shopInfoRepository;
|
||||||
|
|
||||||
|
public ShopInfoService(IShopInfoRepository shopInfoRepository)
|
||||||
|
{
|
||||||
|
_shopInfoRepository = shopInfoRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PublicShopInfoDto> GetPublicShopInfoAsync()
|
||||||
|
{
|
||||||
|
var shopInfo = await _shopInfoRepository.GetAsync();
|
||||||
|
|
||||||
|
if (shopInfo == null)
|
||||||
|
{
|
||||||
|
// Gib Standardwerte zurück, wenn nichts konfiguriert ist
|
||||||
|
return new PublicShopInfoDto { ShopName = "Webshop" };
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PublicShopInfoDto
|
||||||
|
{
|
||||||
|
ShopName = shopInfo.ShopName,
|
||||||
|
Slogan = shopInfo.Slogan,
|
||||||
|
ContactEmail = shopInfo.ContactEmail,
|
||||||
|
PhoneNumber = shopInfo.PhoneNumber,
|
||||||
|
Street = shopInfo.Street,
|
||||||
|
City = shopInfo.City,
|
||||||
|
PostalCode = shopInfo.PostalCode,
|
||||||
|
Country = shopInfo.Country,
|
||||||
|
FacebookUrl = shopInfo.FacebookUrl,
|
||||||
|
InstagramUrl = shopInfo.InstagramUrl,
|
||||||
|
TwitterUrl = shopInfo.TwitterUrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Webshop.Domain/Entities/ShopInfo.cs
Normal file
58
Webshop.Domain/Entities/ShopInfo.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// src/Webshop.Domain/Entities/ShopInfo.cs
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Webshop.Domain.Entities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enthält die zentralen Stammdaten des Shops.
|
||||||
|
/// Es sollte nur eine einzige Zeile in dieser Tabelle existieren.
|
||||||
|
/// </summary>
|
||||||
|
public class ShopInfo
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
[Required, MaxLength(255)]
|
||||||
|
public string ShopName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string? Slogan { get; set; } // << NEU: Für Marketing >>
|
||||||
|
|
||||||
|
[Required, MaxLength(255)]
|
||||||
|
public string ContactEmail { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[MaxLength(50)]
|
||||||
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
||||||
|
// --- Firmenadresse ---
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? Street { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(20)]
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
// --- Rechtliches ---
|
||||||
|
[MaxLength(50)]
|
||||||
|
public string? VatNumber { get; set; } // Umsatzsteuer-ID
|
||||||
|
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string? CompanyRegistrationNumber { get; set; } // Handelsregisternummer
|
||||||
|
|
||||||
|
// --- Social Media & Links ---
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? FacebookUrl { get; set; } // << NEU >>
|
||||||
|
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? InstagramUrl { get; set; } // << NEU >>
|
||||||
|
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? TwitterUrl { get; set; } // << NEU >>
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Webshop.Domain/Interfaces/IShopInfoRepository.cs
Normal file
13
Webshop.Domain/Interfaces/IShopInfoRepository.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// src/Webshop.Domain/Interfaces/IShopInfoRepository.cs
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Webshop.Domain.Interfaces
|
||||||
|
{
|
||||||
|
public interface IShopInfoRepository
|
||||||
|
{
|
||||||
|
Task<ShopInfo?> GetAsync(); // Ruft die (einzige) ShopInfo-Zeile ab
|
||||||
|
Task UpdateAsync(ShopInfo shopInfo);
|
||||||
|
Task AddAsync(ShopInfo shopInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ namespace Webshop.Infrastructure.Data
|
|||||||
public DbSet<ProductDiscount> ProductDiscounts { get; set; } = default!;
|
public DbSet<ProductDiscount> ProductDiscounts { get; set; } = default!;
|
||||||
public DbSet<CategorieDiscount> categorieDiscounts { get; set; } = default!;
|
public DbSet<CategorieDiscount> categorieDiscounts { get; set; } = default!;
|
||||||
public DbSet<ProductImage> ProductImages { get; set; } = default!;
|
public DbSet<ProductImage> ProductImages { get; set; } = default!;
|
||||||
|
public DbSet<ShopInfo> ShopInfos { get; set; } = default!;
|
||||||
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
|||||||
37
Webshop.Infrastructure/Repositories/ShopInfoRepository.cs
Normal file
37
Webshop.Infrastructure/Repositories/ShopInfoRepository.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// src/Webshop.Infrastructure/Repositories/ShopInfoRepository.cs
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webshop.Domain.Entities;
|
||||||
|
using Webshop.Domain.Interfaces;
|
||||||
|
using Webshop.Infrastructure.Data;
|
||||||
|
|
||||||
|
namespace Webshop.Infrastructure.Repositories
|
||||||
|
{
|
||||||
|
public class ShopInfoRepository : IShopInfoRepository
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
|
public ShopInfoRepository(ApplicationDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ShopInfo?> GetAsync()
|
||||||
|
{
|
||||||
|
// Es sollte immer nur eine Zeile geben, also nehmen wir die erste
|
||||||
|
return await _context.ShopInfos.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateAsync(ShopInfo shopInfo)
|
||||||
|
{
|
||||||
|
_context.ShopInfos.Update(shopInfo);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddAsync(ShopInfo shopInfo)
|
||||||
|
{
|
||||||
|
await _context.ShopInfos.AddAsync(shopInfo);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user