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
{
///
/// Service der die Verwaltung von Steuern realisiert
///
public class TaxRateService : ServiceBase, ITaxRateService
{
private readonly IOptions _vatValidationOptions;
private readonly IRepository _namesRepository;
///
/// Erstellt eine Instanz
///
/// Instanz eines IUnitOfWork
/// Instanz von VatValidationSettings
/// Instanz von ShopSettings
public TaxRateService(IUnitOfWork unitOfWork, IOptions vatValidationOptions) : base(unitOfWork)
{
_vatValidationOptions = vatValidationOptions;
_namesRepository = unitOfWork.GetRepository();
}
///
/// Gibt eine gefilterte Liste von Steuern zurück
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// List betroffener Steuern
public IQueryable Filter(string filter)
{
return Repository.Query(c => c.Title.Contains(filter));
}
///
/// Erstellen einer Steuer
///
/// Steuer
public TaxRate Create()
{
var item = new TaxRate
{
Value = 0
};
return item;
}
///
/// Gibt eine gefilterte Liste von Steuern zurück. Sucht nur im Titel
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// List betroffener Hundeausführern
public async Task> SearchAsync(string filter)
{
return (await Repository.FindAsync(c => c.Title.Contains(filter)).ConfigureAwait(false)).ToList();
}
///
/// Gibt eine gefilterte Liste von Steuern mit Namen zurück in einer gewählten Sprache
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// Gewünschte Sprache
/// Fallback Sprache falls keine Übersetzung vorhanden
/// Liste betroffener Steuern
public IQueryable 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;
}
///
/// Prüft ob für ein Land schon eine Steuer mit einem Wert existiert
///
/// Land ISO2
/// Steuer-Wert
/// true wenn existiert, false sonst
public async Task ExistsAsync(string countryIso, decimal value)
{
var existing = await Repository.FirstOrDefaultAsync(c => c.CountryIso == countryIso && c.Value == value);
return existing != null;
}
///
/// Zurücksetzen wird für Versandkosten verwendet
///
/// Id die ausgenommen werden soll
/// Task
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;
}
}
///
/// Gibt den Steuersatz für Versandkosten zurück
///
/// Versandkosten-Steuersatz in Prozent
public async Task GetForShipmentAsync()
{
var result = 0m;
var item = await Repository.FirstOrDefaultAsync(c => c.UseForShipment).ConfigureAwait(false);
if(item != null)
result = item.Value;
return result;
}
///
/// Berechnen eines Brutto-Wertes für einen Preis
///
/// Preis netto
/// Id der Steuerstufe
/// QuellLand des Shops
/// Zielland
/// Brutto-Wert
public async Task 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;
}
///
/// Berechnen eines Brutto-Wertes für Versandkosten
///
/// Preis netto
/// QuellLand des Shops
/// Zielland
/// Brutto-Wert
public async Task 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;
}
}
}