| | | 1 | | using System.Collections.Generic; |
| | | 2 | | using System.Linq; |
| | | 3 | | using System.Threading.Tasks; |
| | | 4 | | using Microsoft.EntityFrameworkCore; |
| | | 5 | | using Microsoft.Extensions.Logging; |
| | | 6 | | using WinSolutions.Sveta.Server.Data.DataModel.Contexts; |
| | | 7 | | using WinSolutions.Sveta.Server.Data.DataModel.Entities; |
| | | 8 | | using WinSolutions.Sveta.Server.Data.DataModel.Kinds; |
| | | 9 | | using WinSolutions.Sveta.Server.Services.Interfaces; |
| | | 10 | | using WinSolutions.Sveta.Common; |
| | | 11 | | using System; |
| | | 12 | | using WinSolutions.Sveta.Common.Extensions; |
| | | 13 | | |
| | | 14 | | namespace WinSolutions.Sveta.Server.Services.Implements |
| | | 15 | | { |
| | | 16 | | |
| | | 17 | | public class ContragentService : SvetaServiceBase, IContragentService |
| | | 18 | | { |
| | | 19 | | private readonly SvetaDbContext _db; |
| | | 20 | | private readonly ILogger<ContragentService> _logger; |
| | | 21 | | private readonly IAuthenticationService _authenticationService; |
| | | 22 | | private readonly ICommonContragentService _commonContragentService; |
| | | 23 | | private readonly ISupplyContractService _contractService; |
| | | 24 | | public ContragentService(SvetaDbContext db, ILogger<ContragentService> logger, ICommonContragentService commonCo |
| | 186 | 25 | | : base(authenticationService) |
| | 186 | 26 | | { |
| | 186 | 27 | | _commonContragentService = commonContragentService; |
| | 186 | 28 | | _contractService = contractService; |
| | 186 | 29 | | _authenticationService = authenticationService; |
| | 186 | 30 | | _db = db; |
| | 186 | 31 | | _logger = logger; |
| | 186 | 32 | | } |
| | | 33 | | |
| | | 34 | | /// <summary> |
| | | 35 | | /// получает КА по id |
| | | 36 | | /// </summary> |
| | | 37 | | /// <param name="contragentId">id KA</param> |
| | | 38 | | /// <returns>контрагент</returns> |
| | 703 | 39 | | public async Task<Contragent> GetContragent(long contragentId) => await _db.Contragents |
| | 703 | 40 | | .Include(x => x.JuridicAddress) |
| | 703 | 41 | | .Include(x => x.PhysicAddress) |
| | 703 | 42 | | .Include(d => d.ContragentsKind) |
| | 703 | 43 | | .Include(d => d.RecState) |
| | 703 | 44 | | .Include(d => d.Owner) |
| | 703 | 45 | | .Include(x => x.BankAccounts) |
| | 703 | 46 | | .Include(d => d.Departments) |
| | 703 | 47 | | .ThenInclude(department => department.Cluster) |
| | 703 | 48 | | .FirstOrDefaultAsync(e => e.Id == contragentId && !e.IsDeleted); |
| | | 49 | | |
| | | 50 | | /// <summary> |
| | | 51 | | /// предварительная выборка КА |
| | | 52 | | /// </summary> |
| | | 53 | | /// <param name="filter"></param> |
| | | 54 | | /// <returns></returns> |
| | 8 | 55 | | private IQueryable<Contragent> PrepareContragents(string filter = null) => _db.Contragents |
| | 8 | 56 | | .Include(x => x.JuridicAddress) |
| | 8 | 57 | | .Include(x => x.PhysicAddress) |
| | 8 | 58 | | .Include(d => d.ContragentsKind) |
| | 8 | 59 | | .Include(d => d.RecState) |
| | 8 | 60 | | .Include(d => d.Owner) |
| | 8 | 61 | | // .Include(d => d.TaxSystem) |
| | 8 | 62 | | .Include(x => x.BankAccounts) |
| | 8 | 63 | | .Where(x => string.IsNullOrWhiteSpace(filter) || x.ShortName.ToUpper().Contains(filter.ToUpper()) || x.F |
| | 8 | 64 | | .OrderBy(x => x.ShortName) |
| | 8 | 65 | | .Where(e => !e.IsDeleted && e.Id > 0); |
| | | 66 | | |
| | | 67 | | /// <summary> |
| | | 68 | | /// Получает список КА с пагинацией |
| | | 69 | | /// </summary> |
| | | 70 | | /// <param name="page">номер страницы</param> |
| | | 71 | | /// <param name="limit">размер страницы</param> |
| | | 72 | | /// <param name="filter">фильтр по короткому/полному наименованию</param> |
| | | 73 | | /// <param name="sort">сортировка</param> |
| | | 74 | | /// <returns></returns> |
| | | 75 | | public async Task<List<Contragent>> GetContragents(int page, int? limit, string filter = null, string sort = "") |
| | 1 | 76 | | { |
| | 1 | 77 | | var items = PrepareContragents(filter).AsNoTracking(); |
| | 1 | 78 | | if (!_authenticationService.IsUserPlatform()) |
| | 0 | 79 | | items= items.Where(x => x.Id == _authenticationService.ContragentId); |
| | 1 | 80 | | items = Sort(items, sort?.ToLower()); |
| | 1 | 81 | | items = limit != null ? items.Skip(page * (int)limit).Take((int)limit) : items; |
| | | 82 | | |
| | 1 | 83 | | return await items.ToListAsync(); |
| | 1 | 84 | | } |
| | | 85 | | |
| | | 86 | | /// <summary> |
| | | 87 | | /// Выводит список уникальных КА поставщиков, которые встречаются в заявках/отгрузках для переданного КА. КА мож |
| | | 88 | | /// </summary> |
| | | 89 | | /// <param name="contragentId">id контрагента, для которого выбираем уникальные записи КА поставщиков в докумен |
| | | 90 | | /// <param name="movementKind">тип документов, в которых искать</param> |
| | | 91 | | /// <returns></returns> |
| | 0 | 92 | | public async Task<List<Contragent>> GetFilteredListByMovementSupplier(long contragentId, MovementKind movementKi |
| | 0 | 93 | | .Include(x => x.MovementsAsCustomer).ThenInclude(MovementsAsCustomer => MovementsAsCustomer.Customer) |
| | 0 | 94 | | .Include(x => x.MovementsAsSupplier).ThenInclude(MovementsAsSupplier => MovementsAsSupplier.Supplier) |
| | 0 | 95 | | .Include(x => x.MovementsAsSupplier).ThenInclude(MovementsAsSupplier => MovementsAsSupplier.MovementStatus) |
| | 0 | 96 | | .Include(x => x.MovementsAsSupplier).ThenInclude(MovementsAsSupplier => MovementsAsSupplier.MovementType) |
| | 0 | 97 | | .Where(x => !x.IsDeleted) |
| | 0 | 98 | | // В зависимости от того, какой тип у переданного КА, ищем либо в покупателях, либо в продавцах. Ведь КА не |
| | 0 | 99 | | .Where(x => x.MovementsAsSupplier.Any(p => !p.IsDeleted && p.MovementType.Id == (int)movementKind && ((contr |
| | 0 | 100 | | .Distinct() |
| | 0 | 101 | | .ToListAsync(); |
| | | 102 | | |
| | | 103 | | /// <summary> |
| | | 104 | | /// Выводит список уникальных КА покупателей, которые встречаются в заявках/отгрузках для переданного КА. КА мож |
| | | 105 | | /// </summary> |
| | | 106 | | /// <param name="contragentId">id контрагента, для которого выбираем уникальные записи КА покупателей в документ |
| | | 107 | | /// <param name="movementKind">тип документов, в которых искать</param> |
| | | 108 | | /// <returns></returns> |
| | 0 | 109 | | public async Task<List<Contragent>> GetFilteredListByMovementCustomer(long contragentId, MovementKind movementKi |
| | 0 | 110 | | .Include(x => x.MovementsAsCustomer).ThenInclude(MovementsAsCustomer => MovementsAsCustomer.MovementStatus) |
| | 0 | 111 | | .Include(x => x.MovementsAsCustomer).ThenInclude(MovementsAsCustomer => MovementsAsCustomer.MovementType) |
| | 0 | 112 | | .Include(x => x.MovementsAsCustomer).ThenInclude(MovementsAsCustomer => MovementsAsCustomer.Customer) |
| | 0 | 113 | | .Include(x => x.MovementsAsSupplier).ThenInclude(MovementsAsSupplier => MovementsAsSupplier.Supplier) |
| | 0 | 114 | | .Where(x => !x.IsDeleted) |
| | 0 | 115 | | // В зависимости от того, какой тип у переданного КА, ищем либо в покупателях, либо в продавцах. Ведь КА не |
| | 0 | 116 | | .Where(x => x.MovementsAsCustomer.Any(p => !p.IsDeleted && p.MovementType.Id == (int)movementKind && ((contr |
| | 0 | 117 | | .Distinct() |
| | 0 | 118 | | .ToListAsync(); |
| | | 119 | | |
| | | 120 | | /// <summary> |
| | | 121 | | /// Возвращает пользователей КА с переданным типом |
| | | 122 | | /// </summary> |
| | | 123 | | /// <param name="kind">тип КА</param> |
| | | 124 | | /// <returns></returns> |
| | | 125 | | public async Task<List<User>> GetContragentUsers(ContragentKind kind) => |
| | 0 | 126 | | await PrepareContragents().Where(d => d.ContragentsKind.Id == (long) kind) |
| | 0 | 127 | | .SelectMany(d => d.User) |
| | 0 | 128 | | .ToListAsync(); |
| | | 129 | | |
| | | 130 | | /// <summary> |
| | | 131 | | /// Возвращает список контрагентов-партнеров с сокращенным набором полей с пагинацией и фильтрами |
| | | 132 | | /// </summary> |
| | | 133 | | /// <param name="page">номер страницы </param> |
| | | 134 | | /// <param name="limit">размер страницы </param> |
| | | 135 | | /// <param name="filter">фильтр по значимым полям FullName / ShortName</param> |
| | | 136 | | /// <param name="sort">сортировка по умолчанию по id - id|desc, created_on,created_on|desc, state,state|desc, st |
| | | 137 | | /// <param name="supplyOwner">true, если владелец поставщика. По умолчанию false</param> |
| | | 138 | | public async Task<List<Contragent>> GetShortContragents(int page, int? limit, string filter = null, string sort |
| | 0 | 139 | | { |
| | 0 | 140 | | var items = PrepareContragents(filter).AsNoTracking(); |
| | 0 | 141 | | if (supplyOwner) //если директор поставщика |
| | 0 | 142 | | items = items.Where(x => x.ContragentsKind.Id == (long)ContragentKind.Retailer || x.ContragentsKind.Id = |
| | 0 | 143 | | .Where(x=>x.Id != _authenticationService.ContragentId); |
| | | 144 | | else |
| | 0 | 145 | | { //иначе выбираем всех КА на основе контрактов с нашим КА |
| | 0 | 146 | | var contracts = await _contractService.GetSupplyContractsByContragent(_authenticationService.ContragentI |
| | 0 | 147 | | List<long> contragents = new List<long>() { }; |
| | 0 | 148 | | foreach (var item in contracts) //выбираем партнеров |
| | 0 | 149 | | { |
| | 0 | 150 | | contragents.Add(item.Seller.Id); |
| | 0 | 151 | | contragents.Add(item.Buyer.Id); |
| | 0 | 152 | | } |
| | 0 | 153 | | contragents = contragents.Distinct().Where(x=> x != _authenticationService.ContragentId).ToList(); // ос |
| | | 154 | | //выбираем КА, у которых КА из этого массива |
| | 0 | 155 | | items = items.Where(x => contragents.Any(p => p == x.Id)); |
| | 0 | 156 | | } |
| | 0 | 157 | | items = Sort(items, sort?.ToLower()); |
| | 0 | 158 | | items = limit != null ? items.Skip(page * (int)limit).Take((int)limit) : items; |
| | | 159 | | |
| | 0 | 160 | | return await items.ToListAsync(); |
| | 0 | 161 | | } |
| | | 162 | | |
| | | 163 | | /// <summary> |
| | | 164 | | /// создает КА |
| | | 165 | | /// </summary> |
| | | 166 | | /// <param name="contragentIn">КА</param> |
| | | 167 | | /// <returns></returns> |
| | | 168 | | public async Task CreateContragent(Contragent contragentIn) |
| | 571 | 169 | | { |
| | 571 | 170 | | await _commonContragentService.Create(contragentIn, CurrentUserId); |
| | 571 | 171 | | } |
| | | 172 | | |
| | | 173 | | /// <summary> |
| | | 174 | | /// Обновляет КА |
| | | 175 | | /// </summary> |
| | | 176 | | /// <param name="contragentIn">КА</param> |
| | | 177 | | /// <returns></returns> |
| | | 178 | | public async Task UpdateContragent(Contragent contragentIn) |
| | 370 | 179 | | { |
| | 370 | 180 | | await _commonContragentService.Update(contragentIn, CurrentUserId); |
| | 370 | 181 | | } |
| | | 182 | | |
| | | 183 | | /// <summary> |
| | | 184 | | /// получает КА на основе ТТ |
| | | 185 | | /// </summary> |
| | | 186 | | /// <param name="departmentId">ТТ</param> |
| | | 187 | | /// <returns></returns> |
| | 0 | 188 | | public async Task<Contragent> GetContragentByWareouse(long departmentId) => await PrepareContragents() |
| | 0 | 189 | | .Where(x => x.Departments.Any(p => p.Id == departmentId)).FirstOrDefaultAsync(); |
| | | 190 | | |
| | | 191 | | /// <summary> |
| | | 192 | | /// удаляет КА по id |
| | | 193 | | /// </summary> |
| | | 194 | | /// <param name="contragentId">id КА</param> |
| | | 195 | | /// <returns></returns> |
| | | 196 | | public async Task DeleteContragent(long contragentId) |
| | 1 | 197 | | { |
| | 1 | 198 | | Contragent rec = await _db.Contragents.FindAsync(contragentId); |
| | 1 | 199 | | if (rec == null) |
| | 0 | 200 | | throw new KeyNotFoundException($"Контрагент с id={contragentId} не найден"); |
| | 1 | 201 | | rec.IsDeleted = true; |
| | 1 | 202 | | await _db.SaveChangesAsync(CurrentUserId); |
| | 1 | 203 | | } |
| | | 204 | | |
| | | 205 | | /// <summary> |
| | | 206 | | /// проверяет существование КА |
| | | 207 | | /// </summary> |
| | | 208 | | /// <param name="contragentId">id КА</param> |
| | | 209 | | /// <returns></returns> |
| | 0 | 210 | | public async Task<bool> ContragentExists(long contragentId) => await _db.Contragents |
| | 0 | 211 | | .AsNoTracking() |
| | 0 | 212 | | .Where(e => e.Id == contragentId) |
| | 0 | 213 | | .Where(e => !e.IsDeleted) |
| | 0 | 214 | | .AnyAsync(); |
| | | 215 | | |
| | | 216 | | /// <summary> |
| | | 217 | | /// получает КА по короткому/полному названию |
| | | 218 | | /// </summary> |
| | | 219 | | /// <param name="name">название</param> |
| | | 220 | | /// <returns></returns> |
| | 3 | 221 | | public async Task<Contragent> GetContragentByName(string name) => await PrepareContragents() |
| | 3 | 222 | | .AsNoTracking() |
| | 3 | 223 | | .FirstOrDefaultAsync(d => d.FullName.Contains(name.NormalizeName()) || d.ShortName.Contains(name.NormalizeNa |
| | | 224 | | |
| | | 225 | | /// <summary> |
| | | 226 | | /// получает список КА на основе типа с пагинацией и фильтрацией |
| | | 227 | | /// </summary> |
| | | 228 | | /// <param name="page">номер страницы</param> |
| | | 229 | | /// <param name="limit">размер страницы</param> |
| | | 230 | | /// <param name="kind">тип КА</param> |
| | | 231 | | /// <param name="filter">фильтр по короткому/полному названию</param> |
| | | 232 | | /// <param name="sort">сортировка</param> |
| | | 233 | | /// <returns></returns> |
| | | 234 | | public async Task<List<Contragent>> GetContragentsByKind(int page, int limit, ContragentKind kind, string filter |
| | 3 | 235 | | { |
| | 3 | 236 | | var items = PrepareContragents(filter) |
| | 3 | 237 | | .Where(d => d.ContragentsKind.Id == (int)kind); |
| | 3 | 238 | | if ((_authenticationService.IsUserWholesaler() && kind == ContragentKind.Wholesaler) || (_authenticationServ |
| | 0 | 239 | | items = items.Where(x => x.Id == _authenticationService.ContragentId); |
| | | 240 | | |
| | 3 | 241 | | items = Sort(items, sort?.ToLower()); |
| | | 242 | | |
| | 3 | 243 | | return await items |
| | 3 | 244 | | .Skip(page * limit) |
| | 3 | 245 | | .Take(limit) |
| | 3 | 246 | | .ToListAsync(); |
| | 3 | 247 | | } |
| | | 248 | | |
| | | 249 | | /// <summary> |
| | | 250 | | /// получатет список КА на основе типа |
| | | 251 | | /// </summary> |
| | | 252 | | /// <param name="kind">тип КА</param> |
| | | 253 | | /// <returns></returns> |
| | 1 | 254 | | public async Task<List<Contragent>> GetContragents(ContragentKind kind) => await PrepareContragents().Where(d => |
| | | 255 | | |
| | | 256 | | /// <summary> |
| | | 257 | | /// Сортирует Contragent по полям |
| | | 258 | | /// </summary> |
| | | 259 | | /// <param name="items"></param> |
| | | 260 | | /// <param name="sort">сортировка по умолчанию |
| | | 261 | | /// по id - id|desc, |
| | | 262 | | /// created_on,created_on|desc, |
| | | 263 | | /// state,state|desc, |
| | | 264 | | /// status,status|desc, |
| | | 265 | | /// fullName,fullName|desc |
| | | 266 | | /// shortName,shortName|desc |
| | | 267 | | /// Owner,Owner|desc</param> |
| | | 268 | | /// <returns></returns> |
| | 4 | 269 | | private IQueryable<Contragent> Sort(IQueryable<Contragent> items, string sort = default) => (sort ?? "").ToLower |
| | 4 | 270 | | { |
| | 4 | 271 | | "created_on" => items.OrderBy(d => d.CreationDateTime), |
| | 4 | 272 | | "created_on|desc" => items.OrderByDescending(d => d.CreationDateTime), |
| | 4 | 273 | | "state" => items.OrderBy(d => d.RecState.Id), |
| | 4 | 274 | | "state|desc" => items.OrderByDescending(d => d.RecState.Id), |
| | 4 | 275 | | "fullName" => items.OrderBy(d => d.FullName), |
| | 4 | 276 | | "fullName|desc" => items.OrderByDescending(d => d.FullName), |
| | 4 | 277 | | "shortName" => items.OrderBy(d => d.ShortName), |
| | 4 | 278 | | "shortName|desc" => items.OrderByDescending(d => d.ShortName), |
| | 4 | 279 | | "Owner" => items.OrderBy(d => d.Owner), |
| | 4 | 280 | | "Owner|desc" => items.OrderByDescending(d => d.Owner), |
| | 4 | 281 | | "id|desc" => items.OrderByDescending(d => d.Id), |
| | 4 | 282 | | _ => items.OrderBy(d => d.Id), |
| | 4 | 283 | | }; |
| | | 284 | | |
| | | 285 | | /// <summary> |
| | | 286 | | /// получает контрагента с джоиниными контрактами |
| | | 287 | | /// </summary> |
| | | 288 | | /// <param name="contragentId">id КА</param> |
| | | 289 | | /// <returns></returns> |
| | | 290 | | public async Task<Contragent> GetContragentWithContracts(long contragentId) |
| | 0 | 291 | | { |
| | 0 | 292 | | return await _db.Contragents |
| | 0 | 293 | | .AsNoTracking() |
| | 0 | 294 | | .Include(x => x.BankAccounts) |
| | 0 | 295 | | .Include(d => d.JuridicAddress) |
| | 0 | 296 | | .Include(d => d.ContragentsKind) |
| | 0 | 297 | | .Include(d => d.RecState) |
| | 0 | 298 | | .Include(d => d.PhysicAddress) |
| | 0 | 299 | | .Include(d => d.Owner) |
| | 0 | 300 | | // .Include(d => d.TaxSystem) |
| | 0 | 301 | | .Include(d => d.User) |
| | 0 | 302 | | .Include(x => x.ContractsAsSeller).ThenInclude(x => x.Buyer) |
| | 0 | 303 | | .Include(x => x.ContractsAsBuyer).ThenInclude(x => x.Seller) |
| | 0 | 304 | | .Where(e => !e.IsDeleted && e.Id == contragentId) |
| | 0 | 305 | | .FirstOrDefaultAsync(); |
| | 0 | 306 | | } |
| | | 307 | | |
| | | 308 | | |
| | | 309 | | } |
| | | 310 | | } |