Commit 965b530d authored by Martin Straka's avatar Martin Straka Committed by Karel Slaný
Browse files

Added databoxCreditInfo service, xml interface and task.

parent 4ccf88d1
......@@ -218,6 +218,7 @@ SOURCES += \
src/sqlite/zfo_db.cpp \
src/sqlite/zfo_db_tables.cpp \
src/worker/task_change_password.cpp \
src/worker/task_credit_info.cpp \
src/worker/task_download_account_info.cpp \
src/worker/task_download_delivery_info.cpp \
src/worker/task_download_dt_info.cpp \
......@@ -386,6 +387,7 @@ HEADERS += \
src/worker/emitter.h \
src/worker/task.h \
src/worker/task_change_password.h \
src/worker/task_credit_info.h \
src/worker/task_download_account_info.h \
src/worker/task_download_delivery_info.h \
src/worker/task_download_dt_info.h \
......
......@@ -41,6 +41,7 @@
#include "src/setwrapper.h"
#include "src/sqlite/zfo_db.h"
#include "src/worker/task_change_password.h"
#include "src/worker/task_credit_info.h"
#include "src/worker/task_download_account_info.h"
#include "src/worker/task_download_delivery_info.h"
#include "src/worker/task_download_dt_info.h"
......@@ -614,14 +615,14 @@ QList<Isds::PDZInfoRec> Isds::Tasks::downloadPdzInfo(const AcntId &acntId,
if (Q_UNLIKELY((GlobInstcs::workPoolPtr == Q_NULLPTR) ||
dbID.isEmpty())) {
Q_ASSERT(0);
return QList<Isds::PDZInfoRec>();
return QList<PDZInfoRec>();
}
TaskPDZInfo *task =
new (::std::nothrow) TaskPDZInfo(acntId, dbID);
if (Q_UNLIKELY(task == Q_NULLPTR)) {
Q_ASSERT(0);
return QList<Isds::PDZInfoRec>();
return QList<PDZInfoRec>();
}
task->setAutoDelete(false);
GlobInstcs::workPoolPtr->runSingle(task);
......@@ -654,3 +655,32 @@ void Isds::Tasks::downloadPdzSendInfo(const AcntId &acntId, const QString &dbID,
canSendInitiatory = task->m_canSendInitiatory;
delete task; task = Q_NULLPTR;
}
QList<Isds::CreditEvent> Isds::Tasks::creditInfo(const AcntId &acntId,
const QString &dbID, const QDate &fromDate, const QDate &toDate,
qint64 &currentCredit, QString &notifEmail)
{
debugFuncCall();
if (Q_UNLIKELY((GlobInstcs::workPoolPtr == Q_NULLPTR) ||
dbID.isEmpty())) {
Q_ASSERT(0);
return QList<CreditEvent>();
}
TaskCreditInfo *task =
new (::std::nothrow) TaskCreditInfo(acntId, dbID, fromDate, toDate);
if (Q_UNLIKELY(task == Q_NULLPTR)) {
Q_ASSERT(0);
return QList<CreditEvent>();
}
task->setAutoDelete(false);
GlobInstcs::workPoolPtr->runSingle(task);
currentCredit = task->m_currentCredit;
notifEmail = task->m_notifEmail;
QList<CreditEvent> creditEvents(task->m_creditEvents);
delete task; task = Q_NULLPTR;
return creditEvents;
}
......@@ -241,5 +241,22 @@ namespace Isds {
void downloadPdzSendInfo(const AcntId &acntId,
const QString &dbID, bool &canSendNormal,
bool &canSendInitiatory);
/*!
* @brief Download credit event information.
*
* @param[in] acntId Account identifier.
* @param[in] dbId Data box identifier.
* @param[in] fromDate From date.
* @param[in] toDate To date.
* @param[out] currentCredit Remaining credit in CZK.
* @param[out] notifEmail Notification email address.
* @return Credit event list.
*/
static
QList<Isds::CreditEvent> creditInfo(const AcntId &acntId,
const QString &dbID, const QDate &fromDate,
const QDate &toDate, qint64 &currentCredit,
QString &notifEmail);
};
}
......@@ -363,3 +363,46 @@ enum Isds::Type::Error Isds::pdzSendInfo(Session &session, const QString &dbID,
return Type::ERR_SUCCESS;
}
enum Isds::Type::Error Isds::dataBoxCreditInfo(Session &session,
const QString &dbID, const QDate &fromDate, const QDate &toDate,
qint64 &currentCredit, QString &notifEmail, QList<CreditEvent> &history,
DbStatus *status, QString *errMsg)
{
QByteArray response;
enum Connection::ErrCode errCode = Connection::communicate(
session, DB_SERVICE, Xml::soapRequestDataBoxCerditInfo(dbID,
fromDate, toDate), response);
if (errCode != Connection::ERR_NO_ERROR) {
if (errMsg != Q_NULLPTR) {
*errMsg = session.ctx()->lastIsdsMsg();
}
return errCode2Error(errCode);
}
bool iOk = false;
DbStatus dbStatus = Xml::toDbStatus(response, &iOk);
if (Q_UNLIKELY(!iOk)) {
return Type::ERR_XML;
}
if (errMsg != Q_NULLPTR) {
*errMsg = dbStatus.message();
}
iOk = dbStatus.ok();
if (status != Q_NULLPTR) {
*status = macroStdMove(dbStatus);
}
/* Cannot use dbStatus.ok(), content might be moved. */
if (Q_UNLIKELY(!iOk)) {
return Type::ERR_ISDS;
}
/* Read data box credit info content. */
history = Xml::toDataBoxCreditInfo(response, currentCredit,
notifEmail, &iOk);
if (Q_UNLIKELY(!iOk)) {
return Type::ERR_XML;
}
return Type::ERR_SUCCESS;
}
......@@ -163,4 +163,24 @@ namespace Isds {
enum Type::Error pdzSendInfo(Session &session, const QString &dbID,
enum Type::PdzMessageType type, bool &canSend,
DbStatus *status = Q_NULLPTR, QString *errMsg = Q_NULLPTR);
/*!
* @brief Download data box credit info using <DataBoxCreditInfo>.
*
* @param[in,out] session Communication session.
* @param[in] dbID Data box ID.
* @param[in] fromDate From date.
* @param[in] toDate To date.
* @param[out] currentCredit Remaining credit in CZK.
* @param[out] notifEmail Notification email address.
* @param[out] history List of credit evens.
* @param[out] status Status as reported by the ISDS.
* @param[out] errMsg Error message.
* @return Error status.
*/
enum Type::Error dataBoxCreditInfo(Session &session, const QString &dbID,
const QDate &fromDate, const QDate &toDate,
qint64 &currentCredit, QString &notifEmail,
QList<CreditEvent> &history, DbStatus *status = Q_NULLPTR,
QString *errMsg = Q_NULLPTR);
}
......@@ -1592,6 +1592,247 @@ fail:
return QList<PDZInfoRec>();
}
/*!
* @brief Read credit event content from DOM element node.
*
* @param[in] elem DOM element node.
* @param[out] ok Set to false on error.
* @return Data result content, null value on error.
*/
static
Isds::CreditEvent readCreditEventContent(const QDomElement &elem, bool *ok)
{
if (Q_UNLIKELY(elem.isNull())) {
if (ok != Q_NULLPTR) {
*ok = false;
}
return Isds::CreditEvent();
}
bool iOk = false;
QString value;
Isds::CreditEvent event;
const QDomNodeList childNodes = elem.childNodes();
for (int i = 0; i < childNodes.size(); ++i) {
const QDomNode &node = childNodes.at(i);
if (Q_UNLIKELY(node.nodeType() != QDomNode::ElementNode)) {
continue;
}
const QDomElement elem = node.toElement();
const QString localName = elem.localName();
if (localName == QLatin1String("ciEventTime")) {
value = Isds::Xml::readSingleChildStringValue(elem, &iOk);
if (iOk) {
event.setTime(
Isds::isoDateTimeStrToUtcDateTime(value));
} else {
goto fail;
}
} else if (localName == QLatin1String("ciCreditChange")) {
value = Isds::Xml::readSingleChildStringValue(elem, &iOk);
if (iOk) {
event.setCreditChange(value.toLongLong());
} else {
goto fail;
}
} else if (localName == QLatin1String("ciCreditAfter")) {
value = Isds::Xml::readSingleChildStringValue(elem, &iOk);
if (iOk) {
event.setCreditAfter(value.toLongLong());
} else {
goto fail;
}
} else {
/*
* There may be other entries in the supplied nodes
* but we shall ignore them.
*/
}
}
if (ok != Q_NULLPTR) {
*ok = true;
}
return event;
fail:
if (ok != Q_NULLPTR) {
*ok = false;
}
return Isds::CreditEvent();
}
/*!
* @brief Read data box credit event list content from DOM element node.
*
* @param[in] elem DOM element node.
* @param[out] ok Set to false on error.
* @return Result list, empty list on error.
*/
static
QList<Isds::CreditEvent> readCreditEventList(const QDomElement &elem, bool *ok)
{
if (Q_UNLIKELY(elem.isNull())) {
/* No attachment list found, treat this as an error. */
if (ok != Q_NULLPTR) {
*ok = false;
}
return QList<Isds::CreditEvent>();
}
bool iOk = false;
QList<Isds::CreditEvent> history;
const QDomNodeList childNodes = elem.childNodes();
for (int i = 0; i < childNodes.size(); ++i) {
const QDomNode &node = childNodes.at(i);
if (Q_UNLIKELY(node.nodeType() != QDomNode::ElementNode)) {
continue;
}
const QDomElement elem = node.toElement();
if (elem.localName() == QLatin1String("ciRecord")) {
Isds::CreditEvent event = readCreditEventContent(elem,
&iOk);
if (iOk) {
history.append(event);
} else {
goto fail;
}
} else {
/* There shouldn't be other content. */
Q_ASSERT(0);
goto fail;
}
}
if (ok != Q_NULLPTR) {
*ok = true;
}
return history;
fail:
if (ok != Q_NULLPTR) {
*ok = false;
}
return QList<Isds::CreditEvent>();
}
/*!
* @brief Read data box credit info result list content and search frame
* status from DOM element node.
*
* @param[in] dom DOM document.
* @param[out] currentCredit Current credit in CZK.
* @param[out] notifEmail Notification email address
* @param[out] ok Set to false on any error.
* @return Result list, empty list on error.
*/
static
QList<Isds::CreditEvent> readDataBoxCreditInfo(const QDomDocument &dom,
qint64 &currentCredit, QString &notifEmail, bool *ok)
{
if (Q_UNLIKELY(dom.isNull())) {
Q_ASSERT(0);
return QList<Isds::CreditEvent>();
}
bool iOk = false;
QString value;
QList<Isds::CreditEvent> history;
const QDomElement elem = Isds::Xml::findSingleDomElement(dom,
QLatin1String("DataBoxCreditInfoResponse"));
const QDomNodeList childNodes = elem.childNodes();
for (int i = 0; i < childNodes.size(); ++i) {
const QDomNode &node = childNodes.at(i);
if (Q_UNLIKELY(node.nodeType() != QDomNode::ElementNode)) {
continue;
}
const QDomElement elem = node.toElement();
const QString localName = elem.localName();
if (localName == QLatin1String("currentCredit")) {
value = Isds::Xml::readSingleChildStringValue(elem,
&iOk);
if (iOk) {
currentCredit = value.toLongLong();
} else {
goto fail;
}
} else if (localName == QLatin1String("notifEmail")) {
value = Isds::Xml::readSingleChildStringValue(elem,
&iOk);
if (iOk) {
notifEmail = ::std::move(value);
} else {
goto fail;
}
} else if (localName == QLatin1String("ciRecords")) {
QList<Isds::CreditEvent> cel =
readCreditEventList(elem, &iOk);
if (iOk) {
history = macroStdMove(cel);
} else {
goto fail;
}
} else {
/*
* There may be other entries in the supplied nodes
* but we shall ignore them.
*/
}
}
if (ok != Q_NULLPTR) {
*ok = true;
}
return history;
fail:
if (ok != Q_NULLPTR) {
*ok = false;
}
return QList<Isds::CreditEvent>();
}
QList<Isds::CreditEvent> Isds::Xml::toDataBoxCreditInfo(
const QByteArray &xmlData, qint64 &currentCredit, QString &notifEmail,
bool *ok)
{
if (Q_UNLIKELY(xmlData.isEmpty())) {
if (ok != Q_NULLPTR) {
*ok = false;
}
return QList<CreditEvent>();
}
bool iOk = false;
QDomDocument dom = toDomDocument(xmlData, &iOk);
QList<CreditEvent> history;
history = readDataBoxCreditInfo(dom, currentCredit, notifEmail, &iOk);
if (Q_UNLIKELY(!iOk)) {
goto fail;
}
if (ok != Q_NULLPTR) {
*ok = true;
}
return history;
fail:
if (ok != Q_NULLPTR) {
*ok = false;
}
return QList<CreditEvent>();
}
QByteArray Isds::Xml::soapRequestGetPasswordInfo(void)
{
QByteArray xmlData("<GetPasswordInfo xmlns=\"" ISDS_XML_NS "\">"
......@@ -1686,3 +1927,27 @@ QByteArray Isds::Xml::soapRequestPdzSendInfo(const QString &dbID,
xmlData.append("</PDZType></PDZSendInfo>");
return coatWithSoapEnvelope(xmlData);
}
QByteArray Isds::Xml::soapRequestDataBoxCerditInfo(const QString &dbID,
const QDate &fromDate, const QDate &toDate)
{
QByteArray xmlData("<DataBoxCreditInfo xmlns=\"" ISDS_XML_NS "\"><dbID>");
xmlData.append(dbID.toUtf8());
xmlData.append("</dbID>");
if (!fromDate.isNull() && fromDate.isValid()) {
xmlData.append("<ciFromDate>");
xmlData.append(fromDate.toString().toUtf8());
xmlData.append("</ciFromDate>");
} else {
xmlData.append("<ciFromDate/>");
}
if (!toDate.isNull() && toDate.isValid()) {
xmlData.append("<ciToDate>");
xmlData.append(toDate.toString().toUtf8());
xmlData.append("</ciToDate>");
} else {
xmlData.append("<ciToDate/>");
}
xmlData.append("</DataBoxCreditInfo>");
return coatWithSoapEnvelope(xmlData);
}
......@@ -142,6 +142,19 @@ namespace Isds {
QList<PDZInfoRec> toPdzInfoRecs(const QByteArray &xmlData,
bool *ok = Q_NULLPTR);
/*!
* @brief Read data box credit info and return credit event list.
*
* @param[in] xmlData XML data.
* @param[out] currentCredit Current credit in CZK.
* @param[out] notifEmail Notification email address.
* @param[out] ok Set to false on failure.
* @return List of credit event info, null value on error.
*/
QList<CreditEvent> toDataBoxCreditInfo(const QByteArray &xmlData,
qint64 &currentCredit, QString &notifEmail,
bool *ok = Q_NULLPTR);
/*!
* @brief Constructs <GetPasswordInfo> request XML.
*
......@@ -220,5 +233,16 @@ namespace Isds {
*/
QByteArray soapRequestPdzSendInfo(const QString &dbID,
enum Type::PdzMessageType type);
/*!
* @brief Constructs <DataBoxCreditInfo> request XML.
*
* @param[in] dbID Data box ID.
* @param[in] fromDate From date.
* @param[in] toDate To date.
* @return Request XML data.
*/
QByteArray soapRequestDataBoxCerditInfo(const QString &dbID,
const QDate &fromDate, const QDate &toDate);
}
}
/*
* Copyright (C) 2014-2021 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include <QThread>
#include "src/datovka_shared/isds/error.h"
#include "src/datovka_shared/log/log.h"
#include "src/global.h"
#include "src/isds/services/box_interface.h"
#include "src/isds/session/isds_session.h"
#include "src/isds/session/isds_sessions.h"
#include "src/worker/emitter.h"
#include "src/worker/task_credit_info.h"
TaskCreditInfo::TaskCreditInfo(const AcntId &acntId, const QString &dbId,
const QDate &fromDate, const QDate &toDate)
: m_result(DL_ERR),
m_lastError(),
m_currentCredit(0),
m_notifEmail(),
m_creditEvents(),
m_acntId(acntId),
m_dbId(dbId),
m_fromDate(fromDate),
m_toDate(toDate)
{
Q_ASSERT(m_acntId.isValid());
Q_ASSERT(!m_dbId.isEmpty());
}
void TaskCreditInfo::run(void)
{
logDebugLv0NL("%s", "----------DOWNLOAD CREDIT INFO TASK------------");
logDebugLv0NL("Starting in thread '%p'", QThread::currentThreadId());
/* ### Worker task begin. ### */
m_result = creditInfo(m_acntId, m_dbId, m_fromDate, m_toDate,
m_currentCredit, m_notifEmail, m_creditEvents, m_lastError);
logDebugLv0NL("Finished in thread '%p'", QThread::currentThreadId());
logDebugLv0NL("%s", "-----------------------------------------------");
/* ### Worker task end. ### */
}
/*!
* @brief Translate communication error onto task error.
*/
static
enum TaskCreditInfo::Result error2result(enum Isds::Type::Error error)
{
switch (error) {
case Isds::Type::ERR_SUCCESS:
return TaskCreditInfo::DL_SUCCESS;
break;
case Isds::Type::ERR_ISDS:
return TaskCreditInfo::DL_ISDS_ERROR;
break;
case Isds::Type::ERR_SOAP:
case Isds::Type::ERR_XML:
return TaskCreditInfo::DL_XML_ERROR;
break;
default:
return TaskCreditInfo::DL_ERR;
break;
}
}
enum TaskCreditInfo::Result TaskCreditInfo::creditInfo(const AcntId &acntId,
const QString &dbId, const QDate &fromDate, const QDate &toDate,
qint64 &currentCredit, QString &notifEmail,
QList<Isds::CreditEvent> &creditEvents, QString &lastError)
{
if (Q_UNLIKELY((!acntId.isValid()) ||
(GlobInstcs::isdsSessionsPtr == Q_NULLPTR) ||
(!GlobInstcs::isdsSessionsPtr->holdsSession(acntId)))) {
Q_ASSERT(0);
return DL_ERR;
}
Isds::Session *session = GlobInstcs::isdsSessionsPtr->session(acntId);
if (Q_UNLIKELY(session == Q_NULLPTR)) {
Q_ASSERT(0);
return DL_ERR;
}
logDebugLv1NL("Sending from account '%s'",
acntId.username().toUtf8().constData());
enum Isds::Type::Error error = Isds::dataBoxCreditInfo(*session, dbId,
fromDate, toDate, currentCredit, notifEmail, creditEvents,
Q_NULLPTR, &lastError);
if (Q_UNLIKELY(error != Isds::Type::ERR_SUCCESS)) {
return error2result(error);
}
return DL_SUCCESS;
}
/*
* Copyright (C) 2014-2021 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by