using ConfectioneryContracts.BindingModels; using ConfectioneryContracts.BusinessLogicsContracts; using ConfectioneryContracts.SearchModels; using ConfectioneryContracts.ViewModels; using ConfectioneryDatabaseImplement.Models; using ConfectioneryDataModels.Models; using Microsoft.AspNetCore.Mvc; using System.Text.Json; namespace ConfectioneryRestApi.Controllers { [Route("api/[controller]/[action]")] [ApiController] public class ShopController : Controller { private readonly ILogger _logger; private readonly IShopLogic _logic; public ShopController(IShopLogic logic, ILogger logger) { _logger = logger; _logic = logic; } [HttpGet] public List? GetShops() { try { return _logic.ReadList(null); } catch (Exception ex) { _logger.LogError(ex, "Ошибка получения списка магазинов"); throw; } } /// /// Получает на вход айди магазина и по нему возвращает магазин /// /// The identifier. /// /// Кортеж из магазина, итератора с изделиями которые находятся в магазине и итератора с количеством этих изделий. /// /// Почему изделия и их количество не находятся в одном кортеже? потому что тогда он их не сериализует /// и я не знаю почему. /// Также, к сожалению, приходится явно присваивать каждое поле из IPastyModel в PastyViewModel, поскольку /// нельзя сериализовать интерфейс, и при это нельзя его неявно кастануть к PastryViewModel, даже если в /// истинном типе ConfectioneryDatabaseImplement.Pastry такой каст есть. /// Сделать же каст в PastryViewModel из IPastryModel нельзя, потому что запрещен каст с интерфейсами. /// Единственный нормальный вариант создать отдельную сущность, где объединить изделия и их количество, /// и уже ее хранить в магазине и соответственно ее передавать. Но поскольку для этого нужно перелопатить пол-проекта /// и получить минус баллы на pr я откажусь от подобной идеи. [HttpGet] public Tuple, IEnumerable>? GetShopWithPastries(int id) { try { var shop = _logic.ReadElement(new() { Id = id }); if (shop == null) { return null; } return Tuple.Create(shop, shop.Pastries.Select(x => new PastryViewModel () { Id = x.Value.Item1.Id, Price = x.Value.Item1.Price, PastryName = x.Value.Item1.PastryName, }), shop.Pastries.Select(x => x.Value.Item2)); } catch (Exception ex) { _logger.LogError(ex, "Ошибка получения магазина"); throw; } } [HttpPost] public void CRUDShop(Action action) { try { action.Invoke(); } catch (Exception ex) { _logger.LogError(ex, "Ошибка операции CRUD - {operation} с магазином", action.Method.Name); throw; } } [HttpPost] public void UpdateShop(ShopBindingModel model) => CRUDShop(() => _logic.Update(model)); [HttpPost] public void CreateShop(ShopBindingModel model) => CRUDShop(() => _logic.Create(model)); [HttpPost] public void DeleteShop(ShopBindingModel model) => CRUDShop(() => _logic.Delete(model)); [HttpPost] public void AddPastryInShop(Tuple countPastryForShop) { CRUDShop(() => _logic.AddPastry(countPastryForShop.Item1, countPastryForShop.Item2, countPastryForShop.Item3)); } } }