197 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using gehGassi.Common;
using gehGassi.Core.Interfaces;
using gehGassi.Domain.Shop;
using Microsoft.Extensions.Options;
namespace gehGassi.Core.Services
{
/// <summary>
/// Service der die Verwaltung von Steuern realisiert
/// </summary>
public class TaxRateService : ServiceBase<TaxRate>, ITaxRateService
{
private readonly IOptions<VatValidationSettings> _vatValidationOptions;
private readonly IRepository<TaxRateWithNames> _namesRepository;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="unitOfWork">Instanz eines IUnitOfWork</param>
/// <param name="vatValidationOptions">Instanz von VatValidationSettings</param>
/// <param name="shopOptions">Instanz von ShopSettings</param>
public TaxRateService(IUnitOfWork unitOfWork, IOptions<VatValidationSettings> vatValidationOptions) : base(unitOfWork)
{
_vatValidationOptions = vatValidationOptions;
_namesRepository = unitOfWork.GetRepository<TaxRateWithNames>();
}
/// <summary>
/// Gibt eine gefilterte Liste von Steuern zurück
/// </summary>
/// <param name="filter">Filterbegriff der in bestimmten Feldern gesucht wird</param>
/// <returns>List betroffener Steuern</returns>
public IQueryable<TaxRate> Filter(string filter)
{
return Repository.Query(c => c.Title.Contains(filter));
}
/// <summary>
/// Erstellen einer Steuer
/// </summary>
/// <returns>Steuer</returns>
public TaxRate Create()
{
var item = new TaxRate
{
Value = 0
};
return item;
}
/// <summary>
/// Gibt eine gefilterte Liste von Steuern zurück. Sucht nur im Titel
/// </summary>
/// <param name="filter">Filterbegriff der in bestimmten Feldern gesucht wird</param>
/// <returns>List betroffener Hundeausführern</returns>
public async Task<List<TaxRate>> SearchAsync(string filter)
{
return (await Repository.FindAsync(c => c.Title.Contains(filter)).ConfigureAwait(false)).ToList();
}
/// <summary>
/// Gibt eine gefilterte Liste von Steuern mit Namen zurück in einer gewählten Sprache
/// </summary>
/// <param name="filter">Filterbegriff der in bestimmten Feldern gesucht wird</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="fallback">Fallback Sprache falls keine Übersetzung vorhanden</param>
/// <returns>Liste betroffener Steuern</returns>
public IQueryable<TaxRateWithNames> FilterWithNames(string filter, string language, string fallback)
{
language = language.ToUpperInvariant();
fallback = fallback.ToUpperInvariant();
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_TaxRatesWithNames({0},{1})", c => c.Title.Contains(filter) || c.Name.Contains(filter), language, fallback);
return baseQuery;
}
/// <summary>
/// Prüft ob für ein Land schon eine Steuer mit einem Wert existiert
/// </summary>
/// <param name="countryIso">Land ISO2</param>
/// <param name="value">Steuer-Wert</param>
/// <returns>true wenn existiert, false sonst</returns>
public async Task<bool> ExistsAsync(string countryIso, decimal value)
{
var existing = await Repository.FirstOrDefaultAsync(c => c.CountryIso == countryIso && c.Value == value);
return existing != null;
}
/// <summary>
/// Zurücksetzen wird für Versandkosten verwendet
/// </summary>
/// <param name="excludeId">Id die ausgenommen werden soll</param>
/// <returns>Task</returns>
public async Task ResetShipmentAsync(int excludeId)
{
var items = await Repository.FindAsync(c => c.Id != excludeId && c.UseForShipment).ConfigureAwait(false);
foreach (var taxRate in items)
{
taxRate.UseForShipment = false;
}
}
/// <summary>
/// Gibt den Steuersatz für Versandkosten zurück
/// </summary>
/// <returns>Versandkosten-Steuersatz in Prozent</returns>
public async Task<decimal> GetForShipmentAsync()
{
var result = 0m;
var item = await Repository.FirstOrDefaultAsync(c => c.UseForShipment).ConfigureAwait(false);
if(item != null)
result = item.Value;
return result;
}
/// <summary>
/// Berechnen eines Brutto-Wertes für einen Preis
/// </summary>
/// <param name="value">Preis netto</param>
/// <param name="taxRateId">Id der Steuerstufe</param>
/// <param name="sourceCountry">QuellLand des Shops</param>
/// <param name="targetCountry">Zielland</param>
/// <returns>Brutto-Wert</returns>
public async Task<TaxGrossResult> CalculateGrossAsync(decimal value, int taxRateId, string sourceCountry, string targetCountry)
{
var result = new TaxGrossResult()
{
Value = 0,
TaxRate = 0,
TaxValue = 0
};
var taxRate = await Repository.FirstOrDefaultAsync(c => c.Id == taxRateId);
if (taxRate != null)
{
var isEuCountry = _vatValidationOptions.Value.Countries.Contains(targetCountry);
var isNoTaxCountry = _vatValidationOptions.Value.NoTaxCountries.Contains(targetCountry);
var isSameAsSource = sourceCountry == targetCountry;
if ((!isEuCountry && !isNoTaxCountry) || isSameAsSource)
{
result.TaxRate = taxRate.Value;
result.TaxValue = Math.Round(((value * taxRate.Value) / 100),2,MidpointRounding.AwayFromZero);
result.Value = Math.Round(value + ((value * taxRate.Value) / 100),2,MidpointRounding.AwayFromZero);
}
}
return result;
}
/// <summary>
/// Berechnen eines Brutto-Wertes für Versandkosten
/// </summary>
/// <param name="value">Preis netto</param>
/// <param name="sourceCountry">QuellLand des Shops</param>
/// <param name="targetCountry">Zielland</param>
/// <returns>Brutto-Wert</returns>
public async Task<TaxGrossResult> CalculateShipmentGrossAsync(decimal value, string sourceCountry, string targetCountry)
{
var result = new TaxGrossResult()
{
Value = 0,
TaxRate = 0,
TaxValue = 0
};
var taxRate = await Repository.FirstOrDefaultAsync(c => c.UseForShipment);
if (taxRate != null)
{
var isEuCountry = _vatValidationOptions.Value.Countries.Contains(targetCountry);
var isNoTaxCountry = _vatValidationOptions.Value.NoTaxCountries.Contains(targetCountry);
var isSameAsSource = sourceCountry == targetCountry;
if ((!isEuCountry && !isNoTaxCountry) || isSameAsSource)
{
result.TaxRate = taxRate.Value;
result.TaxValue = Math.Round(((value * taxRate.Value) / 100), 2, MidpointRounding.AwayFromZero);
result.Value = Math.Round(value + ((value * taxRate.Value) / 100), 2, MidpointRounding.AwayFromZero);
//var result = value + ((value * taxRate.Value) / 100);
//return Math.Round(result, 2, MidpointRounding.AwayFromZero);
}
}
return result;
}
}
}