Example #1
0
        public static DataTable Price(ActivePrice activePrice, IEnumerable <NamedOffer> offers)
        {
            var table = new DbfTable();

            table.Columns(
                Column.Char("CODEPST", 12),
                Column.Char("NAME", 80),
                Column.Char("CNTR", 15),
                Column.Char("FIRM", 40),
                Column.Numeric("QNTPACK", 8),
                Column.Char("EAN13", 13),
                Column.Numeric("NDS", 9, 2),
                Column.Date("GDATE"),
                Column.Numeric("QNT", 9, 2),
                Column.Numeric("NSP", 9, 2),
                Column.Numeric("GNVLS", 1),
                Column.Numeric("PRICE1", 9, 2),
                Column.Numeric("NEWFLG", 1),
                Column.Numeric("PROTECID", 8),
                Column.Numeric("QNTPST", 8),
                Column.Numeric("XCODE", 20));

            foreach (var offer in offers)
            {
                table.Row(
                    Value.For("CODEPST", offer.Code),
                    Value.For("NAME", offer.ProductSynonym),
                    //Value.For("CNTR", offer.),
                    Value.For("FIRM", offer.ProducerSynonym),
                    Value.For("QNTPACK", offer.RequestRatio),
                    Value.For("EAN13", offer.EAN13.Slice(12)),
                    //Value.For("NDS", offer.),
                    Value.For("GDATE", offer.NormalizedPeriod),                     // !
                    Value.For("QNT", offer.Quantity),
                    //Value.For("NSP", offer.),
                    Value.For("GNVLS", offer.VitallyImportant),
                    Value.For("PRICE1", offer.Cost),
                    //Value.For("NEWFLG", offer.)
                    //Value.For("PROTECID", offer.)
                    //Value.For("QNTPST", offer.)
                    Value.For("XCODE", offer.CoreId)
                    );
            }
            return(table.ToDataTable());
        }
Example #2
0
        public static void Price(XmlWriter writer, ActivePrice activePrice,
                                 IEnumerable <NamedOffer> offers)
        {
            var supplier = activePrice.Id.Price.Supplier;

            writer.WriteStartElement("PACKET");
            writer.WriteAttributeString("NAME", "Прайс-лист");
            writer.WriteAttributeString("FROM", supplier.Name);
            writer.WriteAttributeString("TYPE", "10");

            writer.WriteStartElement("PRICELIST");
            writer.WriteAttributeString("DATE", activePrice.PriceDate.ToString("dd.MM.yyyy HH:mm"));
            writer.WriteAttributeString("NAME", $"{supplier.Name} {activePrice.Id.Price.PriceName}");

            foreach (var offer in offers)
            {
                ExportOffer(writer, offer);
            }

            writer.WriteEndElement();
            writer.WriteEndElement();
        }
        private static List <OrderResult> SaveOrders(ISession session, RequestLog log, ClientOrder[] clientOrders, bool force)
        {
            var user   = log.User;
            var rules  = session.Load <OrderRules>(user.Client.Id);
            var errors = new List <OrderResult>();

            if (clientOrders == null)
            {
                return(errors);
            }

            using (StorageProcedures.GetActivePrices((MySqlConnection)session.Connection, user.Id)) {
                var orderitemMap = new Dictionary <OrderItem, uint>();
                var orders       = new List <Order>();
                foreach (var clientOrder in clientOrders)
                {
                    var address = session.Load <Address>(clientOrder.AddressId);
                    var price   = session.Load <PriceList>(clientOrder.PriceId);

                    var activePrice = session.Get <ActivePrice>(new PriceKey(price, clientOrder.RegionId));
                    //мы должны принимать заказы даже если прайс-лист больше не активен, например устарел
                    //как мне кажется смысла в этом не но так было всегда
                    if (activePrice == null)
                    {
                        activePrice = new ActivePrice {
                            Id        = new PriceKey(price, clientOrder.RegionId),
                            PriceDate = clientOrder.PriceDate
                        };
                    }

                    try {
                        var order = new Order(activePrice, user, address, rules)
                        {
                            ClientOrderId   = clientOrder.ClientOrderId,
                            PriceDate       = clientOrder.PriceDate,
                            ClientAddition  = clientOrder.Comment,
                            CalculateLeader = false,
                            PriceName       = clientOrder.PriceName,
                            CostId          = clientOrder.CostId,
                            CostName        = clientOrder.CostName,
                        };
                        foreach (var sourceItem in clientOrder.Items)
                        {
                            var offer = new Offer {
                                Id         = new OfferKey(sourceItem.OfferId.OfferId, sourceItem.OfferId.RegionId),
                                Cost       = (float)sourceItem.Cost,
                                PriceList  = activePrice,
                                PriceCode  = price.PriceCode,
                                CodeFirmCr = sourceItem.ProducerId,
                            };

                            var properties = typeof(BaseOffer).GetProperties().Where(p => p.CanRead && p.CanWrite);
                            foreach (var property in properties)
                            {
                                var value = property.GetValue(sourceItem, null);
                                property.SetValue(offer, value, null);
                            }
                            //клиент в поле уценка передает уценку с учетом клиентских настроек
                            //оригинальная уценка хранится в поле OriginalJunk
                            offer.Junk = sourceItem.OriginalJunk;

                            try {
                                var item = order.AddOrderItem(offer, sourceItem.Count);
                                item.CostWithDelayOfPayment = ((float?)sourceItem.ResultCost).GetValueOrDefault(item.CostWithDelayOfPayment);
                                if (rules.SendRetailMarkup)
                                {
                                    item.RetailCost   = sourceItem.RetailCost;
                                    item.RetailMarkup = sourceItem.RetailMarkup;
                                }
                                if (sourceItem.MinCost != null)
                                {
                                    item.LeaderInfo = new OrderItemLeadersInfo {
                                        OrderItem       = item,
                                        MinCost         = (float?)sourceItem.MinCost,
                                        PriceCode       = sourceItem.MinPrice?.PriceId,
                                        LeaderMinCost   = (float?)sourceItem.LeaderCost,
                                        LeaderPriceCode = sourceItem.LeaderPrice?.PriceId,
                                    };
                                }
                                orderitemMap.Add(item, sourceItem.Id);
                            }
                            catch (OrderException e) {
                                //если здесь произошла ошибка значит есть проблема в клиентском приложении и нужно узнать об этом
                                Log.Error($"Не удалось сформировать заявку по позиции {offer.Id}", e);
                                throw new OrderException($"Не удалось сформировать заявку по позиции {offer.Id}", e);
                            }
                        }
                        if (order.OrderItems.Count > 0)
                        {
                            orders.Add(order);
                        }
                    }
                    catch (OrderException e) {
                        Log.Warn($"Не удалось принять заказ {clientOrder.ClientOrderId}", e);
                        errors.Add(new OrderResult(clientOrder.ClientOrderId, "Отправка заказов запрещена"));
                    }
                }

                errors.AddEach(Validate(session, user, orders, force, orderitemMap));
                //удаление дублей должно производиться после всех проверок тк заказ будет отброшен полностью
                //и проверки для него не важны или пройдет часть позиций которые пользователь "донабил"
                //в этом случае проверки для них не должны применяться тк они идут в "догонку"
                errors.AddEach(RemoveDuplicate(session, orders, orderitemMap));

                //мы не должны сохранять валидные заказы если корректировка заказов
                //включена
                if (!user.UseAdjustmentOrders || errors.Count == 0)
                {
                    var addressIds = orders.Select(o => o.AddressId).Distinct().ToArray();
                    if (addressIds.Length > 0)
                    {
                        var addresses = session.Query <Address>()
                                        .Where(a => addressIds.Contains(a.Id) && a.OrderLimits.Count > 0)
                                        .ToArray();
                        foreach (var order in orders)
                        {
                            var limit = addresses.Where(a => a.Id == order.AddressId)
                                        .SelectMany(a => a.OrderLimits)
                                        .FirstOrDefault(l => l.Supplier.Id == order.PriceList.Supplier.Id);
                            if (limit != null)
                            {
                                session.Save(new PendingLimitLog(log, limit, limit.ConsumeLimit((decimal)order.CalculateSum())));
                            }
                        }
                    }
                    //отмечаем заказа как удаленный до подтверждения
                    orders.Each(o => o.Deleted = true);
                    session.SaveEach(orders);
                    session.SaveEach(orders.Select(o => new AcceptedOrderLog(log, o)));
                }

                errors = errors.Concat(orders.Select(o => new OrderResult(o, orderitemMap))).ToList();
            }
            //информацию по отказам сохраняем для техподдержки
            foreach (var result in errors.Where(x => x.Result == OrderResultStatus.Reject))
            {
                if (!String.IsNullOrEmpty(log.Error))
                {
                    log.Error += Environment.NewLine;
                }
                var order = clientOrders.FirstOrDefault(x => x.ClientOrderId == result.ClientOrderId);
                if (order == null)
                {
                    continue;
                }
                var price = session.Get <PriceList>(order.PriceId);
                var sum   = order.Items.Sum(x => x.Count * x.Cost);
                log.Error += $"Заказ {result.ClientOrderId} на сумму {sum} на поставщика" +
                             $" {price?.Supplier?.Name} был отклонен по причине: {result.Error}";
            }

            //в результате удаления дублей для одного клиентского заказа может быть сформировано два результата
            //один на приемку части заявки второй на удаленные позиций-дублей
            //нужно объединить эти данные
            return(errors.GroupBy(x => Tuple.Create(x.ClientOrderId, x.Result))
                   .Select(x => {
                if (x.Count() == 1)
                {
                    return x.First();
                }
                var dst = x.First();
                dst.ServerOrderId = x.Max(y => y.ServerOrderId);
                dst.Lines.AddRange(x.Skip(1).SelectMany(y => y.Lines));
                return dst;
            })
                   .ToList());
        }