153 lines
4.0 KiB
C++
153 lines
4.0 KiB
C++
#include "eetv4adapter.h"
|
|
|
|
#include <QRegularExpression>
|
|
|
|
namespace
|
|
{
|
|
void setError(QString *error, const QString &message)
|
|
{
|
|
if (error != nullptr)
|
|
{
|
|
*error = message;
|
|
}
|
|
}
|
|
|
|
QDateTime withExplicitOffset(const QDateTime &dateTime)
|
|
{
|
|
if (!dateTime.isValid())
|
|
{
|
|
return {};
|
|
}
|
|
|
|
return dateTime.timeSpec() == Qt::LocalTime
|
|
? dateTime.toOffsetFromUtc(dateTime.offsetFromUtc())
|
|
: dateTime;
|
|
}
|
|
}
|
|
|
|
bool EetV4ShopConfig::validate(QString *error) const
|
|
{
|
|
if (!endpoint.isValid() || endpoint.scheme().compare(QStringLiteral("https"),
|
|
Qt::CaseInsensitive) != 0)
|
|
{
|
|
setError(error, QStringLiteral("EET v4 endpoint must be a valid HTTPS URL."));
|
|
return false;
|
|
}
|
|
if (taxpayerEic.isEmpty())
|
|
{
|
|
setError(error, QStringLiteral("EET v4 taxpayer EIC must not be empty."));
|
|
return false;
|
|
}
|
|
if (unitId < 1)
|
|
{
|
|
setError(error, QStringLiteral("EET v4 unit ID must be positive."));
|
|
return false;
|
|
}
|
|
if (cashRegisterId.isEmpty())
|
|
{
|
|
setError(error, QStringLiteral("EET v4 cash-register ID must not be empty."));
|
|
return false;
|
|
}
|
|
if (timeoutMilliseconds < 1)
|
|
{
|
|
setError(error, QStringLiteral("EET v4 timeout must be positive."));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool EetV4ShopAdapter::amountText(const QDecDouble &amount,
|
|
QString *text,
|
|
QString *error)
|
|
{
|
|
QString value = QString::fromLatin1(amount.toString());
|
|
if (value.contains(QRegularExpression(QStringLiteral("[eE]"))))
|
|
{
|
|
setError(error, QStringLiteral("Voucher amount must not use exponential notation."));
|
|
return false;
|
|
}
|
|
|
|
if (!value.contains(QLatin1Char('.')))
|
|
{
|
|
value += QStringLiteral(".00");
|
|
}
|
|
else
|
|
{
|
|
const int decimals = value.size() - value.indexOf(QLatin1Char('.')) - 1;
|
|
if (decimals > 2)
|
|
{
|
|
setError(error, QStringLiteral("Voucher amount has more than two decimal places."));
|
|
return false;
|
|
}
|
|
value = value.leftJustified(value.size() + (2 - decimals), QLatin1Char('0'));
|
|
}
|
|
|
|
EetV4Amount parsed;
|
|
if (!EetV4Amount::fromString(value, &parsed, error))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (text != nullptr)
|
|
{
|
|
*text = parsed.toString();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool EetV4ShopAdapter::createRequest(const Voucher &voucher,
|
|
const EetV4ShopConfig &config,
|
|
EetV4SaleRequest *request,
|
|
QString *error)
|
|
{
|
|
if (request == nullptr)
|
|
{
|
|
setError(error, QStringLiteral("EET v4 request output must not be null."));
|
|
return false;
|
|
}
|
|
if (!config.validate(error))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const QDateTime saleAt = withExplicitOffset(voucher.payDateTime());
|
|
if (!saleAt.isValid())
|
|
{
|
|
setError(error, QStringLiteral("Voucher payment date must be valid."));
|
|
return false;
|
|
}
|
|
|
|
QString totalText;
|
|
if (!amountText(voucher.totalPrice(), &totalText, error))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
EetV4Amount total;
|
|
if (!EetV4Amount::fromString(totalText, &total, error))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
EetV4SaleRequest result;
|
|
result.sentAt = withExplicitOffset(QDateTime::currentDateTime());
|
|
result.saleAt = saleAt;
|
|
result.firstSubmission = voucher.eetStatus() == Voucher::EET_FOR_SEND;
|
|
result.verificationMode = config.verificationMode;
|
|
result.taxpayerEic = config.taxpayerEic;
|
|
result.unitId = config.unitId;
|
|
result.cashRegisterId = config.cashRegisterId;
|
|
result.receiptNumber = voucher.numSer();
|
|
result.totalSale = total;
|
|
|
|
QStringList validationErrors;
|
|
if (!result.validate(&validationErrors))
|
|
{
|
|
setError(error, validationErrors.join(QStringLiteral("; ")));
|
|
return false;
|
|
}
|
|
|
|
*request = result;
|
|
return true;
|
|
}
|