using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using gehGassi.Common.Data; using gehGassi.Core.Interfaces; using gehGassi.Domain.Advertisements; using gehGassi.Domain.Common; using gehGassi.Domain.News; using Microsoft.EntityFrameworkCore; using NetTopologySuite; using NetTopologySuite.Geometries; namespace gehGassi.Core.Services { /// /// Service der die Verwaltung von News realisiert /// public class NewsService : ServiceBase, INewsService { private readonly IRepository _namesRepository; /// /// Erstellt eine Instanz /// /// Instanz eines IUnitOfWork public NewsService(IUnitOfWork unitOfWork) : base(unitOfWork) { _namesRepository = unitOfWork.GetRepository(); } /// /// Gibt eine gefilterte Liste von News zurück /// /// Filterbegriff der in bestimmten Feldern gesucht wird /// List betroffener News public IQueryable Filter(string filter) { return Repository.Query(c => c.Headline.Contains(filter)); } /// /// Erstellen einer News /// /// News public News Create() { var item = new News() { Status = NewsStatus.Draft, Visibility = NewsVisibility.None, GeoMode = GeoMode.None, Created = DateTimeOffset.UtcNow, Location = new Point(0,0){SRID = 4326} }; return item; } /// /// Gibt eine gefilterte Liste von News zurück. Sucht nur im Titel /// /// Filterbegriff der in bestimmten Feldern gesucht wird /// List betroffener News public async Task> SearchAsync(string filter) { return (await Repository.FindAsync(c => c.Headline.Contains(filter))).ToList(); } /// /// Gibt eine gefilterte Liste von News mit Namen zurück in einer gewählten Sprache /// /// Filterbegriff der in bestimmten Feldern gesucht wird /// Gewünschte Sprache /// Fallback Sprache /// Sollen gelöschte inkludiert werden? /// Liste betroffener News public IQueryable FilterWithNames(string filter, string language, string fallback, bool includeDeleted) { language = language.ToUpperInvariant(); fallback = fallback.ToUpperInvariant(); var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Headline.Contains(filter), language, fallback); if (!includeDeleted) baseQuery = baseQuery.Where(c => c.Deleted == false); return baseQuery; } /// /// Gibt eine gefilterte Liste von News mit Namen zurück in einer gewählten Sprache /// /// Filterbegriff der in bestimmten Feldern gesucht wird /// Liste nach Bundesländern nach Filter /// Gewünschte Sprache /// Fallback Sprache /// Sollen gelöschte inkludiert werden? /// Liste von Ländern nach Filter /// Liste betroffener News public IQueryable FilterWithNames(string filter, List countries, List states, string language, string fallback, bool includeDeleted) { language = language.ToUpperInvariant(); fallback = fallback.ToUpperInvariant(); var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Headline.Contains(filter), language, fallback); if (countries.Any()) baseQuery = baseQuery.Where(c => c.CountryCode != null && c.CountryCode != "" && countries.Contains(c.CountryCode)); if (states.Any()) baseQuery = baseQuery.Where(c => c.State != null && c.State != "" && states.Contains(c.State)); if (!includeDeleted) baseQuery = baseQuery.Where(c => c.Deleted == false); return baseQuery; } /// /// Gibt eine Liste von News-Meldungen für die App zurück. Es werden nur laufende News berücksichtigt /// /// Sichtbar für wen? Wird adaptiert! /// Gewünschte Kategorie oder leer wenn alle /// Land /// Bundesland /// Optional: Breitengrad /// Optional: Längengrad /// Gewünschte Sprache /// Fallback Sprache /// Datensätze auslassen /// Datensätze nehmen /// Liste passender News public async Task<(int total, List list)> GetForAppAsync(NewsVisibility visibility, string categoryId, string country, string state, double? lat, double? lng, string language, string fallback, int skip, int take) { language = language.ToUpperInvariant(); fallback = fallback.ToUpperInvariant(); if(!string.IsNullOrWhiteSpace(country)) country = country.ToUpperInvariant(); if (!string.IsNullOrWhiteSpace(state)) state = state.ToUpperInvariant(); var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326); var location = geometryFactory.CreatePoint(new Coordinate(lng.Value, lat.Value)); var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.CategoryId == categoryId && c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners) && (c.GeoMode == GeoMode.None || (c.GeoMode == GeoMode.Country && c.CountryCode == country) || (c.GeoMode == GeoMode.CountryAndState && c.CountryCode == country && c.State == state) || (c.GeoMode == GeoMode.Location && c.Location.IsWithinDistance(location, c.Radius * 1000))), language, fallback); //if (geoMode == GeoMode.None) //{ // var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.None && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback); // if(!string.IsNullOrEmpty(categoryId)) // baseQuery = baseQuery.Where(c => c.CategoryId == categoryId); // return await baseQuery.ToListAsync().ConfigureAwait(false); //} //else if (geoMode == GeoMode.Country && !string.IsNullOrWhiteSpace(country)) //{ // var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.Country && c.CountryCode == country && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback); // if (!string.IsNullOrEmpty(categoryId)) // baseQuery = baseQuery.Where(c => c.CategoryId == categoryId); // return await baseQuery.ToListAsync().ConfigureAwait(false); //} //else if (geoMode == GeoMode.CountryAndState && !string.IsNullOrWhiteSpace(country) && !string.IsNullOrWhiteSpace(state)) //{ // var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.CountryAndState && c.CountryCode == country && c.State == state && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback); // if (!string.IsNullOrEmpty(categoryId)) // baseQuery = baseQuery.Where(c => c.CategoryId == categoryId); // return await baseQuery.ToListAsync().ConfigureAwait(false); //} //else if(geoMode == GeoMode.Location && lat.HasValue && lng.HasValue) //{ // //Lokalisierungsmodus --> Andere Abfrage weil wir die Distanz zu den Geokoordinaten brauchen // var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326); // var location = geometryFactory.CreatePoint(new Coordinate(lng.Value, lat.Value)); // var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.Location && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback); // baseQuery = baseQuery.Where(c => c.Location.IsWithinDistance(location, c.Radius * 1000)); // if (!string.IsNullOrEmpty(categoryId)) // baseQuery = baseQuery.Where(c => c.CategoryId == categoryId); // return await baseQuery.ToListAsync().ConfigureAwait(false); // //var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNamesDistance({0},{1},{2},{3})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.Location && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback, lat.Value, lng.Value); // //if (!string.IsNullOrEmpty(categoryId)) // // baseQuery = baseQuery.Where(c => c.CategoryId == categoryId); // //return await baseQuery.ToListAsync().ConfigureAwait(false); //} var total = await baseQuery.CountAsync().ConfigureAwait(false); var list = await baseQuery.OrderByDescending(c => c.Start).ThenBy(c => c.Location.Distance(location)).Skip(skip).Take(take).ToListAsync().ConfigureAwait(false); return (total, list); } /// /// Gibt eine News mit Sprachen aufgelöst zurück /// /// Id der News /// Gewünschte Sprache /// Fallback Sprache /// News mit Namen aufgelöst public async Task GetWithNamesAsync(long newsId, string language, string fallback) { language = language.ToUpperInvariant(); fallback = fallback.ToUpperInvariant(); var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Id == newsId, language, fallback); return await baseQuery.FirstOrDefaultAsync().ConfigureAwait(false); } /// /// Starten von freigegebenen News wenn diese das Start-Datum erreicht haben /// /// Anzahl gestartete News public async Task StartApprovedAsnyc() { var items = await Repository.FindAsync(c => c.Status == NewsStatus.Approved && c.Deleted == false && c.Start <= DateTimeOffset.UtcNow && c.End.Value >= DateTimeOffset.UtcNow); foreach (var item in items) { item.Status = NewsStatus.Running; } return items.Count(); } /// /// Stoppen von abgelaufenen News wenn diese das Enddatum erreicht haben /// /// Anzahl gestoppte News public async Task StopRunningAsync() { var items = await Repository.FindAsync(c => c.Status == NewsStatus.Running && c.Deleted == false && c.End.Value <= DateTimeOffset.UtcNow); foreach (var item in items) { item.Status = NewsStatus.Ended; } return items.Count(); } } }