119 lines
3.9 KiB
C++
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'));
|
|
}
|