< Summary

Class:WinSolutions.Sveta.Server.Services.Implements.DepartmentService
Assembly:WinSolutions.Sveta.Server
File(s):/opt/dev/sveta_api_build/WinSolutions.Sveta.Server/Services/Implements/DepartmentService.cs
Covered lines:111
Uncovered lines:58
Coverable lines:169
Total lines:356
Line coverage:65.6% (111 of 169)
Covered branches:36
Total branches:82
Branch coverage:43.9% (36 of 82)

Metrics

MethodLine coverage Branch coverage
.ctor(...)100%100%
GetDeparments()100%62.5%
GetDepartment()0%100%
GetDeparmentsList()0%0%
GetAllDepartments()0%100%
FindDepartments()0%100%
PrepareDepartments()100%100%
PrepareSingleDepartment()100%100%
GetDepartment()100%100%
GetFilteredListByMovementSender()0%100%
GetFilteredListByMovementReceiver()0%100%
GetDepartment()0%100%
CreateDepartment()100%50%
GetDepartmentsByUserAndKind()100%50%
UpdateDepartment()77.77%62.5%
DeleteDepartment()0%100%
DepartmentExists()100%100%
GetKindType()100%100%
GetStatusType()100%100%
GetDepartmentsByKind()0%0%
GetPlatformDepartment()0%100%
Sort(...)100%43.47%

File(s)

/opt/dev/sveta_api_build/WinSolutions.Sveta.Server/Services/Implements/DepartmentService.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Linq;
 3using System.Threading.Tasks;
 4using Microsoft.EntityFrameworkCore;
 5using Microsoft.Extensions.Logging;
 6using WinSolutions.Sveta.Server.Data.DataModel.Contexts;
 7using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 8using WinSolutions.Sveta.Server.Data.DataModel.Kinds;
 9using WinSolutions.Sveta.Server.Domain;
 10using WinSolutions.Sveta.Server.Services.Interfaces;
 11using WinSolutions.Sveta.Common;
 12using System;
 13using System.Text;
 14using WinSolutions.Sveta.Common.Extensions;
 15using Clave.Expressionify;
 16
 17namespace WinSolutions.Sveta.Server.Services.Implements
 18{
 19    public class DepartmentService : SvetaServiceBase, IDepartmentService
 20    {
 21        private readonly SvetaDbContext _db;
 22        private readonly ILogger<DepartmentService> _logger;
 23        private readonly IAuthenticationService _authenticationService;
 24        private readonly IClusterService _clusterService;
 25        private readonly IUserService _userService;
 26        private readonly ISupplyContractService _contractService;
 27        private readonly INotificationService _notifyService;
 28        private readonly IEmailService _emailService;
 29        private readonly IDirectoriesService _dirService;
 30        private readonly IContragentService _contrService;
 31
 32        public DepartmentService(SvetaDbContext db, ILogger<DepartmentService> logger, IClusterService clusterService, I
 33            IAuthenticationService authenticationService, IUserService userService, IDirectoriesService dirService, ICon
 34        INotificationService notifyService, IEmailService emailService)
 18635            : base(authenticationService)
 18636        {
 18637            _userService = userService;
 18638            _contrService = contrService;
 18639            _emailService = emailService;
 18640            _dirService = dirService;
 18641            _notifyService = notifyService;
 18642            _clusterService = clusterService;
 18643            _contractService = contractService;
 18644            _db = db;
 18645            _authenticationService = authenticationService;
 18646            _logger = logger;
 18647        }
 48
 49        /// <summary>
 50        ///получает список подразделений с пагинацией
 51        /// </summary>
 52        /// <param name="contragentId">id КА. Если 0, то по всем в рамках ролевой модели</param>
 53        /// <param name="page">номер страницы</param>
 54        /// <param name="limit">размер страницы</param>
 55        /// <param name="filter">фильтр по названию, адресу, телефону</param>
 56        /// <param name="sort">сортировка</param>
 57        /// <returns></returns>
 58        public async Task<PaginatedData<List<Department>>> GetDeparments(long contragentId, int page, int? limit, string
 56359        {
 56360            var departments = PrepareDepartments().AsNoTracking();
 61            // Тотал записей для смертных считаем после прмиенения ограничения роли
 56362            int total = await departments?.CountAsync(x => _authenticationService.IsUserPlatform() || x.Contragent.Id ==
 56363            departments = departments.Where(x => contragentId == 0 || x.Contragent.Id == contragentId)
 56364                .Where(x => string.IsNullOrWhiteSpace(filter) || x.Name.ToUpper().Contains(filter.ToUpper()) || x.PhoneN
 56365            departments = Sort(departments, sort?.ToLower());
 56366            int filtered = await departments?.CountAsync();
 56367            if (limit != null)
 56368                departments = departments.Skip(page * (int)limit).Take((int)limit);
 56369            return new PaginatedData<List<Department>>
 56370            {
 56371                Result = await departments.ToListAsync(),
 56372                TotalCount = total,
 56373                TotalFilteredCount = filtered
 56374            };
 56375        }
 76
 77        /// <summary>
 78        /// получить подразделение по id КА и типу подразделения
 79        /// </summary>
 80        /// <param name="contragentId">id KA</param>
 81        /// <param name="kind">тип подразделения</param>
 82        /// <returns></returns>
 83        public async Task<Department> GetDepartment(long contragentId, DepartmentKind kind) =>
 084            await _db.Departments
 085                .Include(d => d.Kind)
 086                .Include(d => d.Contragent)
 087                .FirstOrDefaultAsync(d =>
 088                !d.IsDeleted && d.Contragent.Id == contragentId && d.Kind.Id == (long) kind);
 89
 90        /// <summary>
 91        /// получить список подразделений, к которым привязан текущий юзер
 92        /// </summary>
 93        /// <returns></returns>
 94        public async Task<List<Department>> GetDeparmentsList()
 095        {
 096            var departments = PrepareDepartments().AsNoTracking();
 097            if (!_authenticationService.IsUserPlatform())
 098                departments = departments.Where(x => x.UsersDepartments.Any(p => p.UserId == _authenticationService.User
 099            return await departments.ToListAsync();
 0100        }
 101
 102        /// <summary>
 103        /// получить список всех подразделений
 104        /// </summary>
 105        /// <returns></returns>
 106        public async Task<List<Department>> GetAllDepartments()
 0107        {
 0108            return await PrepareDepartments().ToListAsync();
 0109        }
 110
 111        /// <summary>
 112        /// найти подразделение по названию
 113        /// </summary>
 114        /// <param name="name">название подразделения</param>
 115        /// <returns></returns>
 116        public async Task<List<Department>> FindDepartments(string name)
 0117            => await _db.Departments.Where(e => !e.IsDeleted && e.Name.ToLower() == name.NormalizeName().ToLower()).ToLi
 118
 119        /// <summary>
 120        /// предварительная выборка подразделения
 121        /// </summary>
 122        /// <returns></returns>
 564123        private IQueryable<Department> PrepareDepartments() => _db.Departments
 564124            .Include(e => e.Contragent)
 564125            .ThenInclude(Contragent => Contragent.Owner)
 564126            .Include(e => e.UsersDepartments)
 564127            .ThenInclude(UsersDepartments => UsersDepartments.User)
 564128            .Include(x => x.Kind)
 564129            .Include(x => x.Status)
 564130            .Include(x => x.RecState)
 564131            .Include(x => x.ActualAddress)
 564132            .Include(x => x.Cluster).ThenInclude(x => x.Warehouse)
 564133            .Where(e => !e.IsDeleted)
 564134            .AsQueryable();
 135
 136        /// <summary>
 137        /// предварительная выборка одного подразделения
 138        /// </summary>
 139        /// <returns></returns>
 452140        private IQueryable<Department> PrepareSingleDepartment() => _db.Departments
 452141            .Include(e => e.Contragent)
 452142            .ThenInclude(Contragent => Contragent.Owner)
 452143            .Include(e => e.UsersDepartments)
 452144            .ThenInclude(UsersDepartments => UsersDepartments.User)
 452145            .Include(x => x.Kind)
 452146            .Include(x => x.Status)
 452147            .Include(x => x.RecState)
 452148            .Include(x => x.ActualAddress)
 452149            .Include(x => x.Cluster).ThenInclude(x => x.Warehouse)
 452150            .Include(x => x.Cluster).ThenInclude(Cluster => Cluster.ClusterDeliveryTypes).ThenInclude(ClusterDeliveryTyp
 452151            .Where(e => !e.IsDeleted)
 452152            .AsQueryable();
 153
 154        /// <summary>
 155        /// получить подразделение по id
 156        /// </summary>
 157        /// <param name="departmentId">id подразделения</param>
 158        /// <returns></returns>
 452159        public async Task<Department> GetDepartment(long departmentId) => await PrepareSingleDepartment().FirstOrDefault
 160
 161        /// <summary>
 162        /// Выводит список уникальных складов-отправителей, которые встречаются в заявках/отгрузках для переданного КА. 
 163        /// </summary>
 164        /// <param name="contragentId">id контрагента, для которого выбираем уникальные записи складов в документах</par
 165        /// <param name="movementKind">тип документов, в которых искать</param>
 166        /// <returns></returns>
 0167        public async Task<List<Department>> GetFilteredListByMovementSender(long contragentId, MovementKind movementKind
 0168            .Include(x => x.MovementsAsSender).ThenInclude(MovementsAsSender => MovementsAsSender.Customer)
 0169            .Include(x => x.MovementsAsSender).ThenInclude(MovementsAsSender => MovementsAsSender.Supplier)
 0170            .Include(x => x.MovementsAsSender).ThenInclude(MovementsAsSender => MovementsAsSender.MovementType)
 0171            .Include(x => x.MovementsAsSender).ThenInclude(MovementsAsSender => MovementsAsSender.MovementStatus)
 0172            .Where(x => !x.IsDeleted)
 0173            // В зависимости от того, какой тип у переданного КА, ищем либо в покупателях, либо в продавцах. Ведь КА не 
 0174            .Where(x => x.MovementsAsSender.Any(p => !p.IsDeleted && p.MovementType.Id == (int)movementKind && ((contrag
 0175            .Distinct()
 0176            .ToListAsync();
 177
 178        /// <summary>
 179        /// Выводит список уникальных магазинов-получателей, которые встречаются в заявках/отгрузках для переданного КА.
 180        /// </summary>
 181        /// <param name="contragentId">id контрагента, для которого выбираем уникальные записи магазинов в документах</p
 182        /// <param name="movementKind">тип документов, в которых искать</param>
 183        /// <returns></returns>
 0184        public async Task<List<Department>> GetFilteredListByMovementReceiver(long contragentId, MovementKind movementKi
 0185            .Include(x => x.MovementsAsReceiver).ThenInclude(MovementsAsReceiver => MovementsAsReceiver.Customer)
 0186            .Include(x => x.MovementsAsReceiver).ThenInclude(MovementsAsReceiver => MovementsAsReceiver.Supplier)
 0187            .Include(x => x.MovementsAsReceiver).ThenInclude(MovementsAsReceiver => MovementsAsReceiver.MovementType)
 0188            .Include(x => x.MovementsAsReceiver).ThenInclude(MovementsAsReceiver => MovementsAsReceiver.MovementStatus)
 0189            .Where(x => !x.IsDeleted)
 0190            // В зависимости от того, какой тип у переданного КА, ищем либо в покупателях, либо в продавцах. Ведь КА не 
 0191            .Where(x => x.MovementsAsReceiver.Any(p => !p.IsDeleted && p.MovementType.Id == (int)movementKind && ((contr
 0192            .Distinct()
 0193            .ToListAsync();
 194
 195        /// <summary>
 196        /// получить подразделения по id подразделения и id KA
 197        /// </summary>
 198        /// <param name="departmentId">id подразделения</param>
 199        /// <param name="contragentId">id KA</param>
 200        /// <returns></returns>
 201        public async Task<Department> GetDepartment(long departmentId, long contragentId)
 0202            => await PrepareSingleDepartment().FirstOrDefaultAsync(e => e.Id == departmentId && e.Contragent.Id == contr
 203
 204        /// <summary>
 205        /// создать подразделение
 206        /// </summary>
 207        /// <param name="departmentIn">подразделение</param>
 208        /// <returns></returns>
 209        public async Task CreateDepartment(Department departmentIn)
 561210        {
 561211            _db.Entry(departmentIn.Kind).State = departmentIn.Kind.Id == 0 ? EntityState.Detached : EntityState.Unchange
 561212            _db.Entry(departmentIn.Contragent).State = departmentIn.Contragent.Id == 0 ? EntityState.Detached : EntitySt
 561213            _db.Entry(departmentIn.Status).State = departmentIn.Status.Id == 0 ? EntityState.Detached : EntityState.Unch
 561214            await _db.Departments.AddAsync(departmentIn);
 561215            await _db.SaveChangesAsync(CurrentUserId);
 561216        }
 217
 218        /// <summary>
 219        /// получить подразделения по привязке юзера и типу подразделения
 220        /// </summary>
 221        /// <param name="userId">id юзера</param>
 222        /// <param name="kind">тип подразделения</param>
 223        /// <param name="sort">сортировка</param>
 224        /// <returns></returns>
 225        public async Task<List<Department>> GetDepartmentsByUserAndKind(long userId, DepartmentKind kind, string sort)
 1226        {
 1227            var data = _db.Departments
 1228            //.AsNoTracking()
 1229            .Include(d => d.Contragent)
 1230            .ThenInclude(Contragent => Contragent.Owner)
 1231            .Include(d => d.Contragent)
 1232            .ThenInclude(Contragent => Contragent.ContractsAsBuyer)
 1233            .Include(d => d.Cluster)
 1234            .Include(d => d.Kind)
 1235            .Include(x => x.Status)
 1236            .Include(x => x.RecState)
 1237            .Include(d => d.ActualAddress)
 1238            .Include(d => d.UsersDepartments)
 1239            .Where(e => e.Kind.Id == (int)kind)
 1240            .Where(e => !e.IsDeleted && e.UsersDepartments.Any(x => x.UserId == userId));
 1241            data = Sort(data, sort?.ToLower());
 242
 1243            return await data.ToListAsync();
 1244        }
 245
 246        /// <summary>
 247        ///обновить подразделение
 248        /// </summary>
 249        /// <param name="departmentIn">подразделение</param>
 250        /// <returns></returns>
 251        public async Task UpdateDepartment(Department departmentIn)
 1252        {
 1253            if (!(await DepartmentExists(departmentIn.Id)))
 0254            {
 0255                throw new ArgumentException($"Департамент с именем {departmentIn.Name} не найден");
 256            }
 1257            if (departmentIn.ActualAddress != null)
 1258                _db.Entry(departmentIn.ActualAddress).State = departmentIn.ActualAddress.Id == 0 ? EntityState.Added : E
 1259            _db.Departments.Update(departmentIn);
 1260            await _db.SaveChangesAsync(CurrentUserId);
 1261        }
 262
 263        /// <summary>
 264        ///удалить подразделение
 265        /// </summary>
 266        /// <param name="department">подразделение</param>
 267        /// <returns></returns>
 268        public async Task DeleteDepartment(Department department)
 0269        {
 0270            department.IsDeleted = true;
 0271            await _db.SaveChangesAsync(CurrentUserId);
 0272        }
 273
 274        /// <summary>
 275        /// проверить существование подразделения
 276        /// </summary>
 277        /// <param name="departmentId">id подразделения</param>
 278        /// <returns></returns>
 1279        public async Task<bool> DepartmentExists(long departmentId) => await PrepareDepartments().AnyAsync(e => e.Id == 
 280
 281        /// <summary>
 282        ///получить типы подразделений
 283        /// </summary>
 284        /// <param name="contragentId">id контрагента. Если 0 , то выводить все типы, иначе только те типы подразделений
 285        /// <returns></returns>
 1286        public async Task<List<DepartmentsKind>> GetKindType(long contragentId) => await _db.refDepartmentsKind
 1287            //.AsNoTracking()
 1288            .Include(x => x.ContragentsKind).ThenInclude(ContragentsKind => ContragentsKind.Contragents)
 1289            .Where(e => !e.IsDeleted)
 1290            .Where(e => contragentId == 0 || e.ContragentsKind.Contragents.Any(x => x.Id == contragentId))
 1291            .ToListAsync();
 292
 293        /// <summary>
 294        /// получить статусы подразделений
 295        /// </summary>
 296        /// <returns></returns>
 1297        public async Task<List<DepartmentsStatus>> GetStatusType() => await _db.refDepartmentsStatus
 1298           //.AsNoTracking()
 1299           .Where(e => !e.IsDeleted)
 1300           .ToListAsync();
 301
 302        /// <summary>
 303        /// Получает подразделения на основе типа
 304        /// </summary>
 305        /// <param name="kind">тип подразделения</param>
 306        /// <param name="filter">фильтр по имени подразделения</param>
 307        /// <param name="sort">сортировка</param>
 308        /// <param name="showAll">true, если выводить все подразделения указанного типа, не смотря на ролевую модель. По
 309        /// <returns></returns>
 310        public async Task<List<Department>> GetDepartmentsByKind(/*int page, int limit, */
 311        DepartmentKind kind, string filter, string sort, bool showAll = false)
 0312        {
 0313            var items = PrepareDepartments()
 0314                .AsNoTracking()
 0315                .Where(d => d.Kind.Id == (int)kind)
 0316                .Where(x => string.IsNullOrWhiteSpace(filter) || x.Name.ToLower().Contains(filter.ToLower()));
 0317            if (!_authenticationService.IsUserPlatform() && !showAll)
 0318                items = items.Where(x => x.Contragent.Id == _authenticationService.ContragentId);
 0319            items = Sort(items, sort?.ToLower());
 0320            return await items
 0321                .ToListAsync();
 0322        }
 323
 324        /// <summary>
 325        /// получить подразделения, привязанные к платформе
 326        /// </summary>
 327        /// <returns></returns>
 0328        public async Task<Department> GetPlatformDepartment() => await PrepareDepartments()
 0329            .Include(d => d.Contragent)
 0330            .ThenInclude(Contragent => Contragent.ContragentsKind)
 0331            .Where(x => x.Contragent.ContragentsKind.Id == (long)ContragentKind.Platform && x.Id > 0)
 0332            .FirstOrDefaultAsync();
 333
 334        /// <summary>
 335        /// Сортирует подразделения по полям
 336        /// </summary>
 337        /// <param name="items"></param>
 338        /// <param name="sort">сортировка по умолчанию
 339        /// по id|desc, name,name|desc, kindName,kindName|desc postalAddress,postalAddress|desc  area,area|desc, Сортиро
 340        /// <returns></returns>
 564341        private IQueryable<Department> Sort(IQueryable<Department> items, string sort = default) => (sort ?? "").ToLower
 564342        {
 564343            "name" => items.OrderBy(d => d.Name),
 564344            "name|desc" => items.OrderByDescending(d => d.Name),
 564345            "kindname" => items.OrderBy(d => d.Kind.Name),
 564346            "kindname|desc" => items.OrderByDescending(d => d.Kind.Name),
 564347            "postaladdress" => items.OrderBy(d => d.ActualAddress.FullAddress),
 564348            "postaladdress|desc" => items.OrderByDescending(d => d.ActualAddress.FullAddress),
 564349            "area" => items.OrderBy(d => d.Area),
 564350            "area|desc" => items.OrderByDescending(d => d.Area),
 564351            "id|desc" => items.OrderByDescending(d => d.Id),
 564352            _ => items.OrderBy(d => d.Id),
 564353        };
 354    }
 355
 356}