245 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
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<InvoiceController> _logger;
 | 
						|
    private readonly InventoryContext _context;
 | 
						|
    private readonly DatabaseCacheService _cache;
 | 
						|
    private readonly SignInManager<InventoryUser> _signInMan;
 | 
						|
    private readonly Microsoft.AspNetCore.Identity.UserManager<InventoryUser> _userMan;
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region Ctor
 | 
						|
    public InvoiceController(ILogger<InvoiceController> logger,
 | 
						|
                             InventoryContext context,
 | 
						|
                             DatabaseCacheService cache,
 | 
						|
                             SignInManager<InventoryUser> signInMan,
 | 
						|
                             Microsoft.AspNetCore.Identity.UserManager<InventoryUser> userMan) {
 | 
						|
        _logger = logger;
 | 
						|
        _context = context;
 | 
						|
        _cache = cache;
 | 
						|
        _userMan = userMan;
 | 
						|
        _signInMan = signInMan;
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region API Methods
 | 
						|
    [HttpGet, Authorize(Roles = "Client, Administrateur")]
 | 
						|
    public async Task<ActionResult<List<InvoiceModel>>> Get(bool? all = false) {
 | 
						|
        IList<string> roles;
 | 
						|
        string id;
 | 
						|
        try { // Trouver les rôles de l'utilisateur, assumer non-admin si impossible à trouver.
 | 
						|
            var user = await _userMan.GetUserAsync(_signInMan.Context.User);
 | 
						|
            roles = await _userMan.GetRolesAsync(user);
 | 
						|
        }
 | 
						|
        catch (Exception e) {
 | 
						|
            _logger.LogError(10, e.Message);
 | 
						|
            roles = new List<string>();
 | 
						|
        }
 | 
						|
 | 
						|
        try {
 | 
						|
            id = _signInMan.Context.User.Identity.GetUserId();
 | 
						|
            if (all is not null && all == true && roles.Contains("Administrateur"))
 | 
						|
                return Ok(_context.Invoices
 | 
						|
                    .Include("ShippingAddress")
 | 
						|
                    .Include(x => x.Products)
 | 
						|
                    .ThenInclude(y => y.Product)
 | 
						|
                    .ToList());
 | 
						|
 | 
						|
            else
 | 
						|
                return Ok(_context.Invoices
 | 
						|
                    .Include("ShippingAddress")
 | 
						|
                    .Include(x => x.Products)
 | 
						|
                    .ThenInclude(y => y.Product)
 | 
						|
                    .Where(x => x.LinkedAccount != null && x.LinkedAccount.Id == id).ToList());
 | 
						|
        }
 | 
						|
        catch (Exception e) {
 | 
						|
            _logger.LogError(10, e.Message);
 | 
						|
            return BadRequest();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpGet("{id}"), Authorize(Roles = "Client, Administrateur")]
 | 
						|
    public async Task<ActionResult<InvoiceModel>> Get(int id) {
 | 
						|
        IList<string> 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<string>();
 | 
						|
        }
 | 
						|
 | 
						|
        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<ActionResult<InvoiceModel>> Post(SendInvoiceModel sinv) {
 | 
						|
        var user = await _userMan.GetUserAsync(_signInMan.Context.User);
 | 
						|
        var prodcom = sinv.ProdQuant;
 | 
						|
        Dictionary<int, uint> badprods = new();
 | 
						|
        List<ProductModel> prods;
 | 
						|
        InvoiceModel inv = new() {
 | 
						|
            FirstName = sinv.FirstName,
 | 
						|
            LastName = sinv.LastName,
 | 
						|
            EmailAddress = sinv.EmailAddress,
 | 
						|
            PhoneNumber = sinv.PhoneNumber,
 | 
						|
            PurchaseDate = DateTime.Now
 | 
						|
        };
 | 
						|
        AddressModel ad = _context.Addresses.FirstOrDefault(x => x.CivicNumber == sinv.CivicNumber &&
 | 
						|
                                                        x.Appartment == sinv.Appartment &&
 | 
						|
                                                        x.Street == sinv.Street &&
 | 
						|
                                                        x.City == sinv.City &&
 | 
						|
                                                        x.Province == sinv.Province &&
 | 
						|
                                                        x.Country == sinv.Country) ??
 | 
						|
                                                        new() {
 | 
						|
                                                            CivicNumber = sinv.CivicNumber,
 | 
						|
                                                            Appartment = sinv.Appartment,
 | 
						|
                                                            Street = sinv.Street,
 | 
						|
                                                            City = sinv.City,
 | 
						|
                                                            Province = sinv.Province,
 | 
						|
                                                            Country = sinv.Country,
 | 
						|
                                                            PostalCode = sinv.PostalCode
 | 
						|
                                                        };
 | 
						|
        inv.ShippingAddress = ad;
 | 
						|
        if (user is not null)
 | 
						|
            inv.LinkedAccount = user;
 | 
						|
 | 
						|
        try {
 | 
						|
            prods = _context.Products.Where(x => sinv.ProdQuant.Select(x => x.Key).Contains(x.Id)).ToList();
 | 
						|
        }
 | 
						|
        catch (Exception e) {
 | 
						|
            _logger.LogError(8, e.Message);
 | 
						|
            return BadRequest();
 | 
						|
        }
 | 
						|
 | 
						|
        if (prods.Count == 0)
 | 
						|
            return BadRequest("Vous devez inclure au moins un produit à votre commande.");
 | 
						|
 | 
						|
        foreach (var prod in sinv.ProdQuant) { // Update de quantités dans l'inventaire.
 | 
						|
            ProductModel inventProd = prods.Where(x => x.Id == prod.Key).First();
 | 
						|
            if (inventProd.Quantity > prod.Value)
 | 
						|
                badprods.Add(prod.Key, prod.Value);
 | 
						|
            if (inventProd.Quantity == prod.Value) {
 | 
						|
                inventProd.Quantity = 0;
 | 
						|
                inventProd.Status = inventProd.Status == ProductModel.States.Clearance ?
 | 
						|
                                                         ProductModel.States.Discontinued :
 | 
						|
                                                         ProductModel.States.BackOrder;
 | 
						|
            }
 | 
						|
            else inventProd.Quantity -= prod.Value;
 | 
						|
            inventProd.LastSale = DateTime.Now;
 | 
						|
            inventProd.Sales += prod.Value;
 | 
						|
        }
 | 
						|
 | 
						|
        if (badprods.Count > 0) // Retour des produits non-achetable avec l'inventaire restant.
 | 
						|
            return BadRequest(badprods.ToArray());
 | 
						|
 | 
						|
        try { // Faire les updates dans la BD.
 | 
						|
            _context.Addresses.Add(ad);
 | 
						|
            _context.Invoices.Add(inv);
 | 
						|
            _context.Products.UpdateRange(prods);
 | 
						|
            _context.SaveChanges();
 | 
						|
        }
 | 
						|
        catch (Exception e) {
 | 
						|
            _logger.LogError(8, e.Message);
 | 
						|
            return BadRequest(e.InnerException.Message);
 | 
						|
        }
 | 
						|
 | 
						|
        _cache.askForRefresh();
 | 
						|
        return Ok(inv);
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpPost("Cancel/{id}"), Authorize(Roles = "Client, Administrateur")]
 | 
						|
    public async Task<ActionResult<InvoiceModel>> Cancel(int id) {
 | 
						|
        InvoiceModel inv;
 | 
						|
        IList<string> 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<string>();
 | 
						|
        }
 | 
						|
 | 
						|
        // 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();
 | 
						|
 | 
						|
        if (inv.Status == InvoiceModel.InStates.Cancelled ||
 | 
						|
            inv.Status == InvoiceModel.InStates.Returned)
 | 
						|
            return BadRequest("La commande à déjà été annulée.");
 | 
						|
 | 
						|
        if (inv.Status == InvoiceModel.InStates.Shipped)
 | 
						|
            return BadRequest("Il est trop tard pour annuler votre commande, veuillez contacter le service à la clientèle pour retourner la commande.");
 | 
						|
 | 
						|
        inv.Status = InvoiceModel.InStates.Cancelled;
 | 
						|
 | 
						|
        foreach (var prod in inv.Products) { // Revert l'inventaire.
 | 
						|
            if (prod.Product.Quantity == 0)
 | 
						|
                if (prod.Product.Status == ProductModel.States.Discontinued)
 | 
						|
                    prod.Product.Status = ProductModel.States.Clearance;
 | 
						|
                else prod.Product.Status = ProductModel.States.Available;
 | 
						|
            prod.Product.Quantity = prod.Product.Quantity + prod.Quantity;
 | 
						|
            prod.Product.Sales -= prod.Quantity;
 | 
						|
        }
 | 
						|
 | 
						|
        try {
 | 
						|
            _context.Update(inv);
 | 
						|
            _context.SaveChanges();
 | 
						|
        }
 | 
						|
        catch (Exception e) {
 | 
						|
            _logger.LogError(8, e.Message);
 | 
						|
            return BadRequest();
 | 
						|
        }
 | 
						|
 | 
						|
        _cache.askForRefresh();
 | 
						|
        return Ok(inv);
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
} |