588 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using gehGassi.Common.Data;
using gehGassi.Core.Interfaces;
using gehGassi.Core.Services;
using gehGassi.Domain.Common;
using gehGassi.Permissions;
using gehGassi.Web.Auth;
using gehGassi.Web.Auth.Attributes;
using gehGassi.Web.Helper;
using gehGassi.Web.Models;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace gehGassi.Web.Controllers
{
/// <summary>
/// Controller für die Verwaltung von Kunden
/// </summary>
[Authorize]
public class CustomerController : BaseController
{
private readonly ICustomerService _customerService;
private readonly IMapper _mapper;
private readonly IStringLocalizer<CustomerController> _localizer;
private readonly ICountryService _countryService;
private readonly IUserService _userService;
private readonly IFileService _fileService;
private readonly ITicketStore _ticketStore;
private readonly IRefreshTokenService _refreshTokenService;
private readonly ICustomerTypeService _customerTypeService;
private readonly IBranchService _branchService;
private readonly IMangoPayService _mangoPayService;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="customerService">Instanz eines ICustomerService</param>
/// <param name="mapper">Instanz eines IMapper</param>
/// <param name="localizer">Instanz eines IStringLocalizer</param>
/// <param name="countryService">Instanz eines ICountryService</param>
/// <param name="userService">Instanz eines IUserService</param>
/// <param name="fileService">Instanz eines IFileService</param>
/// <param name="ticketStore">Instanz eines ITicketStore</param>
/// <param name="refreshTokenService">Instanz eines IRefreshTokenService</param>
/// <param name="customerTypeService">Instanz eines ICustomerTypeService</param>
/// <param name="branchService">Instanz eines IBranchService</param>
/// <param name="mangoPayService">Instanz eines IMangoPayService</param>
public CustomerController(ICustomerService customerService, IMapper mapper, IStringLocalizer<CustomerController> localizer, ICountryService countryService, IUserService userService,
IFileService fileService, ITicketStore ticketStore, IRefreshTokenService refreshTokenService, ICustomerTypeService customerTypeService, IBranchService branchService,
IMangoPayService mangoPayService)
{
_customerService = customerService;
_mapper = mapper;
_localizer = localizer;
_countryService = countryService;
_userService = userService;
_fileService = fileService;
_ticketStore = ticketStore;
_refreshTokenService = refreshTokenService;
_customerTypeService = customerTypeService;
_branchService = branchService;
_mangoPayService = mangoPayService;
}
/// <summary>
/// Gibt einen View für die Kunden-Verwaltung zurück
/// </summary>
/// <returns>View</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersRead)]
public IActionResult Index()
{
return View();
}
/// <summary>
/// Gibt eine Liste von Entitäten basierend auf Abfragekriterien zurück
/// </summary>
/// <param name="dm">Abfragekriterien</param>
/// <returns>Liste von gefundenen Entitäten</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersRead)]
[HttpPost]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult GetCustomers([FromBody] DataManager dm)
{
if (dm != null)
{
var propList = new List<ComplexProperty>();
dm.SetComplexProperties(propList);
}
var resultList = _customerService.FilterWithNames(dm?.SearchValue ?? "", SelectedLanguage, FallbackLanguage);
//Sortierung
resultList = dm.ApplySorting(resultList);
//Filter
resultList = dm.ApplyFiltering(resultList, out var countFiltered);
//Paging
resultList = dm.ApplyPaging(resultList);
var resultListVm = resultList.ToList().Select(item => _mapper.Map<CustomerListVm>(item)).ToList();
foreach (var itemVm in resultListVm)
{
itemVm.Logo = Tools.GetLogoThumb(itemVm.Logo, 100);
}
//FilterPreview?
if (!dm.RequiresCounts)
return Json(resultListVm);
return Json(new { result = resultListVm, count = countFiltered });
}
/// <summary>
/// Anlegen eines Kunden
/// </summary>
/// <returns>PartialView</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersCreate)]
[ResponseCache(Duration = 0)]
public IActionResult Create()
{
var model = new CustomerCrudVm
{
Number = _customerService.GetNextNumber(),
TypeId = null,
TypeName = _localizer["Common_None"],
UniqueId = Guid.NewGuid(),
};
return PartialView("_Create", model);
}
/// <summary>
/// Anlegen eines Kunden
/// </summary>
/// <param name="model">Model</param>
/// <returns>Json</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersCreate)]
[ValidateAntiForgeryToken]
[HttpPost]
public async Task<IActionResult> Create(CustomerCrudVm model)
{
var result = new ResponseVm { Success = false };
if (ModelState.IsValid)
{
var item = _customerService.Create();
_mapper.Map(model, item);
if (!string.IsNullOrWhiteSpace(model.Vat))
item.Vat = model.Vat.Trim();
item.Created = DateTimeOffset.UtcNow;
//item.Number = _customerService.GetNextNumber();
_customerService.Add(item);
await _customerService.CommitAsync(User.Identity.Name);
if (!string.IsNullOrWhiteSpace(model.Logo))
{
//Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen
var extension = Path.GetExtension(model.Logo);
var fileName = Path.GetFileName(model.Logo);
var filenameToUse = FileServiceHelper.GetCustomerPath(item.Id) + $"logo-{Guid.NewGuid():N}{extension}";
item.Logo = filenameToUse;
await _customerService.CommitAsync(User.Identity.Name);
//Kopieren
var tempFile = await _fileService.GetAsync(FileServiceHelper.TempContainer, model.Logo);
await _fileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile);
//Thumbnails
await GenerateThumbnail(FileServiceHelper.DocumentContainer, filenameToUse, 400);
await GenerateThumbnail(FileServiceHelper.DocumentContainer, filenameToUse, 200);
await GenerateThumbnail(FileServiceHelper.DocumentContainer, filenameToUse, 100);
//Altes Löschen
await _fileService.DeleteAsync(FileServiceHelper.TempContainer, model.Logo);
}
var mangopaySuccess = true;
if (!item.MangopayIdCreated && string.IsNullOrWhiteSpace(item.MangopayPaymentId) && item.HasDataForMangopay() && item.MangopayTermsAccepted)
{
//Der Kunde hat noch keinen Mangopay Account, aber die Daten sind vollständig
var mangopayResult = await _mangoPayService.CreateLegalOwnerAsync(item.Id, false);
if (!mangopayResult.Success)
{
mangopaySuccess = false;
ModelState.AddModelError(string.Empty, mangopayResult.ErrorMessage);
}
}
if (mangopaySuccess)
{
result.Data = item.ToCamelCaseJson();
result.Success = true;
result.Html = string.Empty;
return Json(result);
}
}
ModelState.Remove("CountryName");
var country = _countryService.GetCountry(model.Address.CountryCode);
model.CountryName = country != null ? country.Name : "";
ModelState.Remove("StateName");
var state = _countryService.GetState(model.Address.CountryCode, model.Address.State);
model.StateName = state != null ? state.Name : "";
ModelState.Remove("MangopayCountryName");
var mangopayCountry = _countryService.GetCountry(model.MangopayAddress.CountryCode);
model.MangopayCountryName = mangopayCountry != null ? mangopayCountry.Name : "";
ModelState.Remove("MangopayStateName");
var mangopayState = _countryService.GetState(model.MangopayAddress.CountryCode, model.MangopayAddress.State);
model.MangopayStateName = mangopayState != null ? mangopayState.Name : "";
ModelState.Remove("MangopayContactNationalityName");
var mangopayNationality = _countryService.GetCountry(model.MangopayContactNationality);
model.MangopayContactNationalityName = mangopayNationality != null ? mangopayNationality.Name : "";
ModelState.Remove("MangopayContactMainResidenceCodeName");
var mangopayResidence = _countryService.GetCountry(model.MangopayContactMainResidenceCode);
model.MangopayContactMainResidenceCodeName = mangopayResidence != null ? mangopayResidence.Name : "";
ModelState.Remove("BranchName");
var branche = await _branchService.GetAsync(model.BranchId);
model.BranchName = branche != null ? branche.Name : "";
ModelState.Remove("TypeName");
var type = await _customerTypeService.GetAsync(model.TypeId);
model.TypeName = type != null ? type.Name : "";
result.Html = await PartialView("_Create", model).ToStringAsync(ControllerContext);
return Json(result);
}
/// <summary>
/// Bearbeiten eines Kunden
/// </summary>
/// <param name="id">Id des Kunden</param>
/// <returns>PartialView</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersEdit)]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public async Task<IActionResult> Edit(long id)
{
var item = await _customerService.GetAsync(id);
if (item != null)
{
var model = _mapper.Map<CustomerCrudVm>(item);
var type = await _customerTypeService.GetAsync(item.TypeId);
model.TypeName = type != null ? type.Name : "";
var branche = await _branchService.GetAsync(item.BranchId);
model.BranchName = branche != null ? branche.Name : "";
var country = _countryService.GetCountry(item.Address.CountryCode);
model.CountryName = country != null ? country.Name : "";
var state = _countryService.GetState(item.Address.CountryCode, item.Address.State);
model.StateName = state != null ? state.Name : "";
item.MangopayAddress ??= new Address() { CountryCode = item.Address.CountryCode, State = item.Address.State };
model.MangopayAddress ??= new AddressVm() { CountryCode = item.Address.CountryCode, State = item.Address.State };
var mangopayCountry = _countryService.GetCountry(item.MangopayAddress.CountryCode);
model.MangopayAddress.CountryCode = item.MangopayAddress.CountryCode;
model.MangopayCountryName = mangopayCountry != null ? mangopayCountry.Name : "";
var mangopayState = _countryService.GetState(item.MangopayAddress.CountryCode, item.MangopayAddress.State);
model.MangopayAddress.State = item.MangopayAddress.State;
model.MangopayStateName = mangopayState != null ? mangopayState.Name : "";
if (string.IsNullOrWhiteSpace(item.MangopayContactNationality))
{
item.MangopayContactNationality = item.MangopayAddress.CountryCode;
model.MangopayContactNationality = item.MangopayAddress.CountryCode;
}
var mangopayNationality = _countryService.GetCountry(item.MangopayContactNationality);
model.MangopayContactNationalityName = mangopayNationality != null ? mangopayNationality.Name : "";
if (string.IsNullOrWhiteSpace(item.MangopayContactMainResidenceCode))
{
item.MangopayContactMainResidenceCode = item.MangopayAddress.CountryCode;
model.MangopayContactMainResidenceCode = item.MangopayAddress.CountryCode;
}
var mangopayResidence = _countryService.GetCountry(item.MangopayContactMainResidenceCode);
model.MangopayContactMainResidenceCodeName = mangopayResidence != null ? mangopayResidence.Name : "";
return PartialView("_Edit", model);
}
return PartialView("_Error");
}
/// <summary>
/// Bearbeiten eines Kunden
/// </summary>
/// <param name="model">Model</param>
/// <returns>Json</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersEdit)]
[ValidateAntiForgeryToken]
[HttpPost]
public async Task<IActionResult> Edit(CustomerCrudVm model)
{
var result = new ResponseVm { Success = false };
if (ModelState.IsValid)
{
var item = await _customerService.GetAsync(model.Id);
if (item != null)
{
var oldLogo = item.Logo;
var mangopayUserHasChanges = item.HasChangesForMangopay(model.MangopayCompanyName, model.MangopayEmail, model.MangopayAddress.AddressLine1, model.MangopayAddress.Zip, model.MangopayAddress.City,
model.MangopayAddress.CountryCode, model.MangopayRegistrationNumber, model.MangopayContactFirstName, model.MangopayContactLastName, model.MangopayContactEmail, model.MangopayContactBirthdate,
model.MangopayContactNationality, model.MangopayContactMainResidenceCode, model.MangopayTermsAccepted);
_mapper.Map(model, item);
if (!string.IsNullOrWhiteSpace(model.Vat))
item.Vat = model.Vat.Trim();
if(item.MangopayTermsAccepted && !item.MangopayTermsAcceptedDate.HasValue)
item.MangopayTermsAcceptedDate = DateTimeOffset.UtcNow;
if(item.MangopayTermsAccepted == false)
item.MangopayTermsAcceptedDate = null;
await _customerService.CommitAsync(User.Identity.Name);
if (oldLogo != item.Logo)
{
//Alte Daten löschen, neue Daten anlegen
if (!string.IsNullOrWhiteSpace(oldLogo))
{
await _fileService.DeleteAsync(FileServiceHelper.DocumentContainer, oldLogo);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldLogo, 400);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldLogo, 200);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldLogo, 100);
}
if (!string.IsNullOrWhiteSpace(model.Logo))
{
//Neue Bilddaten verwenden....
var extension = Path.GetExtension(model.Logo);
var fileName = Path.GetFileName(model.Logo);
var filenameToUse = FileServiceHelper.GetCustomerPath(item.Id) + $"logo-{Guid.NewGuid():N}{extension}";
item.Logo = filenameToUse;
await _customerService.CommitAsync(User.Identity.Name);
//Kopieren
var tempFile = await _fileService.GetAsync(FileServiceHelper.TempContainer, model.Logo);
await _fileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile);
//Thumbnails
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400);
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200);
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100);
//Altes Löschen
await _fileService.DeleteAsync(FileServiceHelper.TempContainer, model.Logo);
}
}
var mangopaySuccess = true;
if (!item.MangopayIdCreated && string.IsNullOrWhiteSpace(item.MangopayPaymentId) && item.HasDataForMangopay() && item.MangopayTermsAccepted)
{
//Der Kunde hat noch keinen Mangopay Account, aber die Daten sind vollständig
var mangopayResult = await _mangoPayService.CreateLegalOwnerAsync(item.Id, false);
if (!mangopayResult.Success)
{
mangopaySuccess = false;
ModelState.AddModelError(string.Empty, mangopayResult.ErrorMessage);
}
}
else
{
if (item.MangopayIdCreated && !string.IsNullOrWhiteSpace(item.MangopayPaymentId) && mangopayUserHasChanges)
{
//Daten aktualisieren
var mangopayResult = await _mangoPayService.UpdateLegalOwnerAsync(item.Id);
if (!mangopayResult.Success)
{
mangopaySuccess = false;
ModelState.AddModelError(string.Empty, mangopayResult.ErrorMessage);
}
}
}
if (mangopaySuccess)
{
result.Data = item.ToCamelCaseJson();
result.Success = true;
result.Html = string.Empty;
return Json(new { result.Success, result.Html, result.Data });
}
}
}
ModelState.Remove("CountryName");
var country = _countryService.GetCountry(model.Address.CountryCode);
model.CountryName = country != null ? country.Name : "";
ModelState.Remove("StateName");
var state = _countryService.GetState(model.Address.CountryCode, model.Address.State);
model.StateName = state != null ? state.Name : "";
ModelState.Remove("MangopayCountryName");
var mangopayCountry = _countryService.GetCountry(model.MangopayAddress.CountryCode);
model.MangopayCountryName = mangopayCountry != null ? mangopayCountry.Name : "";
ModelState.Remove("MangopayStateName");
var mangopayState = _countryService.GetState(model.MangopayAddress.CountryCode, model.MangopayAddress.State);
model.MangopayStateName = mangopayState != null ? mangopayState.Name : "";
ModelState.Remove("MangopayContactNationalityName");
var mangopayNationality = _countryService.GetCountry(model.MangopayContactNationality);
model.MangopayContactNationalityName = mangopayNationality != null ? mangopayNationality.Name : "";
ModelState.Remove("MangopayContactMainResidenceCodeName");
var mangopayResidence = _countryService.GetCountry(model.MangopayContactMainResidenceCode);
model.MangopayContactMainResidenceCodeName = mangopayResidence != null ? mangopayResidence.Name : "";
ModelState.Remove("BranchName");
var branche = await _branchService.GetAsync(model.BranchId);
model.BranchName = branche != null ? branche.Name : "";
ModelState.Remove("TypeName");
var type = await _customerTypeService.GetAsync(model.TypeId);
model.TypeName = type != null ? type.Name : "";
result.Html = await PartialView("_Edit", model).ToStringAsync(ControllerContext);
return Json(result);
}
/// <summary>
/// Löschen eines oder mehrerer Kunden
/// </summary>
/// <param name="ids">Liste Id der Entitäten</param>
/// <returns>Json</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
[HasPermission(Permission.CustomersManage, Permission.CustomersDelete)]
[HttpPost]
public async Task<IActionResult> Delete(List<long> ids)
{
var batchErrorHeader = $"<p><strong>{_localizer["Common_BatchDelete_Failed"].Value}</strong></p>";
var batchResult = new BatchResponseVm(batchErrorHeader) { Success = true };
foreach (var id in ids)
{
var item = await _customerService.GetAsync(id);
if (item != null)
{
//Noch was anderes zu berücksichtigen?
var customerCount = 0; //await UserService.CountByTenantAsync(item.Id);
if (customerCount == 0)
{
batchResult.BatchResponseList.Add(new BatchResponseItemVm() { Id = item.Id.ToString(), Name = item.Name, Success = true, NotFound = false, ErrorMessage = "" });
var postingPath = FileServiceHelper.GetCustomerPath(item.Id);
await FileService.ClearDirectoryAsync(FileServiceHelper.DocumentContainer, postingPath);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, item.Logo, 400);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, item.Logo, 200);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, item.Logo, 100);
await _userService.ResetCustomerAsync(item.Id);
_customerService.Remove(item);
}
else
{
batchResult.Success = false;
if (customerCount > 0)
{
batchResult.BatchResponseList.Add(new BatchResponseItemVm() { Id = id.ToString(), Name = item.Name, Success = false, NotFound = false, ErrorMessage = string.Format(_localizer["Common_BatchDelete_InUse_Users"], $"<strong>{item.Name}</strong>", $"<strong>{customerCount}</strong>") + "<br/>" });
break;
}
}
}
else
{
batchResult.Success = false;
batchResult.BatchResponseList.Add(new BatchResponseItemVm() { Id = id.ToString(), Name = "", Success = false, NotFound = true, ErrorMessage = string.Format(_localizer["Common_BatchDelete_NotFound"], $"<strong>{id}</strong>") + "<br/>" });
}
}
if (batchResult.BatchResponseList.Any(c => c.Success))
await _customerService.CommitAsync(User.Identity.Name);
return Json(batchResult);
}
#region Helper
/// <summary>
/// Gibt eine Liste von Kunden für LookUp zurück
/// </summary>
/// <param name="dm">DataManager</param>
/// <param name="includeNone">Soll "Keine(r)" integriert werden</param>
/// <returns>Liste</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
public async Task<IActionResult> Lookup([FromBody] DataManager dm, bool includeNone = false)
{
var filter = string.Empty;
if (dm.Where?.FirstOrDefault() != null)
{
filter = dm.Where.First().value.ToString();
if (filter.IndexOf('(') > 0)
{
filter = filter.Substring(0, (filter.IndexOf('(') - 1));
filter = filter.TrimEnd();
}
}
var items = await _customerService.SearchAsync(filter);
var result = items.Select(item => new LookupItemVm() { Id = item.Id.ToString(), Name = $"{item.Name}" }).OrderBy(c => c.Name).ToList();
if (includeNone)
result.Insert(0, new LookupItemVm() { Id = "", Name = _localizer["Common_None"].ToString() });
return Json(result);
}
/// <summary>
/// Gibt eine Liste von Kunden für LookUp zurück welche über ein Mangopay Konto verfügen
/// </summary>
/// <param name="dm">DataManager</param>
/// <param name="includeNone">Soll "Keine(r)" integriert werden</param>
/// <returns>Liste</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
public async Task<IActionResult> LookupMangopay([FromBody] DataManager dm, bool includeNone = false)
{
var filter = string.Empty;
if (dm.Where?.FirstOrDefault() != null)
{
filter = dm.Where.First().value.ToString();
if (filter.IndexOf('(') > 0)
{
filter = filter.Substring(0, (filter.IndexOf('(') - 1));
filter = filter.TrimEnd();
}
}
var items = await _customerService.SearchWithMangopayAccountAsync(filter);
var result = items.Select(item => new LookupItemVm() { Id = item.Id.ToString(), Name = $"{item.Name}" }).OrderBy(c => c.Name).ToList();
if (includeNone)
result.Insert(0, new LookupItemVm() { Id = "", Name = _localizer["Common_None"].ToString() });
return Json(result);
}
/// <summary>
/// Gibt eine Adresse eines Kunden mit Namen für Land und Bundelsand aufgelöst zurück
/// </summary>
/// <param name="customerId">Id des Kunden</param>
/// <returns>Json</returns>
[Authorize(Policy = Policies.PowerUserOnly)]
public async Task<IActionResult> GetAddress(long customerId)
{
var customer = await _customerService.GetAsync(customerId);
if (customer != null)
{
var model = _mapper.Map<AddressWithNamesVm>(customer.Address);
var country = _countryService.GetCountry(model.CountryCode);
model.CountryName = country.Name;
var state = _countryService.GetState(model.CountryCode, model.State);
model.StateName = state.Name;
return Json(model);
}
return BadRequest();
}
#endregion
}
}