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; } }
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); } }
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); } }
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); }