static async Task SendSalesDocumentAsync(CashReceipt preparedReceipt, SalesDocumentDTO doc)
        {
            if (doc.IsValid)
            {
                logger.Info("Отправка документа на сервер фискализации...");
                var httpCode = await PostSalesDocumentAsync(doc);

                switch (httpCode)
                {
                case HttpStatusCode.OK:
                    logger.Info("Документ успешно отправлен на сервер фискализации.");
                    preparedReceipt.Sent = true;
                    break;

                default:
                    logger.Warn(string.Format("Документ не был отправлен на сервер фискализации. Http код - {0} ({1}).", (int)httpCode, httpCode));
                    preparedReceipt.Sent = false;
                    break;
                }
                preparedReceipt.HttpCode = (int)httpCode;
            }
            else
            {
                logger.Warn(string.Format("Документ \"{0}\" не валиден и не был отправлен на сервер фискализации (-1).", doc.DocNum));
                preparedReceipt.HttpCode = -1;
                preparedReceipt.Sent     = false;
            }
        }
예제 #2
0
        private HttpStatusCode SendDocument(HttpClient httpClient, SalesDocumentDTO doc, int orderId)
        {
            try {
                HttpResponseMessage response = httpClient.PostAsJsonAsync(sendDocumentAddress, doc).Result;

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    logger.Info($"Чек для заказа №{orderId} отправлен. HTTP Code: {(int)response.StatusCode} {response.StatusCode}");
                }
                else
                {
                    SendDocumentResultDTO sendDocumentResult = new SendDocumentResultDTO();
                    try {
                        sendDocumentResult = response.Content.ReadAsAsync <SendDocumentResultDTO>().Result;
                    }
                    catch (Exception e) {
                        logger.Error(e, "Ошибка при чтении результата отправки");
                    }

                    logger.Warn($"Не удалось отправить чек для заказа №{orderId}. HTTP Code: {(int)response.StatusCode} {response.StatusCode}. " +
                                $"Message: {sendDocumentResult.Message ?? "Ошибка чтения"}. Запрашиваю актуальный статус...");
                    try {
                        var statusResponse = httpClient.GetAsync(String.Format(documentStatusAddress, doc.Id)).Result;

                        if (statusResponse.IsSuccessStatusCode)
                        {
                            var documentStatusDTO = statusResponse.Content.ReadAsAsync <SalesDocumentsStatusDTO>().Result;
                            logger.Info($"Актульный статус чека для заказа №{orderId}: {documentStatusDTO.Status}");
                            if (new[] { DocumentStatus.Completed, DocumentStatus.WaitForCallback, DocumentStatus.Printed }.Contains(documentStatusDTO.Status))
                            {
                                return(HttpStatusCode.OK);
                            }
                        }
                        else
                        {
                            logger.Warn($"Не удалось получить актуальный статус чека для заказа №{orderId}. " +
                                        $"HTTP Code: {(int)statusResponse.StatusCode} {statusResponse.StatusCode}");
                        }
                    }
                    catch (Exception ex) {
                        logger.Error(ex, $"Ошибка при получении актального статуса чека для заказа №{orderId}");
                    }
                }

                return(response.StatusCode);
            }
            catch (Exception ex) {
                logger.Error(ex, "Ошибка при отправке на сервер фискализации");
                return(0);
            }
        }
예제 #3
0
        private void SendForOrdersWithNotSendReceipts(IUnitOfWork uow, IEnumerable <ReceiptForOrderNode> nodes, ref int notValidCount)
        {
            IList <PreparedReceiptNode> receiptNodesToSend = new List <PreparedReceiptNode>();
            int sentBefore = 0;

            foreach (var receipt in uow.GetById <CashReceipt>(nodes.Select(n => n.ReceiptId).Where(x => x.HasValue).Select(x => x.Value)))
            {
                if (receipt.Sent)
                {
                    sentBefore++;
                    continue;
                }

                var doc = new SalesDocumentDTO(receipt.Order, receipt.Order.Contract?.Organization?.Leader?.ShortName);

                CashBox cashBox = null;
                if (receipt.Order.Contract?.Organization?.CashBoxId != null)
                {
                    cashBox = cashBoxes.FirstOrDefault(x => x.Id == receipt.Order.Contract.Organization.CashBoxId);
                }

                if (doc.IsValid && cashBox != null)
                {
                    var newPreparedReceiptNode = new PreparedReceiptNode {
                        CashReceipt      = receipt,
                        SalesDocumentDTO = doc,
                        CashBox          = cashBox
                    };

                    receiptNodesToSend.Add(newPreparedReceiptNode);

                    if (receiptNodesToSend.Count >= maxReceiptsAllowedToSendInOneGo)
                    {
                        break;
                    }
                }
                else
                {
                    if (cashBox == null)
                    {
                        logger.Warn($"Для заказа №{receipt.Order.Id} не удалось подобрать кассовый аппарат для отправки. Пропускаю");
                    }

                    notValidCount++;
                    receipt.HttpCode = 0;
                    receipt.Sent     = false;
                    uow.Save(receipt);
                }
            }

            if (sentBefore > 0)
            {
                logger.Info($"{sentBefore} {NumberToTextRus.Case(sentBefore, "документ был отправлен", "документа было отправлено", "документов было отправлено")} ранее.");
            }

            logger.Info($"Количество чеков для переотправки: {receiptNodesToSend.Count} (Макс.: {maxReceiptsAllowedToSendInOneGo})");
            if (!receiptNodesToSend.Any())
            {
                return;
            }

            var result = salesReceiptSender.SendReceipts(receiptNodesToSend.ToArray());

            foreach (var sendReceiptNode in result)
            {
                sendReceiptNode.CashReceipt.Sent     = sendReceiptNode.SendResultCode == HttpStatusCode.OK;
                sendReceiptNode.CashReceipt.HttpCode = (int)sendReceiptNode.SendResultCode;
                uow.Save(sendReceiptNode.CashReceipt);
            }
        }
예제 #4
0
        private void SendForOrdersWithoutReceipts(IUnitOfWork uow, IEnumerable <ReceiptForOrderNode> nodes, ref int notValidCount)
        {
            IList <PreparedReceiptNode> receiptNodesToSend = new List <PreparedReceiptNode>();

            foreach (var order in uow.GetById <Order>(nodes.Select(x => x.OrderId)))
            {
                var newReceipt = new CashReceipt {
                    Order = order
                };
                var doc = new SalesDocumentDTO(order, order.Contract?.Organization?.Leader?.ShortName);

                CashBox cashBox = null;
                if (order.Contract?.Organization?.CashBoxId != null)
                {
                    cashBox = cashBoxes.FirstOrDefault(x => x.Id == order.Contract.Organization.CashBoxId);
                }

                if (doc.IsValid && cashBox != null)
                {
                    var newPreparedReceiptNode = new PreparedReceiptNode {
                        CashReceipt      = newReceipt,
                        SalesDocumentDTO = doc,
                        CashBox          = cashBox
                    };

                    receiptNodesToSend.Add(newPreparedReceiptNode);

                    if (receiptNodesToSend.Count >= maxReceiptsAllowedToSendInOneGo)
                    {
                        break;
                    }
                }
                else
                {
                    if (cashBox == null)
                    {
                        logger.Warn($"Для заказа №{order.Id} не удалось подобрать кассовый аппарат для отправки. Пропускаю");
                    }

                    notValidCount++;
                    newReceipt.HttpCode = 0;
                    newReceipt.Sent     = false;
                    uow.Save(newReceipt);
                }
            }

            logger.Info($"Количество новых чеков для отправки: {receiptNodesToSend.Count} (Макс.: {maxReceiptsAllowedToSendInOneGo})");
            if (!receiptNodesToSend.Any())
            {
                return;
            }

            var result = salesReceiptSender.SendReceipts(receiptNodesToSend.ToArray());

            foreach (var sendReceiptNode in result)
            {
                sendReceiptNode.CashReceipt.Sent     = sendReceiptNode.SendResultCode == HttpStatusCode.OK;
                sendReceiptNode.CashReceipt.HttpCode = (int)sendReceiptNode.SendResultCode;
                uow.Save(sendReceiptNode.CashReceipt);
            }
        }
        public static async Task RunAsync(string baseAddress, AuthenticationHeaderValue authentication)
        {
            if (httpClient == null)
            {
                httpClient = new HttpClient();
                Fiscalization.baseAddress = baseAddress;
                httpClient.BaseAddress    = new Uri(baseAddress);
                httpClient.DefaultRequestHeaders.Accept.Clear();
                httpClient.DefaultRequestHeaders.Authorization = authentication;
                httpClient.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue("application/json")
                    );
            }
            logger.Info(string.Format("Авторизация и проверка фискального регистратора..."));
            FinscalizatorStatusResponseDTO response = await GetSatusAsync("fn/v1/status");

            if (response != null)
            {
                switch (response.Status)
                {
                case FiscalRegistratorStatus.Associated:
                    logger.Warn("Клиент успешно связан с розничной точкой, но касса еще ни разу не вышла на связь и не сообщила свое состояние.");
                    return;

                case FiscalRegistratorStatus.Failed:
                    logger.Warn("Проблемы получения статуса фискального накопителя. Этот статус не препятствует добавлению документов для фискализации. " +
                                "Все документы будут добавлены в очередь на сервере и дождутся момента когда касса будет в состоянии их фискализировать.");
                    break;

                case FiscalRegistratorStatus.Ready:
                    logger.Info("Соединение с фискальным накопителем установлено и его состояние позволяет фискализировать чеки.");
                    break;

                default:
                    logger.Warn(string.Format("Провал с сообщением: \"{0}\".", response.Message));
                    return;
                }
            }
            else
            {
                logger.Warn("Провал. Нет ответа от сервиса.");
                return;
            }

            logger.Info("Подготовка документов к отправке на сервер фискализации...");
            int sent = 0, sentBefore = 0, notValid = 0, receiptsToSend = 0;

            using (IUnitOfWork uow = UnitOfWorkFactory.CreateWithoutRoot("[Fisk] Получение подходящих заказов и чеков (если они есть)...")) {
                var ordersAndReceiptNodes = GetReceiptsForOrders(uow);
                var withoutReceipts       = ordersAndReceiptNodes.Where(r => r.ReceiptId == null);
                var withNotSentReceipts   = ordersAndReceiptNodes.Where(r => r.ReceiptId.HasValue && r.WasSent != true);
                var cashier = uow.GetById <Employee>(new BaseParametersProvider().DefaultSalesReceiptCashierId).ShortName;
                receiptsToSend = withoutReceipts.Count() + withNotSentReceipts.Count();

                if (receiptsToSend <= 0)
                {
                    logger.Info("Нет документов для отправки.");
                    return;
                }

                if (withoutReceipts.Any())
                {
                    var ordersWithoutReceipts = uow.GetById <Order>(withoutReceipts.Select(n => n.OrderId));
                    foreach (var o in ordersWithoutReceipts)
                    {
                        logger.Info(string.Format("Подготовка документа \"№{0}\" к отправке...", o.Id));
                        var newReceipt = new CashReceipt {
                            Order = o
                        };
                        var doc = new SalesDocumentDTO(o, cashier);
                        if (!doc.IsValid)
                        {
                            notValid++;
                        }
                        await SendSalesDocumentAsync(newReceipt, doc);

                        uow.Save(newReceipt);
                        if (newReceipt.Sent)
                        {
                            logger.Info(string.Format("Чек для заказа \"№{0}\" отправлен", o.Id));
                            sent++;
                        }
                        continue;
                    }
                }

                if (withNotSentReceipts.Any())
                {
                    var ordersWithNotSentReceipts = uow.GetById <Order>(withNotSentReceipts.Select(n => n.OrderId));
                    var notSentReceipts           = uow.GetById <CashReceipt>(withNotSentReceipts.Select(n => n.ReceiptId.Value));
                    foreach (var r in notSentReceipts)
                    {
                        if (r.Sent)
                        {
                            sentBefore++;
                            continue;
                        }
                        logger.Info(string.Format("Подготовка документа \"№{0}\" к переотправке...", r.Order.Id));
                        var doc = new SalesDocumentDTO(r.Order, cashier);
                        if (!doc.IsValid)
                        {
                            notValid++;
                        }
                        await SendSalesDocumentAsync(r, doc);

                        uow.Save(r);
                        if (r.Sent)
                        {
                            logger.Info(string.Format("Чек для заказа \"№{0}\" переотправлен", r.Order.Id));
                            sent++;
                        }
                        continue;
                    }
                }
                uow.Commit();
            }

            logger.Info(
                string.Format(
                    "За текущую сессию {0} {1} {2} из {3}.",
                    NumberToTextRus.Case(sent, "был отправлен", "было отправлено", "было отправлено"),
                    sent,
                    NumberToTextRus.Case(sent, "чек", "чека", "чеков"),
                    receiptsToSend
                    )
                );
            if (sentBefore > 0)
            {
                logger.Info(
                    string.Format(
                        "{0} {1} ранее.",
                        sentBefore,
                        NumberToTextRus.Case(sentBefore, "документ был отправлен", "документа было отправлено", "документов было отправлено")
                        )
                    );
            }
            if (notValid > 0)
            {
                logger.Info(
                    string.Format(
                        "{0} {1}.",
                        notValid,
                        NumberToTextRus.Case(notValid, "документ не валиден", "документа не валидно", "документов не валидно")
                        )
                    );
            }
        }
        static async Task <HttpStatusCode> PostSalesDocumentAsync(SalesDocumentDTO order)
        {
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(baseAddress + "/fn/v1/doc", order);

            return(response.StatusCode);
        }