public ActionResult ChangePrice(long id, long pid, decimal newVal)
        {
            // Доступные склады
            var warehouses = CurrentUser.IsAdmin()
                ? DataContext.Warehouses.ToList()
                : CurrentUser.WarehouseKeepers.Select(wk => wk.Warehouse).ToList();

            // Ищем склад и тип продукта
            var warehouse = warehouses.FirstOrDefault(w => w.Id == id);
            if (warehouse == null)
            {
                return Json(new { success = false, msg = "Такой склад не найден" });
            }
            if (warehouse.Project.ProductTypes.All(p => p.Id != pid))
            {
                return Json(new { success = false, msg = "Такой тип продукта не найден" });
            }

            if (newVal < 0)
            {
                newVal = 0;
            }

            // Ищем или создаем
            var warehouseProduct = warehouse.WarehouseProducts.FirstOrDefault(wp => wp.ProductId == pid);
            if (warehouseProduct == null)
            {
                warehouseProduct = new WarehouseProduct()
                {
                    DateCreated = DateTime.Now,
                    Price = 0,
                    Quantity = 0,
                    ProductId = pid,
                    Warehouse = warehouse
                };
                warehouse.WarehouseProducts.Add(warehouseProduct);
            }
            warehouseProduct.Price = newVal;
            warehouseProduct.DateModified = DateTime.Now;

            // Сохраняем
            try
            {
                DataContext.SubmitChanges();
            }
            catch (Exception e)
            {
                return Json(new { success = false, msg = "Ошибка сохранения в базу: " + e.Message });
            }

            return Json(new { success = true });
        }
        public ActionResult UpdateOrderStatus(long id, short newStatus, string comments, bool updateWarehouse)
        {
            // Ищем заявку
            var availableProjects = CurrentUser.IsAdmin() ? DataContext.Projects.Select(p => p.Id) : CurrentUser.ProjectUsers.Select(pu => pu.ProjectId);
            var order = DataContext.FEAOrders.FirstOrDefault(o => o.Id == id && availableProjects.Contains(o.ProjectId));
            if (order == null)
            {
                ShowError("Такая заявка не найдена");
                return RedirectToAction("Index");
            }

            // Проверяем можем ли мы изменить статус
            if (!order.CanChangeStatus(CurrentUser))
            {
                ShowError("Нельзя изменить статус у этой заявки");
                return RedirectToAction("Index");
            }

            // Изменяем статус
            if (newStatus != order.Status)
            {
                order.Status = newStatus;
                order.FEAOrdersStatusChangements.Add(new FEAOrdersStatusChangement()
                {
                    Status = newStatus,
                    FEAOrder = order,
                    Comments = comments,
                    User = CurrentUser,
                    DateCreated = DateTime.Now
                });

                ShowSuccess("Статус ВЭД заявки №{0} успешно изменен");

                // Провряем, требуется ли обновить остатки на указанному складе
                if (newStatus == (short) FEAOrderStatus.Completed && updateWarehouse && order.TargetWarehouse != null)
                {
                    // Обновляем остатки на складе
                    foreach (var orderItem in order.FEAOrderItems)
                    {
                        // Ищем позицию на складе
                        var warehouseItem =
                            order.TargetWarehouse.WarehouseProducts.FirstOrDefault(
                                wp => wp.ProductId == orderItem.ProductId);

                        // Создаем если ее нет
                        if (warehouseItem == null)
                        {
                            warehouseItem = new WarehouseProduct()
                            {
                                ProductId = orderItem.ProductId,
                                DateCreated = DateTime.Now,
                                WarehouseId = order.TargetWarehouse.Id,
                                Price = orderItem.Price.HasValue ? orderItem.Price.Value : 0,
                            };
                            order.TargetWarehouse.WarehouseProducts.Add(warehouseItem);
                        }

                        // Добавляем начисление
                        warehouseItem.Quantity = warehouseItem.Quantity + orderItem.Quantity;
                        warehouseItem.WarehouseProductChangements.Add(new WarehouseProductChangement()
                        {
                            Amount = orderItem.Quantity,
                            Direction = (short)WarehouseProductChangementDirection.Income,
                            DateCreated = DateTime.Now,
                            WarehouseProduct = warehouseItem,
                            Description = String.Format("Автоматическое начисление остатков по выполнению ВЭД заявки №{0}",order.Id)
                        });
                    }

                    ShowSuccess(string.Format("На склад {0} ({1}) успешно зачислены товары из ВЭД заявки №{2}", order.TargetWarehouse.Title, order.TargetWarehouse.City, order.Id));
                }

                DataContext.SubmitChanges();
            }

            return Redirect(string.Format("/fea/{0}/edit#history", order.Id));
        }
        public ActionResult ChangeQuantity(long id, long pid, int newVal)
        {
            // Доступные склады
            var warehouses = CurrentUser.IsAdmin()
                ? DataContext.Warehouses.ToList()
                : CurrentUser.WarehouseKeepers.Select(wk => wk.Warehouse).ToList();

            // Ищем склад и тип продукта
            var warehouse = warehouses.FirstOrDefault(w => w.Id == id);
            if (warehouse == null)
            {
                return Json(new {success = false, msg = "Такой склад не найден"});
            }
            if (warehouse.Project.ProductTypes.All(p => p.Id != pid))
            {
                return Json(new { success = false, msg = "Такой тип продукта не найден" });
            }

            if (newVal < 0)
            {
                newVal = 0;
            }

            var warehouseProduct = warehouse.WarehouseProducts.FirstOrDefault(wp => wp.ProductId == pid);
            if (warehouseProduct == null)
            {
                // Создаем информацию об остатках товара на складе
                warehouseProduct = new WarehouseProduct()
                {
                    DateCreated = DateTime.Now,
                    Price = 0,
                    ProductId = pid,
                    Warehouse = warehouse,
                    Quantity = newVal
                };
                warehouse.WarehouseProducts.Add(warehouseProduct);
                if (newVal > 0)
                {
                    warehouseProduct.WarehouseProductChangements.Add(new WarehouseProductChangement()
                    {
                        Amount = newVal,
                        DateCreated = DateTime.Now,
                        Direction = (short)WarehouseProductChangementDirection.Income,
                        WarehouseProduct = warehouseProduct,
                        Description = String.Format("Ручное изменение: добавление {0} шт. пользователем {1}",newVal,CurrentUser.GetFio())
                    });
                }
            }
            else
            {
                // Изменяем
                var diff = newVal - warehouseProduct.Quantity;
                if (diff != 0)
                {
                    warehouseProduct.Quantity = newVal;
                    warehouseProduct.DateModified = DateTime.Now;
                    warehouseProduct.WarehouseProductChangements.Add(new WarehouseProductChangement()
                    {
                        Amount = diff,
                        DateCreated = DateTime.Now,
                        WarehouseProduct = warehouseProduct,
                        Direction = diff > 0 ? (short)WarehouseProductChangementDirection.Income : (short)WarehouseProductChangementDirection.Outcome,
                        Description = diff > 0 ? String.Format("Ручное изменение: добавление {0} шт. пользователем {1}",diff,CurrentUser.GetFio()) : String.Format("Ручное изменение: изъятие {0} шт. пользователем {1}",Math.Abs(diff),CurrentUser.GetFio())
                    });
                }
            }

            // Сохраняем
            try
            {
                DataContext.SubmitChanges();
            }
            catch (Exception e)
            {
                return Json(new { success = false, msg = "Ошибка сохранения в базу: "+e.Message });
            }

            return Json(new { success = true });
        }
        public ActionResult ChangeOrderStatus(long id, short newStatus, long newUser, long newWarehouse, string comments,
            bool createFeaOrder, string redirectUrl, bool extractFromWarehouse = false)
        {
            var order = DataContext.LeadOrders.FirstOrDefault(lo => lo.Id == id);
            if (order == null)
            {
                ShowError("Такой заказ не найден");
                return RedirectToAction("Index");
            }

            if (!order.CanChangeStatus(CurrentUser))
            {
                ShowError("Такой заказ не найден");
                return RedirectToAction("Index");
            }

            // Изменяем статус
            var oldStatus = order.Status;
            var oldAssignedUserId = order.AssignedUserId;
            var oldWarehouse = order.AssignedWarehouseId;
            order.Status = newStatus;
            order.DateModified = DateTime.Now;
            if (newUser != oldAssignedUserId)
            {
                order.User.LeadOrders.Remove(order);
                DataContext.Users.First(u => u.Id == newUser).LeadOrders.Add(order);
            }
            if (newWarehouse != oldWarehouse)
            {
                if (order.Warehouse != null)
                {
                    order.Warehouse.LeadOrders.Remove(order);
                }
                DataContext.Warehouses.First(w => w.Id == newWarehouse).LeadOrders.Add(order);
            }
            order.LeadOrderChangements.Add(new LeadOrderChangement()
            {
                Author = CurrentUser,
                Comments = comments,
                OldStatus = oldStatus,
                OldAssignedUserId = oldAssignedUserId,
                OldWarehouseId = oldWarehouse,
                NewStatus = newStatus,
                NewAssignedUserId = newUser,
                NewWarehouseId = newWarehouse,
                LeadOrder = order,
                DateCreated = DateTime.Now
            });

            // Сохраняем
            DataContext.SubmitChanges();

            ShowSuccess(string.Format("Статус заказа №{0} для {1} был успешно изменен", order.Id, order.Lead.ToString()));

            if (extractFromWarehouse && order.Warehouse != null)
            {
                // Извлекаем остатки со склада
                foreach (var orderItem in order.LeadOrderItems)
                {
                    var warehouseProduct =
                        order.Warehouse.WarehouseProducts.FirstOrDefault(wp => wp.ProductId == orderItem.ProductId);
                    if (warehouseProduct == null)
                    {
                        warehouseProduct = new WarehouseProduct()
                        {
                            DateCreated = DateTime.Now,
                            ProductId = orderItem.ProductId,
                            Quantity = 0,
                            Warehouse = order.Warehouse,
                            Price = orderItem.Price
                        };
                        order.Warehouse.WarehouseProducts.Add(warehouseProduct);
                    }
                    warehouseProduct.Quantity = warehouseProduct.Quantity - orderItem.Quantity;
                    warehouseProduct.DateModified = DateTime.Now;
                    warehouseProduct.WarehouseProductChangements.Add(new WarehouseProductChangement()
                    {
                        DateCreated = DateTime.Now,
                        Amount = orderItem.Quantity,
                        Direction = (short)WarehouseProductChangementDirection.Outcome,
                        WarehouseProduct = warehouseProduct,
                        Description = String.Format("Изъятие остатков в количестве {0} для выполнения заказа №{1} пользователем {2}", orderItem.Quantity, order.Id, CurrentUser.GetFio())
                    });
                }
                order.LeadOrderChangements.Add(new LeadOrderChangement()
                {
                    Author = CurrentUser,
                    NewAssignedUserId = order.AssignedUserId,
                    OldAssignedUserId = order.AssignedUserId,
                    OldStatus = order.Status,
                    NewStatus = order.Status,
                    OldWarehouseId = order.AssignedWarehouseId,
                    NewWarehouseId = order.AssignedWarehouseId,
                    DateCreated = DateTime.Now,
                    Comments = String.Format("Извлечение остатков со склада {0} ({1}) в общем количестве {2}", order.Warehouse.Title, order.Warehouse.City, order.LeadOrderItems.Sum(oi => oi.Quantity))
                });
                DataContext.SubmitChanges();
                ShowSuccess(string.Format("Остатки со склада {0} ({1}) были успешно извлечены", order.Warehouse.Title, order.Warehouse.City));
            }

            // Создаем заявку на дозакуп
            if (createFeaOrder)
            {
                // Ищем менеджера
                var targetManagers =
                    order.Project.ProjectUsers.Where(u => u.User.HasPermission(Permission.FEA))
                        .Select(u => u.User)
                        .ToList();
                if (targetManagers.Count > 0)
                {
                    User targetManager = null;
                    targetManager = targetManagers.FirstOrDefault(u => u.RoleId != 1) ?? targetManagers.FirstOrDefault();
                    if (targetManager != null)
                    {
                        var newFeaOrder = new FEAOrder()
                        {
                            Description =
                                string.Format("Заявка на дозакуп, сформированная автоматически из заказа №{0}", order.Id),
                            DateCreated = DateTime.Now,
                            Status = (short)FEAOrderStatus.Gathering,
                            Manager = targetManager,
                            Project = order.Project,
                            TargetWarehouse = order.Warehouse
                        };
                        newFeaOrder.FEAOrderItems.AddRange(order.LeadOrderItems.Select(oi => new FEAOrderItem()
                        {
                            DateCreated = DateTime.Now,
                            FEAOrder = newFeaOrder,
                            Price = oi.Price,
                            ProductId = oi.ProductId,
                            Quantity = oi.Quantity*2
                        }));
                        newFeaOrder.FEAOrdersStatusChangements.Add(new FEAOrdersStatusChangement()
                        {
                            User = CurrentUser,
                            FEAOrder = newFeaOrder,
                            DateCreated = DateTime.Now,
                            Status = (short)FEAOrderStatus.Gathering,
                            Comments = string.Format("Автоматическое создание заявку на дозакуп из заказа №{0}", order.Id)
                        });
                        order.LeadOrderChangements.Add(new LeadOrderChangement()
                        {
                            Author = CurrentUser,
                            NewAssignedUserId = order.AssignedUserId,
                            OldAssignedUserId = order.AssignedUserId,
                            OldStatus = order.Status,
                            NewStatus = order.Status,
                            OldWarehouseId = order.AssignedWarehouseId,
                            NewWarehouseId = order.AssignedWarehouseId,
                            DateCreated = DateTime.Now,
                            Comments = String.Format("Автоматическое создание заявки на дозакуп №{0} на пользователя {1}",newFeaOrder.Id,targetManager.GetFio())
                        });
                        DataContext.SubmitChanges();
                        ShowSuccess(string.Format("Заявка на дозакуп №{0} успешно сформирована", newFeaOrder.Id));
                    }
                }
            }

            return Redirect(redirectUrl + "#history");
        }
		private void detach_WarehouseProducts(WarehouseProduct entity)
		{
			this.SendPropertyChanging();
			entity.Warehouse = null;
		}
		private void attach_WarehouseProducts(WarehouseProduct entity)
		{
			this.SendPropertyChanging();
			entity.ProductType = this;
		}