namespace GrossesMitainesAPI.Controllers; #region Dependencies using GrossesMitainesAPI.Data; using GrossesMitainesAPI.Models; using GrossesMitainesAPI.Services; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.AspNet.Identity; using System.Data; using System.Linq; #endregion [EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"), Authorize(AuthenticationSchemes = "Identity.Application", Roles = "Administrateur")] public class InvoiceController : Controller { #region DI Fields private readonly ILogger _logger; private readonly InventoryContext _context; private readonly DatabaseCacheService _cache; private readonly SignInManager _signInMan; private readonly Microsoft.AspNetCore.Identity.UserManager _userMan; #endregion #region Ctor public InvoiceController(ILogger logger, InventoryContext context, DatabaseCacheService cache, Microsoft.AspNetCore.Identity.UserManager userMan) { _logger = logger; _context = context; _cache = cache; _userMan = userMan; } #endregion #region API Methods [HttpGet, Route("GetList"), Authorize(Roles = "Client, Administrateur")] public async Task>> Get(bool? all = false) { IList roles; string id; try { // Trouver les rôles de l'utilisateur, assumer non-admin si impossible à trouver. roles = await _userMan.GetRolesAsync(await _userMan.GetUserAsync(_signInMan.Context.User)); } catch (Exception e) { _logger.LogError(10, e.Message); roles = new List(); } try { id = _signInMan.Context.User.Identity.GetUserId(); if (all is not null && all == true && roles.Contains("Administrateur")) return _context.Invoices.Include("LinkedAccount, ShippingAddress").ToList(); else return _context.Invoices.Include("ShippingAddress").Where(x => x.LinkedAccount != null && x.LinkedAccount.Id == id).ToList(); } catch (Exception e) { _logger.LogError(10, e.Message); return BadRequest(); } } [HttpGet, Route("Get"), Authorize(Roles = "Client, Administrateur")] public async Task> Get(int id) { IList roles; InvoiceModel inv; try { // Trouver les rôles de l'utilisateur, assumer non-admin si impossible à trouver. roles = await _userMan.GetRolesAsync(await _userMan.GetUserAsync(_signInMan.Context.User)); } catch (Exception e) { _logger.LogError(10, e.Message); roles = new List(); } try { inv = _context.Invoices.Where(x => x.Id == id).Include("ShippingAddress").First(); } catch (Exception e) { _logger.LogError(10, e.Message); return BadRequest(); } if (roles.Contains("Administrateur") || (inv.LinkedAccount is not null && inv.LinkedAccount.Id == _signInMan.Context.User.Identity.GetUserId())) return inv; else return Unauthorized(); } [HttpPost, AllowAnonymous] public async Task> Post(InvoiceModel inv) { var user = await _userMan.GetUserAsync(_signInMan.Context.User); List prods; if (user is not null) inv.LinkedAccount = user; inv.PurchaseDate = DateTime.Now; // Pour forcer la date. var prodcom = inv.Products.ToList(); try { prods = _context.Products.Where(x => inv.Products.Select(x => x.Product).Contains(x)).ToList(); } catch (Exception e) { _logger.LogError(8, e.Message); return BadRequest(); } foreach (var prod in prodcom) { // Update de quantités dans l'inventaire. ProductModel inventProd = prods.Where(x => x.Id == prod.Product.Id).First(); if (inventProd.Quantity > prod.Quantity) return BadRequest(); // TODO: retourner le produit qui ne peut pas être vendu. if (inventProd.Quantity == prod.Quantity) { inventProd.Quantity = 0; inventProd.Status = inventProd.Status == ProductModel.States.Clearance ? ProductModel.States.Discontinued : ProductModel.States.BackOrder; } else inventProd.Quantity -= prod.Quantity; } try { // Faire les updates dans la BD. _context.Invoices.Add(inv); _context.Products.UpdateRange(prods); _context.SaveChanges(); } catch (Exception e) { _logger.LogError(8, e.Message); return BadRequest(); } _cache.askForRefresh(); return Ok(inv); } [HttpPost, Authorize(Roles = "Client, Administrateur")] public async Task> Cancel(int id) { InvoiceModel inv; IList roles; try { // Trouver la commande. inv = _context.Invoices.Where(x => x.Id == id) .Include("Product").First(); } catch (Exception e) { _logger.LogError(8, e.Message); return BadRequest(); } try { // Trouver les rôles de l'utilisateur, assumer non-admin si impossible à trouver. roles = await _userMan.GetRolesAsync(await _userMan.GetUserAsync(_signInMan.Context.User)); } catch (Exception e) { _logger.LogError(10, e.Message); roles = new List(); } // Pour ne pas pouvoir arbitrairement annuler la commande d'un autre client en tant que client. if (!((inv.LinkedAccount is not null && inv.LinkedAccount.Id == _signInMan.Context.User.Identity.GetUserId()) || roles.Contains("Administrateur"))) return Unauthorized(); inv.Status = InvoiceModel.InStates.Cancelled; foreach (var prod in inv.Products) // Revert l'inventaire. prod.Product.Quantity = prod.Product.Quantity + prod.Quantity; try { _context.Update(inv); _context.SaveChanges(); } catch (Exception e) { _logger.LogError(8, e.Message); return BadRequest(); } _cache.askForRefresh(); return Ok(inv); } #endregion }