Files
EetCpp/libEet/eetv4request.cpp
T

119 lines
3.9 KiB
C++

#include "eetv4request.h"
#include <QRegularExpression>
namespace
{
void addError(QStringList *errors, const QString &message)
{
if (errors != nullptr)
{
errors->append(message);
}
}
bool isValidEic(const QString &value)
{
static const QRegularExpression expression(QStringLiteral("^CZ[0-9]{8,10}$"));
return expression.match(value).hasMatch();
}
bool isValidRestrictedString(const QString &value, int maxLength)
{
static const QRegularExpression expression(QStringLiteral("^[0-9A-Za-z.,:;/#_\\- ]+$"));
return value.size() >= 1 && value.size() <= maxLength && expression.match(value).hasMatch();
}
}
EetV4Amount::EetV4Amount(qint64 cents)
: m_cents(cents)
{
}
bool EetV4Amount::fromString(const QString &value, EetV4Amount *amount, QString *error)
{
static const QRegularExpression expression(
QStringLiteral("^(?:(?:0|-?[1-9][0-9]{0,7})\\.[0-9]{2}|-0\\.(?:0[1-9]|[1-9][0-9]))$"));
if (!expression.match(value).hasMatch())
{
if (error != nullptr)
{
*error = QStringLiteral("Amount must contain two decimal places and fit the EET range.");
}
return false;
}
const bool negative = value.startsWith('-');
const QString absolute = negative ? value.mid(1) : value;
const QStringList parts = absolute.split('.');
const qint64 whole = parts.at(0).toLongLong();
const qint64 cents = whole * 100 + parts.at(1).toLongLong();
if (amount != nullptr)
{
*amount = EetV4Amount(negative ? -cents : cents);
}
return true;
}
qint64 EetV4Amount::cents() const
{
return m_cents;
}
QString EetV4Amount::toString() const
{
const bool negative = m_cents < 0;
const qint64 absolute = negative ? -m_cents : m_cents;
return QStringLiteral("%1%2.%3")
.arg(negative ? QStringLiteral("-") : QString())
.arg(absolute / 100)
.arg(absolute % 100, 2, 10, QLatin1Char('0'));
}
bool EetV4SaleRequest::validate(QStringList *errors) const
{
bool valid = true;
const auto require = [&valid, errors](bool condition, const QString &message) {
if (!condition)
{
valid = false;
addError(errors, message);
}
};
require(!messageUuid.isNull(), QStringLiteral("messageUuid must not be null."));
require(sentAt.isValid() && sentAt.timeSpec() != Qt::LocalTime,
QStringLiteral("sentAt must be a valid timestamp with an explicit offset."));
require(saleAt.isValid() && saleAt.timeSpec() != Qt::LocalTime,
QStringLiteral("saleAt must be a valid timestamp with an explicit offset."));
require(isValidEic(taxpayerEic),
QStringLiteral("taxpayerEic must match CZ followed by 8 to 10 digits."));
require(authorizingTaxpayerEic.isEmpty() || isValidEic(authorizingTaxpayerEic),
QStringLiteral("authorizingTaxpayerEic has an invalid format."));
require(!multipleTaxpayerAuthorization || !authorizingTaxpayerEic.isEmpty(),
QStringLiteral("authorizingTaxpayerEic is required for multiple taxpayer authorization."));
require(unitId >= 1 && unitId <= 999999999,
QStringLiteral("unitId must be between 1 and 999999999."));
require(isValidRestrictedString(cashRegisterId, 20),
QStringLiteral("cashRegisterId has an invalid format or length."));
require(isValidRestrictedString(receiptNumber, 25),
QStringLiteral("receiptNumber has an invalid format or length."));
return valid;
}
QString EetV4SaleRequest::formatDateTime(const QDateTime &dateTime)
{
const int offset = dateTime.offsetFromUtc();
const QChar sign = offset < 0 ? QLatin1Char('-') : QLatin1Char('+');
const int absoluteOffset = qAbs(offset);
return dateTime.toString(QStringLiteral("yyyy-MM-dd'T'HH:mm:ss"))
+ sign
+ QStringLiteral("%1:%2")
.arg(absoluteOffset / 3600, 2, 10, QLatin1Char('0'))
.arg((absoluteOffset % 3600) / 60, 2, 10, QLatin1Char('0'));
}