public virtual (decimal?, DeviceStatus) GetReceiptAmount() { decimal?receiptAmount = null; var(receiptStatusResponse, deviceStatus) = Request(CommandGetReceiptStatus, "T"); if (!deviceStatus.Ok) { deviceStatus.AddInfo($"Error occured while reading last receipt status"); return(null, deviceStatus); } var fields = receiptStatusResponse.Split(','); if (fields.Length < 3) { deviceStatus.AddInfo($"Error occured while parsing last receipt status"); deviceStatus.AddError("E409", "Wrong format of receipt status"); return(null, deviceStatus); } try { var amountString = fields[2]; if (amountString.Length > 0) { switch (amountString[0]) { case '+': receiptAmount = decimal.Parse(amountString.Substring(1), CultureInfo.InvariantCulture) / 100m; break; case '-': receiptAmount = -decimal.Parse(amountString.Substring(1), CultureInfo.InvariantCulture) / 100m; break; default: if (amountString.Contains(".")) { receiptAmount = decimal.Parse(amountString, CultureInfo.InvariantCulture); } else { receiptAmount = decimal.Parse(amountString, CultureInfo.InvariantCulture) / 100m; } break; } } } catch (Exception e) { deviceStatus = new DeviceStatus(); deviceStatus.AddInfo($"Error occured while parsing the amount of last receipt status"); deviceStatus.AddError("E409", e.Message); return(null, deviceStatus); } return(receiptAmount, deviceStatus); }
public override (string, DeviceStatus) GetLastDocumentNumber(string closeReceiptResponse) { var deviceStatus = new DeviceStatus(); var fields = closeReceiptResponse.Split('\t'); if (fields.Length < 2) { deviceStatus.AddInfo($"Error occured while parsing close receipt response"); deviceStatus.AddError("E409", $"Wrong format of close receipt response"); return(string.Empty, deviceStatus); } return(fields[1], deviceStatus); }
public override (decimal?, DeviceStatus) GetReceiptAmount() { decimal?receiptAmount = null; var(receiptStatusResponse, deviceStatus) = Request(CommandGetReceiptStatus); if (!deviceStatus.Ok) { deviceStatus.AddInfo($"Error occured while reading last receipt status"); return(null, deviceStatus); } var fields = receiptStatusResponse.Split('\t'); if (fields.Length < 5) { deviceStatus.AddInfo($"Error occured while parsing last receipt status"); deviceStatus.AddError("E409", "Wrong format of receipt status"); return(null, deviceStatus); } try { var amountString = fields[4]; if (amountString.Length > 0) { switch (amountString[0]) { case '+': receiptAmount = decimal.Parse(amountString.Substring(1), System.Globalization.CultureInfo.InvariantCulture) / 100m; break; case '-': receiptAmount = -decimal.Parse(amountString.Substring(1), System.Globalization.CultureInfo.InvariantCulture) / 100m; break; default: receiptAmount = decimal.Parse(amountString, System.Globalization.CultureInfo.InvariantCulture); break; } } } catch (Exception e) { deviceStatus = new DeviceStatus(); deviceStatus.AddInfo($"Error occured while parsing the amount of last receipt status"); deviceStatus.AddError("E409", e.Message); return(null, deviceStatus); } return(receiptAmount, deviceStatus); }
protected virtual DeviceStatus PrintReceiptBody(Receipt receipt) { if (receipt.Items == null || receipt.Items.Count == 0) { throw new StandardizedStatusMessageException("Receipt.Items must be not null or empty", "E410"); } DeviceStatus deviceStatus; uint itemNumber = 0; // Receipt items foreach (var item in receipt.Items) { itemNumber++; if (item.Type == ItemType.Comment || item.IsComment) { (_, deviceStatus) = AddComment(item.Text); if (!deviceStatus.Ok) { AbortReceipt(); deviceStatus.AddInfo($"Error occurred in the comment of Item {itemNumber}"); return(deviceStatus); } } else { if (item.PriceModifierValue < 0m) { throw new StandardizedStatusMessageException("PriceModifierValue amount must be positive number", "E403"); } if (item.PriceModifierValue != 0m && item.PriceModifierType == PriceModifierType.None) { throw new StandardizedStatusMessageException("PriceModifierValue must be 0 if priceModifierType is None", "E403"); } try { (_, deviceStatus) = AddItem( item.Text, item.UnitPrice, item.TaxGroup, item.Quantity, item.PriceModifierValue, item.PriceModifierType); } catch (StandardizedStatusMessageException e) { deviceStatus = new DeviceStatus(); deviceStatus.AddError(e.Code, e.Message); } if (!deviceStatus.Ok) { AbortReceipt(); deviceStatus.AddInfo($"Error occurred in Item {itemNumber}"); return(deviceStatus); } } } // Receipt payments if (receipt.Payments == null || receipt.Payments.Count == 0) { (_, deviceStatus) = FullPaymentAndCloseReceipt(); if (!deviceStatus.Ok) { AbortReceipt(); deviceStatus.AddInfo($"Error occurred while making full payment in cash and closing the receipt"); return(deviceStatus); } } else { uint paymentNumber = 0; foreach (var payment in receipt.Payments) { paymentNumber++; try { (_, deviceStatus) = AddPayment(payment.Amount, payment.PaymentType); } catch (StandardizedStatusMessageException e) { deviceStatus = new DeviceStatus(); deviceStatus.AddError(e.Code, e.Message); } if (!deviceStatus.Ok) { AbortReceipt(); deviceStatus.AddInfo($"Error occurred in Payment {paymentNumber}"); return(deviceStatus); } } (_, deviceStatus) = CloseReceipt(); if (!deviceStatus.Ok) { AbortReceipt(); deviceStatus.AddInfo($"Error occurred while closing the receipt"); return(deviceStatus); } } return(deviceStatus); }
public virtual (ReceiptInfo, DeviceStatus) PrintReceiptBody(Receipt receipt, bool reversalReceipt = false) { var receiptInfo = new ReceiptInfo(); var(fiscalMemorySerialNumber, deviceStatus) = GetFiscalMemorySerialNumber(); if (!deviceStatus.Ok) { return(receiptInfo, deviceStatus); } receiptInfo.FiscalMemorySerialNumber = fiscalMemorySerialNumber; if (receipt.Items == null || receipt.Items.Count == 0) { deviceStatus.AddError("E410", "Receipt.Items must be not null or empty"); return(receiptInfo, deviceStatus); } uint itemNumber = 0; // Receipt items foreach (var item in receipt.Items) { itemNumber++; if (item.Type == ItemType.Comment) { (_, deviceStatus) = AddComment(receipt.UniqueSaleNumber, item.Text); if (!deviceStatus.Ok) { deviceStatus.AddInfo($"Error occurred in Item {itemNumber}"); return(receiptInfo, deviceStatus); } } else { if (item.PriceModifierValue < 0m) { throw new StandardizedStatusMessageException("PriceModifierValue amount must be positive number", "E403"); } if (item.PriceModifierValue != 0m && item.PriceModifierType == PriceModifierType.None) { throw new StandardizedStatusMessageException("PriceModifierValue must be 0 if priceModifierType is None", "E403"); } try { (_, deviceStatus) = AddItem( receipt.UniqueSaleNumber, item.Text, item.UnitPrice, item.TaxGroup, item.Quantity, item.PriceModifierValue, item.PriceModifierType, reversalReceipt); } catch (StandardizedStatusMessageException e) { deviceStatus = new DeviceStatus(); deviceStatus.AddError(e.Code, e.Message); } if (!deviceStatus.Ok) { deviceStatus.AddInfo($"Error occurred in Item {itemNumber}"); return(receiptInfo, deviceStatus); } } } // Get receipt number and amount string receiptNumber; decimal?receiptAmount; (receiptNumber, receiptAmount, deviceStatus) = GetReceiptNumberAndAmount(); if (!deviceStatus.Ok) { return(receiptInfo, deviceStatus); } receiptInfo.ReceiptNumber = receiptNumber; receiptInfo.ReceiptAmount = receiptAmount ?? 0m; // Receipt payments if (receipt.Payments == null || receipt.Payments.Count == 0) { deviceStatus = FullPayment(); if (!deviceStatus.Ok) { deviceStatus.AddInfo($"Error occurred while making full payment in cash"); return(receiptInfo, deviceStatus); } } else { uint paymentNumber = 0; foreach (var payment in receipt.Payments) { paymentNumber++; if (payment.PaymentType == PaymentType.Change) { continue; } try { (_, deviceStatus) = AddPayment(payment.Amount, payment.PaymentType); } catch (StandardizedStatusMessageException e) { deviceStatus = new DeviceStatus(); deviceStatus.AddError(e.Code, e.Message); } if (!deviceStatus.Ok) { deviceStatus.AddInfo($"Error occurred in Payment {paymentNumber}"); return(receiptInfo, deviceStatus); } } } // Get the receipt date and time (current fiscal device date and time) DateTime?dateTime; (dateTime, deviceStatus) = GetDateTime(); if (!deviceStatus.Ok) { return(receiptInfo, deviceStatus); } receiptInfo.ReceiptDateTime = dateTime ?? DateTime.Now; if (deviceStatus.Ok) { deviceStatus = FullPayment(); } return(receiptInfo, deviceStatus); }
public virtual DeviceStatus ValidateReceipt(Receipt receipt) { var status = new DeviceStatus(); if (receipt.Items == null || receipt.Items.Count == 0) { status.AddError("E410", "Receipt is empty, no items"); return(status); } if (String.IsNullOrEmpty(receipt.UniqueSaleNumber)) { status.AddError("E405", "UniqueSaleNumber is empty"); return(status); } var uniqueSaleNumberMatch = Regex.Match(receipt.UniqueSaleNumber, "^[A-Z0-9]{8}-[A-Z0-9]{4}-[0-9]{7}$"); if (!uniqueSaleNumberMatch.Success) { status.AddError("E405", "Invalid format of UniqueSaleNumber"); return(status); } var row = 0; foreach (var item in receipt.Items) { row++; if (String.IsNullOrEmpty(item.Text)) { status.AddError("E407", $"Item {row}: \"text\" is empty"); } if (item.IsComment) { status.AddWarning("W401", $"Item {row}: \"isComment\" is deprecated in Item {row}. Use \"type\" : \"comment\" instead"); } // Validation of "type" : "sale" if (item.Type == ItemType.Sale) { if (item.PriceModifierValue <= 0 && item.PriceModifierType != PriceModifierType.None) { status.AddError("E403", $"Item {row}: \"priceModifierValue\" should be positive number"); } if (item.PriceModifierValue != 0 && item.PriceModifierType == PriceModifierType.None) { status.AddError("E403", $"Item {row}: \"priceModifierValue\" should'nt be \"none\" or empty. You can avoid setting priceModifier if you do not want price modification"); } if (item.Quantity <= 0) { status.AddError("E403", $"Item {row}: \"quantity\" should be positive number"); } if (item.TaxGroup == TaxGroup.Unspecified) { status.AddError("E403", $"Item {row}: \"taxGroup\" should'nt be \"unspecified\" or empty"); } try { GetTaxGroupText(item.TaxGroup); } catch (StandardizedStatusMessageException e) { status.AddError(e.Code, e.Message); } } if (!status.Ok) { return(status); } } if (receipt.Payments?.Count > 0) { row = 0; foreach (var payment in receipt.Payments) { row++; if (payment.Amount <= 0) { status.AddError("E403", $"Payment {row}: \"amount\" should be positive number"); } try { GetPaymentTypeText(payment.PaymentType); } catch (StandardizedStatusMessageException e) { status.AddError(e.Code, e.Message); } if (!status.Ok) { status.AddInfo($"Error occured at Payment {row}"); return(status); } } } return(status); }
public virtual DeviceStatus ValidateReceipt(Receipt receipt) { var status = new DeviceStatus(); if (receipt.Items == null || receipt.Items.Count == 0) { status.AddError("E410", "Receipt is empty, no items"); return(status); } if (String.IsNullOrEmpty(receipt.UniqueSaleNumber)) { status.AddError("E405", "UniqueSaleNumber is empty"); return(status); } var uniqueSaleNumberMatch = Regex.Match(receipt.UniqueSaleNumber, "^[A-Z0-9]{8}-[A-Z0-9]{4}-[0-9]{7}$"); if (!uniqueSaleNumberMatch.Success) { status.AddError("E405", "Invalid format of UniqueSaleNumber"); return(status); } var itemsTotalAmount = 0.00m; var row = 0; foreach (var item in receipt.Items) { row++; if (String.IsNullOrEmpty(item.Text)) { status.AddError("E407", $"Item {row}: \"text\" is empty"); } // Validation of "type" : "sale" if (item.Type == ItemType.Sale) { if (item.PriceModifierValue <= 0 && item.PriceModifierType != PriceModifierType.None) { status.AddError("E403", $"Item {row}: \"priceModifierValue\" should be positive number"); } if (item.PriceModifierValue != 0 && item.PriceModifierType == PriceModifierType.None) { status.AddError("E403", $"Item {row}: \"priceModifierValue\" should'nt be \"none\" or empty. You can avoid setting priceModifier if you do not want price modification"); } if (item.Quantity <= 0) { status.AddError("E403", $"Item {row}: \"quantity\" should be positive number"); } if (item.TaxGroup == TaxGroup.Unspecified) { status.AddError("E403", $"Item {row}: \"taxGroup\" should'nt be \"unspecified\" or empty"); } try { GetTaxGroupText(item.TaxGroup); } catch (StandardizedStatusMessageException e) { status.AddError(e.Code, e.Message); } var quantity = Math.Round(item.Quantity, 3, MidpointRounding.AwayFromZero); var unitPrice = Math.Round(item.UnitPrice, 2, MidpointRounding.AwayFromZero); var itemPrice = quantity * unitPrice; switch (item.PriceModifierType) { case PriceModifierType.DiscountAmount: itemPrice -= item.PriceModifierValue; break; case PriceModifierType.DiscountPercent: itemPrice -= itemPrice * (item.PriceModifierValue / 100.0m); break; case PriceModifierType.SurchargeAmount: itemPrice += item.PriceModifierValue; break; case PriceModifierType.SurchargePercent: itemPrice += itemPrice * (item.PriceModifierValue / 100.0m); break; } itemsTotalAmount += Math.Round(itemPrice, 2, MidpointRounding.AwayFromZero); } if (!status.Ok) { return(status); } } if (receipt.Payments?.Count > 0) { var paymentAmount = 0.00m; row = 0; foreach (var payment in receipt.Payments) { row++; if (payment.Amount <= 0 && payment.PaymentType != PaymentType.Change) { status.AddError("E403", $"Payment {row}: \"amount\" should be positive number"); } if (payment.Amount >= 0 && payment.PaymentType == PaymentType.Change) { status.AddError("E403", $"Change {row}: \"amount\" should be negative number"); } try { if (payment.PaymentType != PaymentType.Change) { // Check if the payment type is supported GetPaymentTypeText(payment.PaymentType); } } catch (StandardizedStatusMessageException e) { status.AddError(e.Code, e.Message); } if (!status.Ok) { status.AddInfo($"Error occured at Payment {row}"); return(status); } var amount = Math.Round(payment.Amount, 2, MidpointRounding.AwayFromZero); paymentAmount += amount; } var difference = Math.Abs(paymentAmount - itemsTotalAmount); if (difference >= 0.01m && difference / itemsTotalAmount > 0.00001m) { status.AddError("E403", $"Payment total amount ({paymentAmount.ToString(CultureInfo.InvariantCulture)}) should be the same as the items total amount ({itemsTotalAmount.ToString(CultureInfo.InvariantCulture)})"); } } return(status); }