| | | 1 | | using DocumentFormat.OpenXml.Office2013.PowerPoint.Roaming; |
| | | 2 | | using Microsoft.AspNetCore.Mvc; |
| | | 3 | | using Microsoft.AspNetCore.Server.IIS.Core; |
| | | 4 | | using Microsoft.EntityFrameworkCore.Internal; |
| | | 5 | | using Microsoft.Extensions.Logging; |
| | | 6 | | using SVETA.Api.Data.DTO; |
| | | 7 | | using SVETA.Api.Data.DTO.Cluster; |
| | | 8 | | using SVETA.Api.Data.DTO.DepartmentDTO; |
| | | 9 | | using SVETA.Api.Helpers; |
| | | 10 | | using SVETA.Api.Helpers.Authorize; |
| | | 11 | | using SVETA.Api.Services.Interfaces; |
| | | 12 | | using System; |
| | | 13 | | using System.Collections.Generic; |
| | | 14 | | using System.Linq; |
| | | 15 | | using System.Runtime.InteropServices.WindowsRuntime; |
| | | 16 | | using System.Text; |
| | | 17 | | using System.Threading.Tasks; |
| | | 18 | | using WinSolutions.Sveta.Common; |
| | | 19 | | using WinSolutions.Sveta.Common.Extensions; |
| | | 20 | | using WinSolutions.Sveta.Server.Data.DataModel.Entities; |
| | | 21 | | using WinSolutions.Sveta.Server.Data.DataModel.Kinds; |
| | | 22 | | using WinSolutions.Sveta.Server.Services.Interfaces; |
| | | 23 | | |
| | | 24 | | |
| | | 25 | | |
| | | 26 | | namespace SVETA.Api.Services.Implements |
| | | 27 | | { |
| | | 28 | | public class DepartmentWorker : IDepartmentWorker |
| | | 29 | | { |
| | | 30 | | private readonly IDepartmentService _depService; |
| | | 31 | | private readonly INotificationWorker _notifyWorker; |
| | | 32 | | private readonly ILogger<DepartmentWorker> _logger; |
| | | 33 | | private readonly IAuthenticationService _authenticationService; |
| | | 34 | | private readonly IClusterService _clusterService; |
| | | 35 | | private readonly IUserService _userService; |
| | | 36 | | private readonly ISupplyContractService _contractService; |
| | | 37 | | private readonly INotificationService _notifyService; |
| | | 38 | | private readonly IEmailService _emailService; |
| | | 39 | | private readonly IDirectoriesService _dirService; |
| | | 40 | | private readonly IContragentService _contrService; |
| | | 41 | | private readonly IWorkScheduleService _scheduleService; |
| | | 42 | | private readonly ICategoryService _catService; |
| | | 43 | | private readonly ICategoryRatioService _catRatiosService; |
| | | 44 | | private readonly ITelegramNotificationService _telegramService; |
| | | 45 | | private readonly IMovementRouteService _movementRouteService; |
| | | 46 | | private readonly IAddressService _addressService; |
| | | 47 | | |
| | 185 | 48 | | public DepartmentWorker(ILogger<DepartmentWorker> logger, IClusterService clusterService, ISupplyContractService |
| | 185 | 49 | | IAuthenticationService authenticationService, IUserService userService, IDirectoriesService dirService, ICon |
| | 185 | 50 | | INotificationService notifyService, IEmailService emailService, IDepartmentService depService, INotification |
| | 185 | 51 | | IMovementRouteService movementRouteService, IAddressService addressService, ICategoryService catService, ICa |
| | 185 | 52 | | { |
| | 185 | 53 | | _depService = depService; |
| | 185 | 54 | | _addressService = addressService; |
| | 185 | 55 | | _notifyWorker = notifyWorker; |
| | 185 | 56 | | _userService = userService; |
| | 185 | 57 | | _scheduleService = scheduleService; |
| | 185 | 58 | | _contrService = contrService; |
| | 185 | 59 | | _emailService = emailService; |
| | 185 | 60 | | _dirService = dirService; |
| | 185 | 61 | | _notifyService = notifyService; |
| | 185 | 62 | | _clusterService = clusterService; |
| | 185 | 63 | | _contractService = contractService; |
| | 185 | 64 | | _authenticationService = authenticationService; |
| | 185 | 65 | | _telegramService = telegramService; |
| | 185 | 66 | | _logger = logger; |
| | 185 | 67 | | _catService = catService; |
| | 185 | 68 | | _catRatiosService = catRatiosService; |
| | 185 | 69 | | _movementRouteService = movementRouteService; |
| | 185 | 70 | | } |
| | | 71 | | |
| | | 72 | | /// <summary> |
| | | 73 | | /// Создает подразделение и выполняет первичное наполнение связанных данных (кластера, контракты, расписание, ре |
| | | 74 | | /// </summary> |
| | | 75 | | /// <param name="data">подразделение</param> |
| | | 76 | | /// <param name="warehouseId">id склада, с которым заключать контракт и к которому включать в кластер. Актуально |
| | | 77 | | /// <returns></returns> |
| | | 78 | | public async Task CreateDepartment(Department data, long warehouseId = 0) |
| | | 79 | | { |
| | 566 | 80 | | if ((await _depService.GetDeparments(data.Contragent.Id, 0, int.MaxValue, null, null)).Result.Any(x => x.Nam |
| | | 81 | | throw new SvetaException($"Подразделение с названием {data.Name} и контрагентом {data.Contragent.ShortNa |
| | | 82 | | await _depService.CreateDepartment(data); |
| | | 83 | | await CreateNotifications(data); |
| | | 84 | | await CreateDataForNewWarehouse(data); |
| | | 85 | | await CreateDataForNewShop(data, warehouseId); |
| | | 86 | | await CreateSchedule(data); |
| | | 87 | | await CreateMovementStatusRoutes(data); |
| | | 88 | | } |
| | | 89 | | |
| | | 90 | | /// <summary> |
| | | 91 | | /// Возвращает все подразделения партнеров-контрагентов |
| | | 92 | | /// </summary> |
| | | 93 | | /// <param name="filter">фильтр по названию и адресу</param> |
| | | 94 | | /// <param name="contragentId">по умолчанию 0. Если 0, то выводит все ТТ платформы (если админ). Если > 0, то вы |
| | | 95 | | /// <param name="warehouseId">по умолчанию 0. Если 0, то выводит все ТТ, иначе только те, которые не привязаны к |
| | | 96 | | /// <returns>список объектов DepartmentShortWithAddressDTO</returns> |
| | | 97 | | public async Task<List<DepartmentShortWithAddressDTO>> GetPartnersDepartments(string filter, long contragentId, |
| | | 98 | | { |
| | | 99 | | contragentId = _authenticationService.IsUserPlatform() ? contragentId : _authenticationService.ContragentId; |
| | | 100 | | var result = await Task.FromResult(_depService.GetDeparments(0, 0, int.MaxValue, filter, default).Result.Res |
| | | 101 | | if (contragentId == 0) |
| | | 102 | | {//если 0, выводим все ТТ платформы. Если warehouseId>0, то выводим ТТ, которые не привязаны к кластерам пер |
| | 0 | 103 | | result = result.Where(x => (warehouseId == 0 || x.Cluster?.WarehouseId != warehouseId) && x.Kind.Id == ( |
| | 0 | 104 | | return result.Select(x => new DepartmentShortWithAddressDTO(x)).ToList(); |
| | | 105 | | } |
| | | 106 | | var contracts = await _contractService.GetSupplyContractsByContragent(contragentId, true, null); //находим в |
| | | 107 | | List<long> contragents = new List<long>() { }; |
| | | 108 | | foreach (var item in contracts) //выбираем его партнеров |
| | | 109 | | { |
| | | 110 | | if (contragentId != item.Seller.Id) |
| | | 111 | | contragents.Add(item.Seller.Id); |
| | | 112 | | if (contragentId != item.Buyer.Id) |
| | | 113 | | contragents.Add(item.Buyer.Id); |
| | | 114 | | } |
| | | 115 | | contragents = contragents.Distinct().ToList(); // оставляем униклальные |
| | | 116 | | //выбираем ТТ, у которых КА из этого массива. Если warehouseId>0, то выводим ТТ, которые не привязаны к клас |
| | 0 | 117 | | result = result.Where(x => contragents.Any(p => p == x.Contragent.Id) && (warehouseId == 0 || x.Cluster?.War |
| | 0 | 118 | | return result.Select(x => new DepartmentShortWithAddressDTO(x)).ToList(); |
| | | 119 | | } |
| | | 120 | | |
| | | 121 | | /// <summary> |
| | | 122 | | /// привязывает пользователей к подразделению |
| | | 123 | | /// </summary> |
| | | 124 | | /// <param name="id">id подразделения</param> |
| | | 125 | | /// <param name="usersId">юзеры</param> |
| | | 126 | | /// <returns></returns> |
| | | 127 | | public async Task BindUserToDepartment(long id, List<long> usersId) |
| | | 128 | | { |
| | | 129 | | if (usersId.Count > 0) |
| | | 130 | | { |
| | | 131 | | var department = _authenticationService.IsUserPlatform() ? await _depService.GetDepartment(id) : await _ |
| | | 132 | | if (department == null) |
| | | 133 | | throw new KeyNotFoundException($"Подразделение с id={id} не найдено"); |
| | | 134 | | foreach (var listx in usersId) |
| | | 135 | | { |
| | | 136 | | var bindUser = await _userService.GetUser(listx); |
| | | 137 | | //привязывать можем только людей нашего КА или любых, но только если мы повелитель |
| | | 138 | | if (bindUser != null && (bindUser.Contragent.Id == _authenticationService.ContragentId || _authentic |
| | | 139 | | { |
| | 0 | 140 | | if (!department.UsersDepartments.Any(x => x.UserId == listx)) |
| | | 141 | | department.UsersDepartments.Add(new UserDepartment { UserId = listx }); |
| | | 142 | | } |
| | | 143 | | else throw new KeyNotFoundException($"Пользователь с id={listx} не найден"); |
| | | 144 | | } |
| | | 145 | | await _depService.UpdateDepartment(department); |
| | | 146 | | } |
| | | 147 | | else throw new KeyNotFoundException($"Не указаны пользователи"); |
| | | 148 | | } |
| | | 149 | | |
| | | 150 | | /// <summary> |
| | | 151 | | /// привязывает пользователей к подразделению |
| | | 152 | | /// </summary> |
| | | 153 | | /// <param name="id">id подразделения</param> |
| | | 154 | | /// <param name="usersId">юзеры</param> |
| | | 155 | | /// <returns></returns> |
| | | 156 | | public async Task UnbindUserFromDepartment(long id, List<long> usersId) |
| | | 157 | | { |
| | | 158 | | if (usersId.Count > 0) |
| | | 159 | | { |
| | | 160 | | var department = _authenticationService.IsUserPlatform() ? await _depService.GetDepartment(id) : await _ |
| | | 161 | | if (department == null) |
| | | 162 | | throw new KeyNotFoundException($"Подразделение с id={id} не найдено"); |
| | | 163 | | foreach (var listx in usersId) |
| | | 164 | | { |
| | | 165 | | var bindUser = await _userService.GetUser(listx); |
| | | 166 | | if (bindUser.Id == department.Contragent.Owner.Id) |
| | | 167 | | throw new ArgumentException("Нельзя отвязывать владельца подразделения"); |
| | | 168 | | //отвязывать можем только людей нашего КА или любых, но только если мы повелитель |
| | | 169 | | if (bindUser != null && (bindUser.Contragent.Id == _authenticationService.ContragentId || _authentic |
| | | 170 | | { |
| | 0 | 171 | | if (department.UsersDepartments.Any(x => x.UserId == listx)) |
| | 0 | 172 | | department.UsersDepartments.Remove(department.UsersDepartments.Where(x => x.UserId == listx) |
| | | 173 | | } |
| | | 174 | | else throw new KeyNotFoundException($"Пользователь с id={listx} не найден"); |
| | | 175 | | } |
| | | 176 | | await _depService.UpdateDepartment(department); |
| | | 177 | | } |
| | | 178 | | else throw new KeyNotFoundException($"Не указаны пользователи"); |
| | | 179 | | } |
| | | 180 | | |
| | | 181 | | /// <summary> |
| | | 182 | | /// Создает нотификации о созданном подразделении |
| | | 183 | | /// </summary> |
| | | 184 | | /// <param name="data">подразделение</param> |
| | | 185 | | /// <returns></returns> |
| | | 186 | | private async Task CreateNotifications(Department data) |
| | 560 | 187 | | { |
| | 560 | 188 | | var sb = new StringBuilder(); |
| | 560 | 189 | | sb.Append($"Создано подразделение {data.Name}.<br>"); |
| | 560 | 190 | | sb.Append($"Тип - {data.Kind.Name}.<br>"); |
| | 560 | 191 | | sb.Append($"Телефон - {data.PhoneNumber}.<br>"); |
| | 560 | 192 | | sb.Append($"Контрагент - {data.Contragent.ShortName}.<br>"); |
| | 560 | 193 | | sb.Append($"Площадь - {data.Area}.<br>"); |
| | 560 | 194 | | sb.Append($"КПП - {data.Kpp}.<br>"); |
| | 560 | 195 | | sb.Append($"Email - {data.Email}.<br>"); |
| | 560 | 196 | | sb.Append($"Адрес - {data.ActualAddress.FullAddress}.<br>"); |
| | 560 | 197 | | await _emailService.Create("Создано новое подразделение", sb.ToString(), new List<string>() { data.Email, _a |
| | | 198 | | |
| | 560 | 199 | | if ((await _telegramService.CanSendToTelegram("#department"))) |
| | 560 | 200 | | { |
| | 560 | 201 | | string textTelegram = |
| | 560 | 202 | | $"#department " + |
| | 560 | 203 | | $"\nСоздано подразделение {data.Name} у контрагента {data.Contragent.ShortName}. " + |
| | 560 | 204 | | $"\nФактический адрес: {data.ActualAddress.FullAddress} " + |
| | 560 | 205 | | $"\ne-mail: {data.Email} " + |
| | 560 | 206 | | $"\nНомер телефона: {data.PhoneNumber}"; |
| | 560 | 207 | | await Telegram.SendNotification(textTelegram); |
| | 560 | 208 | | } |
| | 560 | 209 | | } |
| | | 210 | | |
| | | 211 | | /// <summary> |
| | | 212 | | /// Создает/проверяет для нового магазин контракт и включает в кластер |
| | | 213 | | /// </summary> |
| | | 214 | | /// <param name="department">Магазин</param> |
| | | 215 | | /// <param name="warehouseId">id Склада поставщика</param> |
| | | 216 | | private async Task CreateDataForNewShop(Department department, long warehouseId) |
| | | 217 | | { |
| | | 218 | | if (department.Kind.Id != (long)DepartmentKind.Shop) |
| | | 219 | | return; |
| | | 220 | | var warehouse = await _depService.GetDepartment(warehouseId) ?? throw new KeyNotFoundException($"Не найден у |
| | | 221 | | var user = await _userService.GetUser(_authenticationService.UserId); |
| | | 222 | | //получаем свежий активный контракт между КА магазина и КА переданного склада |
| | 380 | 223 | | var contract = (await _contractService.GetSupplyContracts(department.Contragent.Id, true)).OrderBy(x => x.Id |
| | | 224 | | //если контракта нет, то создаем его |
| | | 225 | | if (contract == null) |
| | | 226 | | { |
| | | 227 | | contract = new SupplyContract() |
| | | 228 | | { |
| | | 229 | | Buyer = department.Contragent, |
| | | 230 | | Seller = warehouse.Contragent, |
| | | 231 | | BeginDate = DateTime.Now.Date, |
| | | 232 | | EndDate = new DateTime(DateTime.Now.Year, 12, 31, 20, 59, 59, 999), |
| | | 233 | | SignOffDate = DateTime.Now.Date, |
| | | 234 | | DocumentNumber = "0", |
| | | 235 | | PrepaimentPercent = 100, |
| | | 236 | | TradeRatio = 100, |
| | | 237 | | RecState = await _dirService.GetRecordState((long)RecordState.Active) |
| | | 238 | | }; |
| | | 239 | | await _contractService.Create(contract); |
| | | 240 | | await _notifyService.CreateNotificationForUser("Заключение контракта", $"Заключен контракт №{contract.Do |
| | | 241 | | } |
| | | 242 | | //ищем кластера склада |
| | 1870 | 243 | | var cluster = (await _clusterService.GetClustersByWarehouse(warehouse.Id)).OrderBy(e => e.Id).FirstOrDefault |
| | | 244 | | if (cluster == null) |
| | | 245 | | throw new KeyNotFoundException($"У склада {warehouse.Name} не найдено кластеров"); |
| | | 246 | | cluster.Departments.Add(department); |
| | | 247 | | await _notifyService.CreateNotificationForUser("Включение магазина в кластер", $"Магазин {department.Name} п |
| | | 248 | | await _clusterService.UpdateCluster(cluster); |
| | | 249 | | } |
| | | 250 | | |
| | | 251 | | /// <summary> |
| | | 252 | | /// Метод для создания контракта и кластера между новым складом в БД и анонимным КА. Также создает анонимный маг |
| | | 253 | | /// </summary> |
| | | 254 | | /// <param name="department">подразделение</param> |
| | | 255 | | private async Task CreateDataForNewWarehouse(Department department) |
| | | 256 | | { |
| | | 257 | | if (department.Kind.Id != (long)DepartmentKind.Warehouse) |
| | | 258 | | return; |
| | | 259 | | var activeRec = await _dirService.GetRecordState((int)RecordState.Active); |
| | | 260 | | var anonymContragent = await _contrService.GetContragent(-1); |
| | | 261 | | var existContract = await _contractService.GetSupplyContract(anonymContragent.Id, department.Contragent.Id, |
| | | 262 | | if (existContract == null) |
| | | 263 | | { |
| | | 264 | | var contract = new SupplyContract() |
| | | 265 | | { |
| | | 266 | | RecState = activeRec, |
| | | 267 | | Buyer = anonymContragent, //аноним |
| | | 268 | | Seller = department.Contragent, |
| | | 269 | | BeginDate = DateTime.UtcNow.Date, |
| | | 270 | | EndDate = new DateTime(2029, 12, 31, 20, 59, 59), |
| | | 271 | | SignOffDate = DateTime.Now.AddDays(-1), |
| | | 272 | | DocumentNumber = "0", |
| | | 273 | | PrepaimentPercent = 100, |
| | | 274 | | TradeRatio = 100 |
| | | 275 | | }; |
| | | 276 | | await _contractService.Create(contract); |
| | | 277 | | } |
| | | 278 | | anonymContragent.Departments ??= new List<Department>(); |
| | 372 | 279 | | var newShop = anonymContragent.Departments.FirstOrDefault(d => d.Cluster == null); |
| | | 280 | | if (newShop == null) |
| | | 281 | | { |
| | | 282 | | newShop = new Department |
| | | 283 | | { |
| | | 284 | | Name = $"Витрина \"{department.Name}\"", |
| | | 285 | | PhoneNumber = "8000000000", |
| | 3 | 286 | | Kind = (await _depService.GetKindType(0)).FirstOrDefault(d => d.Id == (long) DepartmentKind.Shop), |
| | 3 | 287 | | Status = (await _depService.GetStatusType()).FirstOrDefault(d => d.Code.ToUpper().Equals("ACTIVE")), |
| | | 288 | | Contragent = anonymContragent, |
| | | 289 | | RecState = activeRec, |
| | | 290 | | ActualAddress = anonymContragent.PhysicAddress, |
| | | 291 | | Kpp = anonymContragent.Kpp, |
| | | 292 | | UsersDepartments = new List<UserDepartment>{new UserDepartment{UserId = anonymContragent.Owner.Id}} |
| | | 293 | | }; |
| | | 294 | | await _depService.CreateDepartment(newShop); |
| | | 295 | | anonymContragent.Departments.Add(newShop); |
| | | 296 | | await _contrService.UpdateContragent(anonymContragent); |
| | | 297 | | } |
| | | 298 | | |
| | | 299 | | var cluster = new Cluster() |
| | | 300 | | { |
| | | 301 | | RecState = activeRec, |
| | | 302 | | Departments = new List<Department>() { newShop }, //аноним |
| | | 303 | | Name = $"Демонстрационный кластер для склада {department.Name}", |
| | | 304 | | TradeRatio = 100, |
| | | 305 | | MinOrderSum = 100, |
| | | 306 | | Warehouse = department, |
| | | 307 | | ClusterDeliveryTypes = new List<ClusterDeliveryType> { new ClusterDeliveryType { DeliveryTypeId = (await |
| | | 308 | | }; |
| | | 309 | | await _clusterService.CreateCluster(cluster); |
| | | 310 | | } |
| | | 311 | | |
| | | 312 | | /// <summary> |
| | | 313 | | /// Создает регламент по заявкам для нового склада |
| | | 314 | | /// </summary> |
| | | 315 | | /// <param name="department">подразделение</param> |
| | | 316 | | /// <returns></returns> |
| | | 317 | | private async Task CreateMovementStatusRoutes(Department department) |
| | | 318 | | { |
| | | 319 | | if (department.Kind.Id != (long)DepartmentKind.Warehouse) |
| | | 320 | | { |
| | | 321 | | return; |
| | | 322 | | } |
| | 8227 | 323 | | var modelRoutes = (await _movementRouteService.GetRoutes()).Where(x => x.WarehouseId == -2); //эталонное рас |
| | | 324 | | var newRoutes = new List<MovementStatusRoute>(); |
| | 8184 | 325 | | newRoutes.AddRange(modelRoutes.Select(p => new MovementStatusRoute |
| | 8184 | 326 | | { |
| | 8184 | 327 | | StatusCurrentId = p.StatusCurrentId, |
| | 8184 | 328 | | StatusNextId = p.StatusNextId, |
| | 8184 | 329 | | RouteKey = p.RouteKey, |
| | 8184 | 330 | | Hour = p.Hour, |
| | 8184 | 331 | | Warehouse = department |
| | 8184 | 332 | | })); |
| | | 333 | | await _movementRouteService.CreateRoutes(newRoutes); |
| | | 334 | | } |
| | | 335 | | |
| | | 336 | | /// <summary> |
| | | 337 | | /// Создает расписание работы для нового склада |
| | | 338 | | /// </summary> |
| | | 339 | | /// <param name="department">подразделение</param> |
| | | 340 | | /// <returns></returns> |
| | | 341 | | private async Task CreateSchedule(Department department) |
| | | 342 | | { |
| | | 343 | | if (department.Kind.Id != (long)DepartmentKind.Warehouse) |
| | | 344 | | return; |
| | 42721 | 345 | | var modelSchedules = (await _scheduleService.GetSchedules()).Where(x=>x.WarehouseId == -2 && x.BeginTime.Dat |
| | | 346 | | var newSchedules = new List<WorkSchedule>(); |
| | 23808 | 347 | | newSchedules.AddRange(modelSchedules.Select(p => new WorkSchedule() { Warehouse = department, BeginTime = p. |
| | | 348 | | await _scheduleService.Create(newSchedules); |
| | | 349 | | } |
| | | 350 | | |
| | | 351 | | /// <summary> |
| | | 352 | | /// Получает типы доставки для подразделения |
| | | 353 | | /// </summary> |
| | | 354 | | /// <param name="departmentId">id подразделения</param> |
| | | 355 | | /// <param name="clusterId">id кластера. Если в departmentId передан склад, то в этом параметре можно указать, и |
| | | 356 | | /// <returns>список объектов для ClusterDeliveryTypesResponseDTO</returns> |
| | | 357 | | public async Task<List<ClusterDeliveryTypesResponseDTO>> GetDepartmentDeliveryTypes(long departmentId, long clus |
| | | 358 | | { |
| | | 359 | | var result = new List<ClusterDeliveryTypesResponseDTO>(); |
| | | 360 | | var department = _authenticationService.IsUserPlatform() ? await _depService.GetDepartment(departmentId) : a |
| | | 361 | | if (department == null) |
| | | 362 | | throw new KeyNotFoundException($"Подразделение с id={departmentId} не найдено"); |
| | | 363 | | if (department.Kind.Id == (long)DepartmentKind.Shop) |
| | | 364 | | result.Add(new ClusterDeliveryTypesResponseDTO() |
| | | 365 | | { |
| | | 366 | | Cluster = new IdNameDTO(department.Cluster.Id, department.Cluster.Name), |
| | 0 | 367 | | DeliveryTypes = new List<DeliveryTypeResponseDto>(department.Cluster.ClusterDeliveryTypes.Select(x = |
| | | 368 | | }); |
| | | 369 | | if (department.Kind.Id == (long)DepartmentKind.Warehouse) |
| | | 370 | | { |
| | 0 | 371 | | var clusters = (await _clusterService.GetClustersByWarehouse(departmentId)).Where(x => clusterId == 0 || |
| | 0 | 372 | | result.AddRange(clusters.Select(x => new ClusterDeliveryTypesResponseDTO() |
| | 0 | 373 | | { |
| | 0 | 374 | | Cluster = new IdNameDTO(x.Id, x.Name), |
| | 0 | 375 | | DeliveryTypes = new List<DeliveryTypeResponseDto>(x.ClusterDeliveryTypes.Select(z => new DeliveryTyp |
| | 0 | 376 | | })); |
| | | 377 | | } |
| | | 378 | | return result; |
| | | 379 | | } |
| | | 380 | | |
| | | 381 | | /// <summary> |
| | | 382 | | /// Получить торговые коэффициенты для одного подразделения по всем категориям товаров. Для тех категорий, у кот |
| | | 383 | | /// </summary> |
| | | 384 | | /// <remarks>author IPod</remarks> |
| | | 385 | | /// <param name="id">Id подразделения</param> |
| | | 386 | | /// <param name="parentId">Идентифиатор родительской категории: null - все категории, 0 - корневые категории, >1 |
| | | 387 | | /// <param name="filter">Фильтр для поиска по названию категории</param> |
| | | 388 | | /// <param name="page">Любое значение ниже нуля изменится на 1, номер страницы</param> |
| | | 389 | | /// <param name="limit">Любое значение ниже нуля изменится на 10, лимит выдачи</param> |
| | | 390 | | /// <returns>список объектов DepartmentCategoryRatioResponseDTO</returns> |
| | | 391 | | public async Task<List<DepartmentCategoryRatioResponseDTO>> GetCategoryRatios(long id, long? parentId, string fi |
| | 0 | 392 | | { |
| | 0 | 393 | | page = page < 1 ? 1 : page; |
| | 0 | 394 | | limit = limit < 1 ? 10 : limit; |
| | | 395 | | |
| | 0 | 396 | | var categoryList = await _catService.GetCategories(page, limit, filter, parentId); |
| | | 397 | | |
| | 0 | 398 | | var result = new List<DepartmentCategoryRatioResponseDTO>(); |
| | | 399 | | |
| | 0 | 400 | | foreach (var category in categoryList) |
| | 0 | 401 | | { |
| | 0 | 402 | | var existingDCR = await _catRatiosService.GetDepartmentCategoryRatio(id, category.Id); |
| | | 403 | | |
| | 0 | 404 | | var newDCR = new DepartmentCategoryRatioResponseDTO |
| | 0 | 405 | | { |
| | 0 | 406 | | Id = existingDCR == null ? 0 : existingDCR.Id, |
| | 0 | 407 | | CategoryId = category.Id, |
| | 0 | 408 | | ParentId = category.Parent?.Id, |
| | 0 | 409 | | Name = category.Name, |
| | 0 | 410 | | Code = category.Code, |
| | 0 | 411 | | DepartmentId = id, |
| | 0 | 412 | | TradeRatio = existingDCR == null ? 0 : existingDCR.TradeRatio, |
| | 0 | 413 | | Expandable = (await _catService.GetCategoriesCount(null, category.Id)) > 0 |
| | 0 | 414 | | }; |
| | | 415 | | |
| | 0 | 416 | | result.Add(newDCR); |
| | 0 | 417 | | } |
| | 0 | 418 | | return result; |
| | 0 | 419 | | } |
| | | 420 | | |
| | | 421 | | /// <summary> |
| | | 422 | | /// Создать торговый коэффициент для одного подразделения по одной категории товара. |
| | | 423 | | /// </summary> |
| | | 424 | | /// <param name="id">id подразделения</param> |
| | | 425 | | /// <param name="categoryId">id категории</param> |
| | | 426 | | /// <param name="tradeRatio">коэффициент категории</param> |
| | | 427 | | /// <returns>объект DepartmentCategoryRatioResponseDTO</returns> |
| | | 428 | | public async Task<DepartmentCategoryRatioResponseDTO> CreateCategoryRatio(long id, long categoryId, decimal trad |
| | 0 | 429 | | { |
| | 0 | 430 | | var department = await _depService.GetDepartment(id) ?? throw new KeyNotFoundException($"Подразделение с id= |
| | 0 | 431 | | if (department.Contragent.Id != _authenticationService.ContragentId && !_authenticationService.IsUserPlatfor |
| | 0 | 432 | | throw new ForbidException(); |
| | | 433 | | |
| | 0 | 434 | | var category = await _catService.GetCategory(categoryId) ?? throw new KeyNotFoundException($"Категория с id= |
| | 0 | 435 | | var dсr = await _catRatiosService.GetDepartmentCategoryRatio(department.Id, category.Id); |
| | 0 | 436 | | if (dсr.Id != 0) |
| | 0 | 437 | | throw new ArgumentException($"Запись с категорией {category.Name} (id={category.Id}) и подразделением {d |
| | 0 | 438 | | var newSetting = new DepartmentCategoryRatio |
| | 0 | 439 | | { |
| | 0 | 440 | | Department = department, |
| | 0 | 441 | | Category = category, |
| | 0 | 442 | | TradeRatio = tradeRatio |
| | 0 | 443 | | }; |
| | 0 | 444 | | newSetting = await _catRatiosService.Create(newSetting); |
| | 0 | 445 | | var result = new DepartmentCategoryRatioResponseDTO |
| | 0 | 446 | | { |
| | 0 | 447 | | Id = newSetting.Id, |
| | 0 | 448 | | CategoryId = newSetting.Category.Id, |
| | 0 | 449 | | ParentId = newSetting.Category.Parent?.Id, |
| | 0 | 450 | | Name = category.Name, |
| | 0 | 451 | | Code = category.Code, |
| | 0 | 452 | | DepartmentId = newSetting.Department.Id, |
| | 0 | 453 | | TradeRatio = newSetting.TradeRatio, |
| | 0 | 454 | | Expandable = (await _catService.GetCategories(1, 10, null, newSetting.Id)).Count() > 0 |
| | 0 | 455 | | }; |
| | 0 | 456 | | return result; |
| | 0 | 457 | | } |
| | | 458 | | |
| | | 459 | | /// <summary> |
| | | 460 | | /// Получает список складов, которые доступны для текущего КА покупателя. Ключ сравнения: первые 2 цифры ИНН пок |
| | | 461 | | /// </summary> |
| | | 462 | | /// <returns>список складов</returns> |
| | | 463 | | public async Task<List<Department>> GetAvailableWarehouse() |
| | | 464 | | { |
| | | 465 | | //Если поставщик то возвращает пустоту |
| | | 466 | | if (_authenticationService.IsUserWholesaler()) |
| | | 467 | | return new List<Department>(); |
| | | 468 | | var allWarehouses = await _depService.GetDepartmentsByKind(DepartmentKind.Warehouse, null, null, true); |
| | | 469 | | //если мы админ, то возвращаем весь список складов. Пусть юзер сам определяет |
| | | 470 | | if (_authenticationService.IsUserPlatform()) |
| | | 471 | | return allWarehouses; |
| | | 472 | | //получаем контракты с КА текущего пользователя |
| | 0 | 473 | | var contract = (await _contractService.GetSupplyContracts(_authenticationService.ContragentId, true)).OrderB |
| | | 474 | | //если контракт есть, то возвращаем склады продавца из контракта |
| | | 475 | | if (contract != null) |
| | 0 | 476 | | return allWarehouses.Where(x => x.Contragent.Id == contract.Seller.Id).ToList(); |
| | | 477 | | //находим склады, у КА которых инн начинается с таких же 2 цифр, что и у КА текущего юзера магазина |
| | | 478 | | var currentContragent = await _contrService.GetContragent(_authenticationService.ContragentId); |
| | 0 | 479 | | var departments = allWarehouses.Where(x=>x.Contragent.Inn.StartsWith(currentContragent.Inn.Substring(0,2))). |
| | | 480 | | //если нашли, возвращаем их, иначе все склады |
| | | 481 | | return departments.Count > 0 ? departments : allWarehouses; |
| | | 482 | | } |
| | | 483 | | |
| | | 484 | | /// <summary> |
| | | 485 | | /// Выводит список уникальных складов-отправителей или магазинов-получателей, которые встречаются в заявках/отгр |
| | | 486 | | /// </summary> |
| | | 487 | | /// <param name="kind">тип департамента, по которому надо найти уникальные подразделения</param> |
| | | 488 | | /// <param name="movementKind">тип документов, в которых искать</param> |
| | | 489 | | /// <returns></returns> |
| | | 490 | | public async Task<List<Department>> GetFilterListByMovementDepartment(DepartmentKind kind, MovementKind movement |
| | 0 | 491 | | { |
| | 0 | 492 | | var contragentId = _authenticationService.IsUserPlatform() ? 0 : _authenticationService.ContragentId; |
| | 0 | 493 | | var result = kind == DepartmentKind.Warehouse ? await _depService.GetFilteredListByMovementSender(contragent |
| | 0 | 494 | | return result; |
| | 0 | 495 | | } |
| | | 496 | | } |
| | | 497 | | } |