Browse Source

refs #1 Syncronizing with release commit: 29d8a75477

qt5
parent
commit
b72dfb0e80
100 changed files with 1252 additions and 534 deletions
  1. +1
    -0
      3.0/src/apps/PaymentProcessor/src/Services/PrintConstants.h
  2. +73
    -38
      3.0/src/apps/PaymentProcessor/src/Services/PrintingCommands.cpp
  3. +7
    -1
      3.0/src/apps/PaymentProcessor/src/Services/PrintingCommands.h
  4. +198
    -143
      3.0/src/apps/PaymentProcessor/src/Services/PrintingService.cpp
  5. +13
    -3
      3.0/src/apps/PaymentProcessor/src/Services/PrintingService.h
  6. +19
    -2
      3.0/src/apps/Updater/src/UpdaterApp.cpp
  7. +2
    -0
      3.0/src/apps/Updater/src/UpdaterApp.h
  8. +24
    -0
      3.0/src/includes/Common/ExitAction.h
  9. +36
    -35
      3.0/src/includes/Hardware/CashDevices/CCTalkDeviceConstants.h
  10. +1
    -0
      3.0/src/includes/Hardware/Common/HardwareConstants.h
  11. +2
    -2
      3.0/src/includes/Hardware/FR/FRBaseConstants.h
  12. +1
    -1
      3.0/src/includes/Hardware/Printers/PrinterConstants.h
  13. +2
    -0
      3.0/src/includes/Hardware/Printers/PrinterStatusCodes.h
  14. +2
    -0
      3.0/src/includes/Hardware/Printers/PrinterStatusesDescriptions.h
  15. +13
    -0
      3.0/src/includes/SDK/Drivers/FR/FiscalDataTypes.h
  16. +7
    -0
      3.0/src/includes/SDK/Drivers/FR/FiscalFields.h
  17. +4
    -1
      3.0/src/includes/SDK/Drivers/HardwareConstants.h
  18. +0
    -12
      3.0/src/includes/SDK/Drivers/IFiscalPrinter.h
  19. +3
    -0
      3.0/src/includes/SDK/Drivers/IIOPort.h
  20. +22
    -0
      3.0/src/includes/SDK/Drivers/PrintingModes.h
  21. +5
    -1
      3.0/src/includes/SDK/PaymentProcessor/Core/IPrinterService.h
  22. +31
    -18
      3.0/src/includes/SDK/PaymentProcessor/FiscalRegister/IFiscalRegister.h
  23. +11
    -0
      3.0/src/includes/SDK/PaymentProcessor/Scripting/PrinterService.h
  24. +69
    -0
      3.0/src/includes/SDK/Plugins/PluginBase.h
  25. +1
    -0
      3.0/src/interface/modern/confirm_payment_scene.qml
  26. +8
    -6
      3.0/src/interface/modern/scenario/payment_scenario.js
  27. +4
    -10
      3.0/src/modules/DatabaseProxy/DatabaseProxy.qbs
  28. +19
    -17
      3.0/src/modules/Hardware/CashDispensers/src/DispenserBase.cpp
  29. +3
    -0
      3.0/src/modules/Hardware/CashDispensers/src/DispenserBase.h
  30. +39
    -12
      3.0/src/modules/Hardware/CashDispensers/src/Suzo/SuzoHopper.cpp
  31. +6
    -3
      3.0/src/modules/Hardware/CashDispensers/src/Suzo/SuzoHopper.h
  32. +18
    -2
      3.0/src/modules/Hardware/CashDispensers/src/Suzo/SuzoHopperData.h
  33. +1
    -0
      3.0/src/modules/Hardware/Common/msvc/Common.vcxproj
  34. +3
    -0
      3.0/src/modules/Hardware/Common/msvc/Common.vcxproj.filters
  35. +3
    -0
      3.0/src/modules/Hardware/Common/src/Base/DeviceBase.h
  36. +2
    -2
      3.0/src/modules/Hardware/Common/src/Polling/PollingDeviceBase.cpp
  37. +1
    -1
      3.0/src/modules/Hardware/Common/src/Polling/PollingDeviceBase.h
  38. +0
    -14
      3.0/src/modules/Hardware/Common/src/Utils/DeviceUtils.h
  39. +1
    -0
      3.0/src/modules/Hardware/FR/src/Atol/AtolModelData.cpp
  40. +1
    -0
      3.0/src/modules/Hardware/FR/src/Atol/AtolModelData.h
  41. +2
    -2
      3.0/src/modules/Hardware/FR/src/Atol/Ejector/AtolVKP80BasedFR.cpp
  42. +10
    -3
      3.0/src/modules/Hardware/FR/src/Base/FFEngine.cpp
  43. +3
    -0
      3.0/src/modules/Hardware/FR/src/Base/FFEngine.h
  44. +42
    -17
      3.0/src/modules/Hardware/FR/src/Base/FRBase.cpp
  45. +13
    -0
      3.0/src/modules/Hardware/FR/src/Base/FiscalFieldDescriptions.cpp
  46. +15
    -3
      3.0/src/modules/Hardware/FR/src/Base/FiscalFieldDescriptions.h
  47. +43
    -1
      3.0/src/modules/Hardware/FR/src/Base/Port/PortFRBase.cpp
  48. +9
    -0
      3.0/src/modules/Hardware/FR/src/Base/Port/PortFRBase.h
  49. +4
    -2
      3.0/src/modules/Hardware/FR/src/Kasbi/KasbiFRConstants.h
  50. +40
    -7
      3.0/src/modules/Hardware/FR/src/MStar/Online/AFPFR.cpp
  51. +3
    -0
      3.0/src/modules/Hardware/FR/src/MStar/Online/AFPFR.h
  52. +1
    -1
      3.0/src/modules/Hardware/FR/src/MStar/Online/AFPFRConstants.h
  53. +1
    -1
      3.0/src/modules/Hardware/FR/src/OPOSMStarTUPK/OPOSMStarTUPK.cpp
  54. +2
    -0
      3.0/src/modules/Hardware/FR/src/Shtrih/Base/ProtoShtrihFR.cpp
  55. +10
    -2
      3.0/src/modules/Hardware/FR/src/Shtrih/Online/MStarTK2.cpp
  56. +29
    -25
      3.0/src/modules/Hardware/FR/src/Shtrih/Online/ShtrihFROnlineConstants.h
  57. +13
    -1
      3.0/src/modules/Hardware/FR/src/Shtrih/Online/ShtrihOnlineFRBase.cpp
  58. +6
    -0
      3.0/src/modules/Hardware/Hardware.qbs
  59. +6
    -0
      3.0/src/modules/Hardware/IOPorts/src/COM/windows/AsyncSerialPort.cpp
  60. +3
    -0
      3.0/src/modules/Hardware/IOPorts/src/COM/windows/AsyncSerialPort.h
  61. +6
    -0
      3.0/src/modules/Hardware/IOPorts/src/LibUSB/LibUSBPort.cpp
  62. +3
    -0
      3.0/src/modules/Hardware/IOPorts/src/LibUSB/LibUSBPort.h
  63. +12
    -0
      3.0/src/modules/Hardware/IOPorts/src/TCP/TCPPort.cpp
  64. +6
    -0
      3.0/src/modules/Hardware/IOPorts/src/TCP/TCPPort.h
  65. +46
    -8
      3.0/src/modules/Hardware/Printers/src/Base/PrinterBase.cpp
  66. +11
    -2
      3.0/src/modules/Hardware/Printers/src/Base/PrinterBase.h
  67. +2
    -0
      3.0/src/modules/Hardware/Printers/src/POSPrinters/Custom/CustomTG2480H.h
  68. +2
    -0
      3.0/src/modules/Hardware/Printers/src/POSPrinters/Custom/CustomVKP/CustomVKP80.cpp
  69. +69
    -24
      3.0/src/modules/Hardware/Printers/src/SystemPrinter/SystemPrinter.cpp
  70. +4
    -1
      3.0/src/modules/Hardware/Printers/src/SystemPrinter/SystemPrinter.h
  71. +2
    -0
      3.0/src/modules/Hardware/Printers/src/Tags/Tags.h
  72. +5
    -6
      3.0/src/modules/NetworkTaskManager/NetworkTaskManager.qbs
  73. +1
    -0
      3.0/src/modules/SDK/Drivers/msvc/DriverSDK.vcxproj
  74. +3
    -0
      3.0/src/modules/SDK/Drivers/msvc/DriverSDK.vcxproj.filters
  75. +5
    -2
      3.0/src/modules/SDK/PaymentProcessor/PPSDK.qbs
  76. +16
    -3
      3.0/src/modules/SDK/PaymentProcessor/src/Scripting/PrinterService.cpp
  77. +1
    -0
      3.0/src/modules/SDK/Plugins/msvc/PluginSDK.vcxproj
  78. +3
    -0
      3.0/src/modules/SDK/Plugins/msvc/PluginSDK.vcxproj.filters
  79. +3
    -4
      3.0/src/modules/SysUtils/SysUtils.qbs
  80. +25
    -4
      3.0/src/plugins/Drivers/BillDispensers/src/BillDispenserPlugin.cpp
  81. +23
    -17
      3.0/src/plugins/Drivers/Printer/src/locale/printers_de.ts
  82. +23
    -17
      3.0/src/plugins/Drivers/Printer/src/locale/printers_en.ts
  83. +23
    -17
      3.0/src/plugins/Drivers/Printer/src/locale/printers_kk.ts
  84. +23
    -17
      3.0/src/plugins/Drivers/Printer/src/locale/printers_ru.ts
  85. +6
    -6
      3.0/src/plugins/NativeWidgets/ServiceMenu/src/Backend/PaymentManager.cpp
  86. +2
    -1
      3.0/src/plugins/NativeWidgets/ServiceMenu/src/Backend/PaymentManager.h
  87. +1
    -1
      3.0/src/plugins/NativeWidgets/ServiceMenu/src/Backend/ServiceMenuBackend.cpp
  88. +3
    -3
      3.0/src/plugins/NativeWidgets/ServiceMenu/src/GUI/PaymentServiceWindow.cpp
  89. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/1Cmodule_mts.xml
  90. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/aeroflot.xml
  91. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/bank_masked.xml
  92. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/bank_masked_error.xml
  93. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/bilet_online.xml
  94. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/credit_card_masked.xml
  95. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/credit_card_masked_error.xml
  96. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/credit_europe_bank_masked.xml
  97. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/credit_europe_bank_masked_error.xml
  98. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/fns.xml
  99. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/fns2.xml
  100. +1
    -1
      3.0/src/runtimes/ru/common/receipts/data/receipts/freepay.xml

+ 1
- 0
3.0/src/apps/PaymentProcessor/src/Services/PrintConstants.h View File

@@ -22,6 +22,7 @@ namespace CPrintConstants
const char * const DealerVAT = "DEALER_NDS";
const char * const DealerAgentFlag = "DEALER_AGENT_FLAG";
const char * const DealerTaxSystem = "DEALER_SNO";
const char * const FiscalData = "FISCAL_DATA";
const char * const MtRegistrationAddress = "MT_REGISTRATION_ADDRESS";
const char * const PointAddress = "POINT_ADDRESS";
const char * const PointName = "POINT_NAME";


+ 73
- 38
3.0/src/apps/PaymentProcessor/src/Services/PrintingCommands.cpp View File

@@ -30,6 +30,20 @@ void PrintCommand::setReceiptTemplate(const QString & aTemplateName)
}
//---------------------------------------------------------------------------
QVariantMap PrintCommand::getPrintingParameters(SDK::Driver::IPrinter * aPrinter)
{
QVariantMap configuration = aPrinter->getDeviceConfiguration();
QVariantMap result;
if (configuration.contains(CHardwareSDK::Printer::LineSize) && configuration[CHardwareSDK::Printer::LineSize].isValid())
{
result.insert(CHardwareSDK::Printer::LineSize, configuration[CHardwareSDK::Printer::LineSize]);
}
return result;
}
//---------------------------------------------------------------------------
PrintFiscalCommand::PrintFiscalCommand(const QString & aReceiptType, FiscalCommand::Enum aFiscalCommand, PrintingService * aService) :
PrintCommand(aReceiptType),
mFiscalCommand(aFiscalCommand),
@@ -182,37 +196,45 @@ bool PrintFiscalCommand::canFiscalPrint(DSDK::IPrinter * aPrinter, bool aRealChe
}
//---------------------------------------------------------------------------
bool PrintFiscalCommand::getFiscalInfo(QVariantMap & aParameters, QStringList & aReceiptLines)
bool PrintFiscalCommand::getFiscalInfo(QVariantMap & aParameters, QStringList & aReceiptLines, bool aWaitResult)
{
PPSDK::IFiscalRegister * fr = mService->getFiscalRegister();
if (fr && fr->haveCapability(PPSDK::IFiscalRegister::Receipt))
if (!fr || !fr->hasCapability(PPSDK::ERequestType::Receipt) || !fr->isReady(PPSDK::ERequestType::Receipt))
{
qint64 paymentId = aParameters.value(PPSDK::CPayment::Parameters::ID).toLongLong();
QStringList parameterNames = fr->getParameterNames();
return false;
}
// Если в параметрах платежа ещё нет информации о фискальном номере
bool OK = !parameterNames.toSet().intersect(aParameters.keys().toSet()).isEmpty();
if (!OK)
{
auto fiscalParameters = fr->createFiscalTicket(paymentId, aParameters, getPaymentData(aParameters));
OK = !fiscalParameters.isEmpty();
aParameters.unite(fiscalParameters);
qint64 paymentId = aParameters.value(PPSDK::CPayment::Parameters::ID).toLongLong();
QStringList parameterNames = fr->getParameterNames();
mService->setFiscalNumber(paymentId, fiscalParameters);
}
// Если в параметрах платежа ещё нет информации о фискальном номере
bool OK = !parameterNames.toSet().intersect(aParameters.keys().toSet()).isEmpty();
SDK::Driver::SPaymentData fiscalPaymentData;
if (OK)
if (!OK)
{
fiscalPaymentData = getPaymentData(aParameters);
auto fiscalParameters = fr->createFiscalTicket(paymentId, aParameters, fiscalPaymentData, aWaitResult);
if (!aWaitResult)
{
aReceiptLines = fr->getReceipt(paymentId, aParameters);
return true;
}
return OK;
OK = !fiscalParameters.isEmpty();
aParameters.unite(fiscalParameters);
mService->setFiscalNumber(paymentId, fiscalParameters);
}
return false;
if (OK)
{
aReceiptLines = fr->getReceipt(paymentId, aParameters, fiscalPaymentData);
}
return OK;
}
//---------------------------------------------------------------------------
@@ -229,6 +251,16 @@ bool PrintPayment::canPrint(DSDK::IPrinter * aPrinter, bool aRealCheck)
}
//---------------------------------------------------------------------------
bool PrintPayment::makeFiscalByFR(const QVariantMap & aParameters)
{
QStringList receipt = mService->getReceipt(mReceiptTemplate, aParameters);
QVariantMap parameters(aParameters);
QStringList fiscalPart;
return getFiscalInfo(parameters, fiscalPart, false);
}
//---------------------------------------------------------------------------
bool PrintPayment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParameters)
{
// Добавляем строки основного чека
@@ -243,15 +275,17 @@ bool PrintPayment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParamet
KKMSerialNumber = configuration[CHardwareSDK::SerialNumber].toString();
}
QVariantMap parameters = QVariantMap(aParameters).unite(getPrintingParameters(aPrinter));
QStringList fiscalPart;
bool hasFiscalInfo = getFiscalInfo(parameters, fiscalPart, true);
QVariantMap actualParameters = aParameters;
actualParameters.insert(CPrintConstants::KKM::SerialNumber, KKMSerialNumber);
actualParameters.insert("ONLINE_KKM", onlineKKM ? 1 : 0);
actualParameters.insert(CPrintConstants::FiscalData, int(hasFiscalInfo));
QStringList receipt = mService->getReceipt(mReceiptTemplate, actualParameters);
QVariantMap parameters = aParameters;
QStringList fiscalPart;
bool hasFiscalInfo = getFiscalInfo(parameters, fiscalPart);
if (hasFiscalInfo)
{
receipt.append(fiscalPart);
@@ -343,16 +377,17 @@ bool PrintPayment::isFiscal(DSDK::IPrinter * aPrinter)
bool PrintBalance::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParameters)
{
QStringList receipt = mService->getReceipt(mReceiptType, expandFields(aParameters));
auto fr = dynamic_cast<DSDK::IFiscalPrinter *>(aPrinter);
auto virtualFR = mService->getFiscalRegister();
QStringList fiscalReceipt;
if (mFiscalMode && virtualFR && virtualFR->haveCapability(PPSDK::IFiscalRegister::Balance))
if (mFiscalMode && virtualFR && virtualFR->hasCapability(PPSDK::ERequestType::XReport) && virtualFR->isReady(PPSDK::ERequestType::XReport) &&
virtualFR->serviceRequest(PPSDK::ERequestType::XReport, fiscalReceipt, getPrintingParameters(aPrinter)))
{
receipt.append(virtualFR->balance());
receipt << fiscalReceipt;
}
mService->saveReceiptContent(QString("%1_balance").arg(QTime::currentTime().toString("hhmmsszzz")), receipt);
auto fr = dynamic_cast<DSDK::IFiscalPrinter *>(aPrinter);
return mFiscalMode && fr && fr->isFiscalReady(false, mFiscalCommand) ? fr->printXReport(receipt) : aPrinter->print(receipt);
}
@@ -410,17 +445,17 @@ bool PrintEncashment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aPara
{
// Сохраняем чек перед печатью.
QStringList receipt = mService->getReceipt(mReceiptType, expandFields(aParameters));
auto virtualFR = mService->getFiscalRegister();
QStringList fiscalReceipt;
// Производим выплату фискального регистратора.
if (mFiscalMode && virtualFR && virtualFR->haveCapability(PPSDK::IFiscalRegister::Encashment))
if (mFiscalMode && virtualFR && virtualFR->hasCapability(PPSDK::ERequestType::Encashment) && virtualFR->isReady(PPSDK::ERequestType::Encashment) &&
virtualFR->serviceRequest(PPSDK::ERequestType::Encashment, fiscalReceipt, getPrintingParameters(aPrinter)))
{
receipt.append(virtualFR->encashment());
receipt << fiscalReceipt;
}
mService->saveReceiptContent(QString("%1_%2_encashment").arg(QTime::currentTime().toString("hhmmsszzz")).arg(aParameters["ENCASHMENT_NUMBER"].toString()), receipt);
auto fr = dynamic_cast<DSDK::IFiscalPrinter *>(aPrinter);
if (!canPrint(aPrinter, false))
@@ -438,7 +473,7 @@ bool PrintZReport::canPrint(DSDK::IPrinter * aPrinter, bool aRealCheck)
auto virtualFR = mService->getFiscalRegister();
return (virtualFR && virtualFR->haveCapability(PPSDK::IFiscalRegister::ZReport) && PrintCommand::canPrint(aPrinter, aRealCheck)) ||
return (virtualFR && virtualFR->hasCapability(PPSDK::ERequestType::ZReport) && virtualFR->isReady(PPSDK::ERequestType::ZReport) && PrintCommand::canPrint(aPrinter, aRealCheck)) ||
(fr && fr->isFiscalReady(aRealCheck, mFiscalCommand));
}
@@ -453,18 +488,18 @@ bool PrintZReport::print(DSDK::IPrinter * aPrinter, const QVariantMap & /*aParam
}
auto virtualFR = mService->getFiscalRegister();
QStringList fiscalReport;
if (virtualFR && virtualFR->haveCapability(PPSDK::IFiscalRegister::ZReport))
if (virtualFR && virtualFR->hasCapability(PPSDK::ERequestType::ZReport) && virtualFR->isReady(PPSDK::ERequestType::ZReport) &&
virtualFR->serviceRequest(PPSDK::ERequestType::ZReport, fiscalReport, getPrintingParameters(aPrinter)))
{
QStringList report = virtualFR->getZreport();
if (!report.isEmpty())
if (!fiscalReport.isEmpty())
{
result = aPrinter && aPrinter->print(report);
result = aPrinter && aPrinter->print(fiscalReport);
mService->saveReceiptContent(QString("%1_Z_report%2")
.arg(QTime::currentTime().toString("hhmmsszzz"))
.arg(result ? "" : CPrintCommands::NotPrintedPostfix), report);
.arg(result ? "" : CPrintCommands::NotPrintedPostfix), fiscalReport);
}
}


+ 7
- 1
3.0/src/apps/PaymentProcessor/src/Services/PrintingCommands.h View File

@@ -67,6 +67,9 @@ public:
/// Возвращает тип чека.
QString getReceiptType() const { return mReceiptType; }
/// Получить параметры принтера для печати.
QVariantMap getPrintingParameters(SDK::Driver::IPrinter * aPrinter);
protected:
QString mReceiptType;
QString mReceiptTemplate;
@@ -89,7 +92,7 @@ protected:
bool canFiscalPrint(SDK::Driver::IPrinter * aPrinter, bool aRealCheck);
/// Получить строки с фискальной информацией чека
bool getFiscalInfo(QVariantMap & aParameters, QStringList & aReceiptLines);
bool getFiscalInfo(QVariantMap & aParameters, QStringList & aReceiptLines, bool aWaitResult);
FiscalCommand::Enum mFiscalCommand;
@@ -114,6 +117,9 @@ public:
/// Печать.
virtual bool print(SDK::Driver::IPrinter * aPrinter, const QVariantMap & aParameters);
/// Сформировать фискальный чек через фискальный сервер.
bool makeFiscalByFR(const QVariantMap & aParameters);
private:
/// Добавить данные платежа.
void addFiscalPaymentData(const SDK::Driver::TFiscalPaymentData & aFPData, QStringList & aData);


+ 198
- 143
3.0/src/apps/PaymentProcessor/src/Services/PrintingService.cpp View File

@@ -38,6 +38,9 @@
#include <SDK/Drivers/Components.h>
#include <SDK/Drivers/HardwareConstants.h>
// Common
#include "Common/ExitAction.h"
// Project
#include "System/IApplication.h"
@@ -55,6 +58,10 @@
namespace PPSDK = SDK::PaymentProcessor;
//------------------------------------------------------------------------------
const char * PPSDK::IFiscalRegister::OFDNotSentSignal = SIGNAL(OFDNotSent(bool));
//------------------------------------------------------------------------------
namespace CPrintingService
{
const QString ReceiptDateTimeFormat = "dd.MM.yyyy hh:mm:ss";
@@ -69,7 +76,7 @@ PrintingService::PrintingService(IApplication * aApplication) :
mApplication(aApplication),
mDatabaseUtils(nullptr),
mDeviceService(nullptr),
mContinuousMode(false),
mPrintingMode(DSDK::EPrintingModes::None),
mServiceOperation(false),
mRandomReceiptsID(false),
mNextReceiptIndex(1),
@@ -167,8 +174,9 @@ bool PrintingService::shutdown()
if (mFiscalRegister)
{
SDK::Plugin::IPluginLoader * pluginLoader = PluginService::instance(mApplication)->getPluginLoader();
pluginLoader->destroyPlugin(dynamic_cast<SDK::Plugin::IPlugin *>(mFiscalRegister));
mFiscalRegister = nullptr;
}
return true;
@@ -219,9 +227,9 @@ bool PrintingService::canPrintReceipt(const QString & aReceiptType, bool aRealCh
}
//---------------------------------------------------------------------------
int PrintingService::printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aReceiptTemplate, bool aContinuousMode, bool aServiceOperation)
int PrintingService::printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aReceiptTemplate, DSDK::EPrintingModes::Enum aPrintingMode, bool aServiceOperation)
{
mContinuousMode = aContinuousMode;
mPrintingMode = aPrintingMode;
mServiceOperation = aServiceOperation;
QStringList receiptTemplates;
@@ -265,7 +273,7 @@ void PrintingService::printEmptyReceipt(int aJobIndex, bool aError)
//---------------------------------------------------------------------------
bool PrintingService::printReceiptDirected(DSDK::IPrinter * aPrinter, const QString & aReceiptTemplate, const QVariantMap & aParameters)
{
mContinuousMode = false;
mPrintingMode = DSDK::EPrintingModes::None;
// Извлекаем шаблон для чека нужного типа.
if (!mCachedReceipts.contains(aReceiptTemplate.toLower()))
@@ -278,7 +286,7 @@ bool PrintingService::printReceiptDirected(DSDK::IPrinter * aPrinter, const QStr
printCommand->setReceiptTemplate(aReceiptTemplate);
QVariantMap configuration;
configuration.insert(CHardwareSDK::Printer::ContinuousMode, mContinuousMode);
configuration.insert(CHardwareSDK::Printer::PrintingMode, mPrintingMode);
configuration.insert(CHardwareSDK::Printer::ServiceOperation, mServiceOperation);
aPrinter->setDeviceConfiguration(configuration);
@@ -305,25 +313,39 @@ int PrintingService::performPrint(PrintCommand * aCommand, const QVariantMap & a
mPrintingFunction =
[this, aReceiptTemplate](int aJobIndex, PrintCommand * aCommand, QVariantMap aParameters) -> bool
{
QVariantMap staticParameters;
joinMap(staticParameters, mStaticParameters);
QVariantMap paymentParameters = joinMap(aParameters, staticParameters);
auto printer = takePrinter(aCommand->getReceiptType(), false);
PrintPayment * paymentPrintingCommand = dynamic_cast<PrintPayment *>(aCommand);
auto makeResult = [&] (bool result, const QString & aLog) -> bool { if (aCommand) delete aCommand;
toLog(result ? LogLevel::Normal : LogLevel::Error, aLog); emit receiptPrinted(aJobIndex, !result); return result; };
if (!printer)
{
delete aCommand;
if (!getFiscalRegister())
{
return makeResult(false, "Failed to process receipt without printer due to no fiscal register");
}
else if (!paymentPrintingCommand)
{
return makeResult(false, "Failed to process receipt without printer due to no printing command");
}
return false;
}
bool result = paymentPrintingCommand->makeFiscalByFR(paymentParameters);
QVariantMap staticParameters;
joinMap(staticParameters, mStaticParameters);
return makeResult(result, "Send receipt printed without printer");
}
QVariantMap configuration;
configuration.insert(CHardwareSDK::Printer::ContinuousMode, mContinuousMode);
configuration.insert(CHardwareSDK::Printer::PrintingMode, mPrintingMode);
configuration.insert(CHardwareSDK::Printer::ServiceOperation, mServiceOperation);
configuration.insert(CHardwareSDK::Printer::ReceiptTemplate, aReceiptTemplate);
printer->setDeviceConfiguration(configuration);
bool result = aCommand->print(printer, joinMap(aParameters, staticParameters));
bool result = aCommand->print(printer, paymentParameters);
if (result)
{
@@ -332,11 +354,7 @@ int PrintingService::performPrint(PrintCommand * aCommand, const QVariantMap & a
giveBackPrinter(printer);
delete aCommand;
emit receiptPrinted(aJobIndex, !result);
return result;
return makeResult(result, "Send receipt printed");
};
int taskIndex = mNextReceiptIndex.fetchAndAddOrdered(1);
@@ -386,6 +404,12 @@ int PrintingService::printReport(const QString & aReceiptType, const QVariantMap
}
//---------------------------------------------------------------------------
bool PrintingService::hasFiscalRegister()
{
return mFiscalRegister && mFiscalRegister->hasCapability(PPSDK::ERequestType::Receipt);
}
//---------------------------------------------------------------------------
void PrintingService::giveBackPrinter(DSDK::IPrinter * aPrinter)
{
if (aPrinter)
@@ -1193,56 +1217,58 @@ void PrintingService::expandTags(QStringList & aReceipt, const QVariantMap & aPa
}
//---------------------------------------------------------------------------
void PrintingService::loadReceiptTemplates()
bool PrintingService::loadReceiptTemplate(const QFileInfo & aFileInfo)
{
auto loadReceiptTemplate = [&](const QFileInfo & aFileInfo)
if (aFileInfo.suffix().compare("xml", Qt::CaseInsensitive))
{
if (!aFileInfo.suffix().compare("xml", Qt::CaseInsensitive))
{
QDomDocument xmlFile(aFileInfo.fileName());
QFile file(aFileInfo.filePath());
if (!file.open(QIODevice::ReadOnly))
{
toLog(LogLevel::Error, QString("Failed to open file %1").arg(aFileInfo.filePath()));
return;
}
toLog(LogLevel::Error, QString("Bad receipt template file extension : %1").arg(aFileInfo.fileName()));
return false;
}
xmlFile.setContent(&file);
QDomDocument xmlFile(aFileInfo.fileName());
QFile file(aFileInfo.filePath());
QDomElement body = xmlFile.documentElement();
if (!file.open(QIODevice::ReadOnly))
{
toLog(LogLevel::Error, QString("Failed to open file %1").arg(aFileInfo.filePath()));
return false;
}
QStringList receiptContents;
xmlFile.setContent(&file);
for (QDomNode node = body.firstChild(); !node.isNull(); node = node.nextSibling())
{
QDomElement row = node.toElement();
if (row.tagName() == "string" || row.tagName() == "else")
{
QString prefix = row.attribute("if").isEmpty() ? "" : QString("%1%2").arg(row.attribute("if")).arg(CPrintingService::ConditionTag);
receiptContents.append(QString("%1%2").arg(prefix).arg(row.text()));
}
else if (row.tagName() == "hr")
{
receiptContents.append("[hr]-[/hr]");
}
}
QDomElement body = xmlFile.documentElement();
if (!receiptContents.isEmpty())
{
mCachedReceipts.insert(aFileInfo.baseName().toLower(), receiptContents);
}
else
{
toLog(LogLevel::Error, QString("Bad receipt template '%1': parse xml error").arg(aFileInfo.fileName()));
}
QStringList receiptContents;
for (QDomNode node = body.firstChild(); !node.isNull(); node = node.nextSibling())
{
QDomElement row = node.toElement();
if (row.tagName() == "string" || row.tagName() == "else")
{
QString prefix = row.attribute("if").isEmpty() ? "" : QString("%1%2").arg(row.attribute("if")).arg(CPrintingService::ConditionTag);
receiptContents.append(QString("%1%2").arg(prefix).arg(row.text()));
}
else
else if (row.tagName() == "hr")
{
toLog(LogLevel::Error, QString("Bad receipt template file extension : %1").arg(aFileInfo.fileName()));
receiptContents.append("[hr]-[/hr]");
}
};
}
if (receiptContents.isEmpty())
{
toLog(LogLevel::Error, QString("Bad receipt template '%1': parse xml error").arg(aFileInfo.fileName()));
return false;
}
mCachedReceipts.insert(aFileInfo.baseName().toLower(), receiptContents);
return true;
}
//---------------------------------------------------------------------------
void PrintingService::loadReceiptTemplates()
{
// Загружаем все шаблоны чеков в папке ./receipts
QDir receiptDirectory;
@@ -1361,6 +1387,26 @@ QString PrintingService::loadReceipt(qint64 aPaymentId)
}
//---------------------------------------------------------------------------
void PrintingService::onOFDNotSent(bool aExist)
{
auto service = SettingsService::instance(mApplication);
auto adapter = service ? service->getAdapter<PPSDK::TerminalSettings>() : nullptr;
bool block = adapter ? adapter->getCommonSettings().blockOn(PPSDK::SCommonSettings::PrinterError) : true;
QVariantMap configuration;
configuration.insert(CHardwareSDK::Printer::OFDNotSentError, aExist);
configuration.insert(CHardwareSDK::Printer::BlockTerminalOnError, block);
foreach (auto printer, mPrinterDevices)
{
if (printer)
{
printer->setDeviceConfiguration(configuration);
}
}
}
//---------------------------------------------------------------------------
void PrintingService::onStatusChanged(DSDK::EWarningLevel::Enum aWarningLevel, const QString & /*aTranslation*/, int /*aStatus*/)
{
emit printerStatus(aWarningLevel == DSDK::EWarningLevel::OK);
@@ -1385,36 +1431,38 @@ void PrintingService::onFRSessionClosed(const QVariantMap & aParameters)
QFile file(fileName);
// Сохраняем отчёт.
if (file.open(QIODevice::WriteOnly))
if (!file.open(QIODevice::WriteOnly))
{
using namespace SDK::Driver;
QXmlStreamWriter stream(&file);
stream.setAutoFormatting(true);
stream.writeStartDocument();
stream.writeStartElement(CFRReport::ZReport);
stream.writeAttribute(CFRReport::Number, aParameters[CFiscalPrinter::ZReportNumber].toString());
stream.writeStartElement(CFRReport::FR);
stream.writeAttribute(CFRReport::Serial, aParameters[CFiscalPrinter::Serial].toString());
stream.writeAttribute(CFRReport::RNM, aParameters[CFiscalPrinter::RNM].toString());
stream.writeEndElement(); // CFRReport::FR
stream.writeTextElement(CFRReport::PaymentCount, aParameters[CFiscalPrinter::PaymentCount].toString());
double amount = aParameters[CFiscalPrinter::PaymentAmount].toDouble();
stream.writeTextElement(CFRReport::PaymentAmount, QString::number(amount, 'f', 2));
amount = aParameters[CFiscalPrinter::NonNullableAmount].toDouble();
stream.writeTextElement(CFRReport::NonNullableAmount, QString::number(amount, 'f', 2));
stream.writeTextElement(CFRReport::FRDateTime, aParameters[CFiscalPrinter::FRDateTime].toString());
stream.writeTextElement(CFRReport::SystemDateTime, aParameters[CFiscalPrinter::SystemDateTime].toString());
stream.writeEndElement(); // CFRReport::ZReport
stream.writeEndDocument();
file.flush();
file.close();
return;
}
using namespace SDK::Driver;
QXmlStreamWriter stream(&file);
stream.setAutoFormatting(true);
stream.writeStartDocument();
stream.writeStartElement(CFRReport::ZReport);
stream.writeAttribute(CFRReport::Number, aParameters[CFiscalPrinter::ZReportNumber].toString());
stream.writeStartElement(CFRReport::FR);
stream.writeAttribute(CFRReport::Serial, aParameters[CFiscalPrinter::Serial].toString());
stream.writeAttribute(CFRReport::RNM, aParameters[CFiscalPrinter::RNM].toString());
stream.writeEndElement(); // CFRReport::FR
stream.writeTextElement(CFRReport::PaymentCount, aParameters[CFiscalPrinter::PaymentCount].toString());
double amount = aParameters[CFiscalPrinter::PaymentAmount].toDouble();
stream.writeTextElement(CFRReport::PaymentAmount, QString::number(amount, 'f', 2));
amount = aParameters[CFiscalPrinter::NonNullableAmount].toDouble();
stream.writeTextElement(CFRReport::NonNullableAmount, QString::number(amount, 'f', 2));
stream.writeTextElement(CFRReport::FRDateTime, aParameters[CFiscalPrinter::FRDateTime].toString());
stream.writeTextElement(CFRReport::SystemDateTime, aParameters[CFiscalPrinter::SystemDateTime].toString());
stream.writeEndElement(); // CFRReport::ZReport
stream.writeEndDocument();
file.flush();
file.close();
}
//---------------------------------------------------------------------------
@@ -1441,38 +1489,37 @@ void PrintingService::updateHardwareConfiguration()
{
DSDK::IPrinter * device = dynamic_cast<DSDK::IPrinter *>(mDeviceService->acquireDevice(printerName));
if (device)
if (!device)
{
QVariantMap dealerSettings;
if (mStaticParameters.contains(CPrintConstants::DealerTaxSystem)) dealerSettings.insert(CHardwareSDK::FR::DealerTaxSystem, mStaticParameters[CPrintConstants::DealerTaxSystem]);
if (mStaticParameters.contains(CPrintConstants::DealerAgentFlag)) dealerSettings.insert(CHardwareSDK::FR::DealerAgentFlag, mStaticParameters[CPrintConstants::DealerAgentFlag]);
if (mStaticParameters.contains(CPrintConstants::DealerVAT)) dealerSettings.insert(CHardwareSDK::FR::DealerVAT, mStaticParameters[CPrintConstants::DealerVAT]);
if (mStaticParameters.contains(CPrintConstants::DealerSupportPhone)) dealerSettings.insert(CHardwareSDK::FR::DealerSupportPhone, mStaticParameters[CPrintConstants::DealerSupportPhone]);
toLog(LogLevel::Error, QString("Failed to acquire device %1 .").arg(printerName));
continue;
}
mPrinterDevices.append(device);
QVariantMap dealerSettings;
if (mStaticParameters.contains(CPrintConstants::DealerTaxSystem)) dealerSettings.insert(CHardwareSDK::FR::DealerTaxSystem, mStaticParameters[CPrintConstants::DealerTaxSystem]);
if (mStaticParameters.contains(CPrintConstants::DealerAgentFlag)) dealerSettings.insert(CHardwareSDK::FR::DealerAgentFlag, mStaticParameters[CPrintConstants::DealerAgentFlag]);
if (mStaticParameters.contains(CPrintConstants::DealerVAT)) dealerSettings.insert(CHardwareSDK::FR::DealerVAT, mStaticParameters[CPrintConstants::DealerVAT]);
if (mStaticParameters.contains(CPrintConstants::DealerSupportPhone)) dealerSettings.insert(CHardwareSDK::FR::DealerSupportPhone, mStaticParameters[CPrintConstants::DealerSupportPhone]);
// Подписываемся на события принтера.
device->subscribe(SDK::Driver::IDevice::StatusSignal, this, SLOT(onStatusChanged(SDK::Driver::EWarningLevel::Enum, const QString &, int)));
mPrinterDevices.append(device);
// Подписываемся на события фискальника.
if (dynamic_cast<DSDK::IFiscalPrinter *>(device))
{
device->subscribe(SDK::Driver::IFiscalPrinter::FRSessionClosedSignal, this, SLOT(onFRSessionClosed(const QVariantMap &)));
// Подписываемся на события принтера.
device->subscribe(SDK::Driver::IDevice::StatusSignal, this, SLOT(onStatusChanged(SDK::Driver::EWarningLevel::Enum, const QString &, int)));
if (autoZReportTime.isValid() && !autoZReportTime.isNull())
{
toLog(LogLevel::Normal, QString("Setup auto z-report time: %1.").arg(autoZReportTime.toString("hh:mm:ss")));
// Подписываемся на события фискальника.
if (dynamic_cast<DSDK::IFiscalPrinter *>(device))
{
device->subscribe(SDK::Driver::IFiscalPrinter::FRSessionClosedSignal, this, SLOT(onFRSessionClosed(const QVariantMap &)));
dealerSettings.insert(CHardwareSDK::FR::ZReportTime, autoZReportTime);
}
}
if (autoZReportTime.isValid() && !autoZReportTime.isNull())
{
toLog(LogLevel::Normal, QString("Setup auto z-report time: %1.").arg(autoZReportTime.toString("hh:mm:ss")));
device->setDeviceConfiguration(dealerSettings);
}
else
{
toLog(LogLevel::Error, QString("Failed to acquire device %1 .").arg(printerName));
dealerSettings.insert(CHardwareSDK::FR::ZReportTime, autoZReportTime);
}
}
device->setDeviceConfiguration(dealerSettings);
}
mAvailablePrinters = mPrinterDevices.toSet();
@@ -1481,51 +1528,59 @@ void PrintingService::updateHardwareConfiguration()
//---------------------------------------------------------------------------
void PrintingService::createFiscalRegister()
{
if (!mFiscalRegister)
if (mFiscalRegister)
{
// Получаем информацию о фискальных регистраторах.
PPSDK::ExtensionsSettings * extSettings = SettingsService::instance(mApplication)->getAdapter<PPSDK::ExtensionsSettings>();
SDK::Plugin::IPluginLoader * pluginLoader = PluginService::instance(mApplication)->getPluginLoader();
return;
}
// Получаем информацию о фискальных регистраторах.
PPSDK::ExtensionsSettings * extSettings = SettingsService::instance(mApplication)->getAdapter<PPSDK::ExtensionsSettings>();
SDK::Plugin::IPluginLoader * pluginLoader = PluginService::instance(mApplication)->getPluginLoader();
QStringList frPlugins = pluginLoader->getPluginList(QRegExp(PPSDK::CComponents::FiscalRegister));
foreach(auto fr, pluginLoader->getPluginList(QRegExp(PPSDK::CComponents::FiscalRegister)))
foreach (auto fr, frPlugins)
{
auto plugin = pluginLoader->createPlugin(fr);
if (!plugin)
{
auto plugin = pluginLoader->createPlugin(fr);
if (!plugin)
{
continue;
}
continue;
}
PPSDK::IFiscalRegister * frPlugin = dynamic_cast<PPSDK::IFiscalRegister *>(plugin);
PPSDK::IFiscalRegister * frPlugin = dynamic_cast<PPSDK::IFiscalRegister *>(plugin);
if (!frPlugin)
{
toLog(LogLevel::Error, QString("FR %1 not have IFiscalRegister interface.").arg(fr));
pluginLoader->destroyPlugin(plugin);
continue;
}
if (!frPlugin)
{
toLog(LogLevel::Error, QString("FR %1 not have IFiscalRegister interface.").arg(fr));
pluginLoader->destroyPlugin(plugin);
continue;
}
auto parameters = extSettings->getSettings(plugin->getPluginName());
auto parameters = extSettings->getSettings(plugin->getPluginName());
if (parameters.isEmpty())
{
toLog(LogLevel::Warning, QString("FR %1 not have extensions settings. Skip it. (check config.xml).").arg(plugin->getPluginName()));
pluginLoader->destroyPlugin(plugin);
continue;
}
if (parameters.isEmpty())
{
toLog(LogLevel::Warning, QString("FR %1 not have extensions settings. Skip it. (check config.xml).").arg(plugin->getPluginName()));
pluginLoader->destroyPlugin(plugin);
continue;
}
connect(dynamic_cast<QObject *>(frPlugin), SDK::Driver::IFiscalPrinter::FRSessionClosedSignal, this, SLOT(onFRSessionClosed(const QVariantMap &)));
frPlugin->subscribe(PPSDK::IFiscalRegister::OFDNotSentSignal, this, SLOT(onOFDNotSent(bool)));
if (!frPlugin->initialize(parameters))
{
toLog(LogLevel::Warning, QString("FR %1 error initialize. Skip it.").arg(plugin->getPluginName()));
pluginLoader->destroyPlugin(plugin);
continue;
}
if (!frPlugin->initialize(parameters))
{
frPlugin->unsubscribe(PPSDK::IFiscalRegister::OFDNotSentSignal, this);
mFiscalRegister = frPlugin;
toLog(LogLevel::Normal, QString("FR %1 loaded successful.").arg(plugin->getPluginName()));
break;
toLog(LogLevel::Warning, QString("FR %1 error initialize. Skip it.").arg(plugin->getPluginName()));
pluginLoader->destroyPlugin(plugin);
continue;
}
mFiscalRegister = frPlugin;
toLog(LogLevel::Normal, QString("FR %1 loaded successful.").arg(plugin->getPluginName()));
break;
}
}


+ 13
- 3
3.0/src/apps/PaymentProcessor/src/Services/PrintingService.h View File

@@ -17,6 +17,7 @@
#include <QtCore/QSignalMapper>
#include <QtCore/QWaitCondition>
#include <QtCore/QAtomicInt>
#include <QtCore/QFileInfo>
#include <Common/QtHeadersEnd.h>
// SDK
@@ -93,7 +94,7 @@ public:
/// Печать типизированного чека с параметрами aParameters. Возвращает индекс задания, поставленного в очередь.
/// Результат придёт в сигнале receiptPrinted.
virtual int printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aReceiptTemplate, bool aContinuousMode, bool aServiceOperation = false);
virtual int printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aReceiptTemplate, DSDK::EPrintingModes::Enum aPrintingMode, bool aServiceOperation = false);
/// Сохранение электронной версии типизированного чека с параметрами aParameters.
virtual void saveReceipt(const QVariantMap & aParameters, const QString & aReceiptTemplate);
@@ -107,6 +108,9 @@ public:
/// Печать отчета.
virtual int printReport(const QString & aReceiptType, const QVariantMap & aParameters);
/// Может ли работать с фискальным сервером?
virtual bool hasFiscalRegister();
#pragma endregion
bool enableBlankFiscalData() const { return mEnableBlankFiscalData; }
@@ -147,9 +151,12 @@ private:
/// Первоначальная загрузка значений тегов.
bool loadTags();
/// Загрузка чеков.
/// Загрузка шаблонов чеков.
void loadReceiptTemplates();
/// Загрузка шаблона чека из файла.
bool loadReceiptTemplate(const QFileInfo & aFileInfo);
/// Печать чека, возвращает индекс задания, поставленного в очередь.
int performPrint(PrintCommand * aCommand, const QVariantMap & aParameters, QStringList aReceiptTemplate = QStringList());
@@ -195,6 +202,9 @@ private slots:
/// Обработчик печати с ошибкой
void printEmptyReceipt(int aJobIndex, bool aError);
/// Обработчик сигнала о наличии неотправленных чеков в фисклаьном регистраторе.
void onOFDNotSent(bool aExist);
private:
typedef QMap<QString, QString> TStaticParameters;
typedef QMap<QString, QStringList> TCachedReceipts;
@@ -227,7 +237,7 @@ private:
std::function<bool(int, PrintCommand *, QVariantMap)> mPrintingFunction;
/// Режим непрерывной печати чеков.
bool mContinuousMode;
DSDK::EPrintingModes::Enum mPrintingMode;
bool mServiceOperation;
bool mRandomReceiptsID;
mutable std::mt19937 mRandomGenerator;


+ 19
- 2
3.0/src/apps/Updater/src/UpdaterApp.cpp View File

@@ -437,9 +437,26 @@ CUpdaterApp::ExitCode::Enum UpdaterApp::bitsCheckStatus(bool aAlreadyRunning)
// Restart for download w/o bits
parameters << "--no-bits" << "true";

if (!QProcess::startDetached(qApp->applicationFilePath(), parameters))
QString commanLine = QDir::toNativeSeparators(qApp->applicationFilePath());
QString arguments = parameters.join(" ");
QString workDir = QDir::toNativeSeparators(mUpdater->getWorkingDir());

try
{
// Shedule restart myself
PhishMe::AddScheduledTask(L"TC_Updater",
commanLine.toStdWString(),
arguments.toStdWString(),
workDir.toStdWString(),
CUpdaterApp::BITSErrorRestartTimeout);

getLog()->write(LogLevel::Normal, QString("Do create updater restart scheduler task OK. Timeout: %1 min.").arg(CUpdaterApp::BITSErrorRestartTimeout / 60));
}
catch (std::exception & ex)
{
getLog()->write(LogLevel::Fatal, QString("Couldn't start updater from '%1'.").arg(qApp->applicationFilePath()));
// Something seriously went wrong inside ScheduleTask
getLog()->write(LogLevel::Fatal, QString("Didn't create updater restart scheduler task '%1'. Reason: %2.")
.arg(commanLine).arg(QString::fromLocal8Bit(ex.what())));
}

return CUpdaterApp::ExitCode::NetworkError;


+ 2
- 0
3.0/src/apps/Updater/src/UpdaterApp.h View File

@@ -29,6 +29,8 @@ namespace CUpdaterApp
/// Таймаут попыток повторнго запуска по финишу BITS
const long BITSCompleteTimeout = 15 * 60; // 15 минут

const long BITSErrorRestartTimeout = 3 * 60; // 3 минуты

typedef enum
{
Download, // закачиваем обновления


+ 24
- 0
3.0/src/includes/Common/ExitAction.h View File

@@ -0,0 +1,24 @@
/* @file Класс для выполнения функционала при выходе из области видимости. */
/* @brief Если отпадает необходимость в его вызове - вызвать reset(). */

#pragma once

// STL
#include <functional>

typedef std::function<void()> TVoidMethod;

//---------------------------------------------------------------------------
class ExitAction
{
public:
ExitAction(const TVoidMethod & aAction) : mAction(aAction) {}
~ExitAction() { if (mAction) mAction(); }

bool reset(const TVoidMethod & aAction = TVoidMethod()) { mAction = aAction; return true; }

private:
TVoidMethod mAction;
};

//---------------------------------------------------------------------------

+ 36
- 35
3.0/src/includes/Hardware/CashDevices/CCTalkDeviceConstants.h View File

@@ -42,43 +42,44 @@ namespace CCCTalk
namespace Command
{
/// Общие.
const uchar SimplePoll = 254;
const uchar VendorID = 246;
const uchar DeviceTypeID = 245;
const uchar ProductCode = 244;
const uchar BuildCode = 192;
const uchar SimplePoll = 254; // FE
const uchar VendorID = 246; // F6
const uchar DeviceTypeID = 245; // F5
const uchar ProductCode = 244; // F4
const uchar BuildCode = 192; // C0

/// Общие +.
const uchar Serial = 242;
const uchar SoftVersion = 241;
const uchar ProtocolID = 4;
const uchar Reset = 1;

const uchar Status = 248;
const uchar GetVariables = 247;
const uchar DBVersion = 243;
const uchar TestCoils = 240;
const uchar SelfCheck = 232;
const uchar PartialEnable = 231;
const uchar GetBufferedCoinStatuses = 229;
const uchar AllSetEnable = 228;
const uchar CreationDate = 196;
const uchar SoftLastDate = 195;
const uchar GetCoinID = 184;
const uchar SetSecurity = 181;
const uchar BaseYear = 170;
const uchar Dispense = 167;
const uchar GetHopperStatus = 166;
const uchar SetVariables = 165;
const uchar EnableHopper = 164;
const uchar TestHopper = 163;
const uchar ModifyInhibitsAndRegesters = 162;
const uchar GetBufferedBillStatuses = 159;
const uchar GetBillID = 157;
const uchar GetCountryScalingFactor = 156;
const uchar RouteBill = 154;
const uchar ModifyBillOperatingMode = 153;
const uchar GetCurrencyRevision = 145;
const uchar Serial = 242; // F2
const uchar SoftVersion = 241; // F1
const uchar ProtocolID = 4; // 04
const uchar Reset = 1; // 01

const uchar Status = 248; // F8
const uchar GetVariables = 247; // F7
const uchar DBVersion = 243; // F3
const uchar TestCoils = 240; // F0
const uchar SelfCheck = 232; // E8
const uchar PartialEnable = 231; // E7
const uchar GetBufferedCoinStatuses = 229; // E5
const uchar AllSetEnable = 228; // E4
const uchar CreationDate = 196; // C4
const uchar SoftLastDate = 195; // C3
const uchar SetPayoutCapacity = 187; // BB
const uchar GetCoinID = 184; // B8
const uchar SetSecurity = 181; // B7
const uchar BaseYear = 170; // AA
const uchar Dispense = 167; // A7
const uchar GetHopperStatus = 166; // A6
const uchar SetVariables = 165; // A5
const uchar EnableHopper = 164; // A4
const uchar TestHopper = 163; // A3
const uchar ModifyInhibitsAndRegesters = 162; // A2
const uchar GetBufferedBillStatuses = 159; // 9F
const uchar GetBillID = 157; // 9D
const uchar GetCountryScalingFactor = 156; // 9C
const uchar RouteBill = 154; // 9A
const uchar ModifyBillOperatingMode = 153; // 99
const uchar GetCurrencyRevision = 145; // 91

namespace EAnswerType
{


+ 1
- 0
3.0/src/includes/Hardware/Common/HardwareConstants.h View File

@@ -194,6 +194,7 @@ namespace CHardware
const char BackFeed[] = "back_feed";
const char PrintPageNumber[] = "print_page_number";
const char LeftMargin[] = "left_margin";
const char RightMargin[] = "right_margin";
}
/// Параметры обработки чека после отрезки.


+ 2
- 2
3.0/src/includes/Hardware/FR/FRBaseConstants.h View File

@@ -62,8 +62,8 @@ namespace CFR
/// Формальная дата окончания ФН.
inline QString FSValidityDateOff(const QDate & aDate) { return aDate.addDays(-3).toString(CFR::DateLogFormat); }
/// Срок годности обычной (на 13 месяцев) ФН в днях - так фактически, у всех производителей.
const int SimpleFSValidityDays = 410;
/// Срок годности ФН на 15 месяцев (Автоматика/Прагматик) в днях.
const int FS15ValidityDays = 470;
/// Результаты запроса статуса.
namespace Result


+ 1
- 1
3.0/src/includes/Hardware/Printers/PrinterConstants.h View File

@@ -29,7 +29,7 @@ namespace CPrinters
const int DefaultHRSize = 35;
/// Белый цвет.
const QRgb White = QColor(Qt::white).rgb();
const QRgb White = QColor(Qt::transparent).rgb();
/// Действие с незабранным чеком.
namespace ELeftReceiptAction


+ 2
- 0
3.0/src/includes/Hardware/Printers/PrinterStatusCodes.h View File

@@ -22,6 +22,7 @@ namespace PrinterStatusCode
const int TonerNearEnd = 212; /// Тонер заканчивается.
const int PaperEndVirtual = 213; /// Бумага закончилась по показания датчика скорого окончания бумаги.
const int WrongFWConfiguration = 214; /// Неверная конфигурация прошивки.
const int OFDNotSent = 215; /// Нет связи с ОФД сервером (виртуальный статус фискального сервера).
}

/// Ошибки.
@@ -44,6 +45,7 @@ namespace PrinterStatusCode
const int OutletFull = 234; /// Выходной лоток полон.
const int NeedPaperTakeOut = 235; /// Необходимо извлечь бумагу из презентера.
const int MemoryEnd = 236; /// Не хватает памяти.
const int OFDNotSent = 237; /// Нет связи с ОФД сервером (виртуальный статус фискального сервера).
}
}



+ 2
- 0
3.0/src/includes/Hardware/Printers/PrinterStatusesDescriptions.h View File

@@ -27,6 +27,7 @@ namespace PrinterStatusCode
ADD_PRINTER_WARNING(TonerNearEnd, QCoreApplication::translate("PrinterStatuses", "#toner_near_end"));
ADD_PRINTER_WARNING(PaperEndVirtual, QCoreApplication::translate("PrinterStatuses", "#no_paper_virtual"));
ADD_PRINTER_WARNING(WrongFWConfiguration, QCoreApplication::translate("PrinterStatuses", "#wrong_firmware_configuration"));
ADD_PRINTER_WARNING(OFDNotSent, QCoreApplication::translate("PrinterStatuses", "#ofd_not_sent"));

/// Ошибки.
ADD_PRINTER_ERROR(PaperEnd, QCoreApplication::translate("PrinterStatuses", "#no_paper"));
@@ -46,6 +47,7 @@ namespace PrinterStatusCode
ADD_PRINTER_ERROR(OutletFull, QCoreApplication::translate("PrinterStatuses", "#outlet_full"));
ADD_PRINTER_ERROR(NeedPaperTakeOut, QCoreApplication::translate("PrinterStatuses", "#need_paper_take_out"));
ADD_PRINTER_ERROR(MemoryEnd, QCoreApplication::translate("PrinterStatuses", "#memory_end"));
ADD_PRINTER_ERROR(OFDNotSent, QCoreApplication::translate("PrinterStatuses", "#ofd_not_sent"));
}

TStatusCodes getAvailableErrors()


+ 13
- 0
3.0/src/includes/SDK/Drivers/FR/FiscalDataTypes.h View File

@@ -14,6 +14,19 @@ namespace SDK {
namespace Driver {
//--------------------------------------------------------------------------------
/// Состояние сессии.
namespace ESessionState
{
enum Enum
{
Error, /// Ошибка определения.
Opened, /// Открыта.
Closed, /// Закрыта.
Expired /// Истекла.
};
}
//--------------------------------------------------------------------------------
// Структура описателя фискальных тегов.
struct SFiscalFieldData
{


+ 7
- 0
3.0/src/includes/SDK/Drivers/FR/FiscalFields.h View File

@@ -101,6 +101,13 @@ namespace SDK { namespace Driver { namespace CAllHardware { namespace FiscalFiel
const char TaxAmount06[] = "tax_amount_06"; // 1106 (Сумма НДС чека по расчетной ставке 18/118 (20/120)).
const char TaxAmount07[] = "tax_amount_07"; // 1107 (Сумма НДС чека по расчетной ставке 10/110).
// Значения.
namespace Values
{
/// ФФД маркер отсутствия данных.
const char NoData[] = "none";
}
}}}}
namespace CFiscalSDK = SDK::Driver::CAllHardware::FiscalFields;


+ 4
- 1
3.0/src/includes/SDK/Drivers/HardwareConstants.h View File

@@ -81,9 +81,12 @@ namespace CAllHardware
/// Константы принтера.
namespace Printer
{
const char LineSize[] = "line_size";
const char ReceiptTemplate[] = "receipt_template";
const char ContinuousMode[] = "continuous_mode";
const char PrintingMode[] = "printing_mode";
const char ServiceOperation[] = "service_operation";
const char BlockTerminalOnError[] = "block_terminal_on_error";
const char OFDNotSentError[] = "ofd_not_sent_error";
}
/// Константы HID-устройств.


+ 0
- 12
3.0/src/includes/SDK/Drivers/IFiscalPrinter.h View File

@@ -15,18 +15,6 @@
namespace SDK {
namespace Driver {

/// Состояние сессии.
namespace ESessionState
{
enum Enum
{
Error, /// Ошибка определения.
Opened, /// Открыта.
Closed, /// Закрыта.
Expired /// Истекла.
};
}

/// Состояние документа.
namespace EDocumentState
{


+ 3
- 0
3.0/src/includes/SDK/Drivers/IIOPort.h View File

@@ -82,6 +82,9 @@ public: // методы
/// Подключено новое устройство?
virtual bool deviceConnected() = 0;

/// Открыт?
virtual bool opened() = 0;

protected:
virtual ~IIOPort() {}
};


+ 22
- 0
3.0/src/includes/SDK/Drivers/PrintingModes.h View File

@@ -0,0 +1,22 @@
/* @file Режимы печати. */

#pragma once

namespace SDK {
namespace Driver {

namespace EPrintingModes
{
enum Enum
{
None = 0,
Continuous,
Glue
};
};

}} // namespace SDK::Driver

namespace DSDK = SDK::Driver;

//---------------------------------------------------------------------------

+ 5
- 1
3.0/src/includes/SDK/PaymentProcessor/Core/IPrinterService.h View File

@@ -13,6 +13,7 @@

// SDK
#include <SDK/Drivers/WarningLevel.h>
#include <SDK/Drivers/PrintingModes.h>

namespace SDK {
namespace Driver { class IPrinter; }
@@ -32,7 +33,7 @@ public:

/// Печать типизированного чека с параметрами aParameters. Возвращает индекс задания, поставленного в очередь.
/// Результат придёт в сигнале receiptPrinted.
virtual int printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aReceiptTemplate, bool aContinuousMode, bool aServiceOperation = false) = 0;
virtual int printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aReceiptTemplate, DSDK::EPrintingModes::Enum aPrintingMode, bool aServiceOperation = false) = 0;

/// Сохранение электронной версии типизированного чека с параметрами aParameters.
virtual void saveReceipt(const QVariantMap & aParameters, const QString & aReceiptTemplate) = 0;
@@ -46,6 +47,9 @@ public:
/// Печать отчета.
virtual int printReport(const QString & aReceiptType, const QVariantMap & aParameters) = 0;

/// Может ли работать с фискальным сервером?
virtual bool hasFiscalRegister() = 0;

signals:
/// Срабатывает после печати произвольного чека. Успешность операции передаётся в поле aError.
void receiptPrinted(int aJobIndex, bool aErrorHappened);


+ 31
- 18
3.0/src/includes/SDK/PaymentProcessor/FiscalRegister/IFiscalRegister.h View File

@@ -5,7 +5,7 @@
// Qt
#include <Common/QtHeadersBegin.h>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <Common/QtHeadersEnd.h>

// SDK
@@ -15,21 +15,34 @@
namespace SDK {
namespace PaymentProcessor {

//------------------------------------------------------------------------------
class IFiscalRegister
namespace ERequestType
{
public:
enum
enum Enum
{
Receipt = 1,
Balance = 2,
XReport = 2,
Encashment = 4,
ZReport = 8
ZReport = 8,
SessionData
};
}

//------------------------------------------------------------------------------
class IFiscalRegister
{
public:
/// Соединение открыто.
static const char * OFDNotSentSignal; // SIGNAL(OFDNotSent(bool));

public:
virtual ~IFiscalRegister() {}

/// Соединяет сигнал данного класса со слотом приёмника.
virtual bool subscribe(const char * aSignal, QObject * aReceiver, const char * aSlot) = 0;

/// Отсоединяет сигнал данного класса от слота приёмника.
virtual bool unsubscribe(const char * aSignal, QObject * aReceiver) = 0;

/// Инициализация регистратора
virtual bool initialize(const QMap<QString, QString> & aParameters) = 0;

@@ -37,24 +50,24 @@ public:
virtual QStringList getParameterNames() = 0;

/// Получить список возможностей ФР
virtual bool haveCapability(quint32 aCapabilityFlags) = 0;
virtual bool hasCapability(quint32 aCapabilityFlags) = 0;

/// Проверить готовность к выполнению операции.
virtual bool isReady(ERequestType::Enum aType) = 0;

/// Зарегистрировать платёж и вернуть набор параметров
virtual QVariantMap createFiscalTicket(qint64 aPaymentId, const QVariantMap & aPaymentParameters, const SDK::Driver::SPaymentData & aPaymentData) = 0;
virtual QVariantMap createFiscalTicket(qint64 aPaymentId, const QVariantMap & aPaymentParameters, const SDK::Driver::SPaymentData & aPaymentData, bool aWaitResult) = 0;

/// Получить строки для чека с фискальной информацией, список параметров может модифицироваться!
virtual QStringList getReceipt(qint64 paymentId, const QVariantMap & aPaymentParameters) = 0;

/// Получить отчёт по балансу ФР
virtual QStringList balance() = 0;
virtual QStringList getReceipt(qint64 paymentId, const QVariantMap & aPaymentParameters, const SDK::Driver::SPaymentData & aPaymentData) = 0;

/// Инкассировать и получить текст для печати на чеке
virtual QStringList encashment() = 0;

/// Получить Z отчёт
virtual QStringList getZreport() = 0;
/// Выполнить сервисную операцию (инкассация, Z-отчет, X-отчет).
virtual bool serviceRequest(ERequestType::Enum aType, QStringList & aReceipt, const QVariantMap & aParameters) = 0;
};

//------------------------------------------------------------------------------
}} // SDK::PaymentProcessor

namespace PPSDK = SDK::PaymentProcessor;

//------------------------------------------------------------------------------

+ 11
- 0
3.0/src/includes/SDK/PaymentProcessor/Scripting/PrinterService.h View File

@@ -9,6 +9,9 @@
#include <QtCore/QFutureSynchronizer>
#include <Common/QtHeadersEnd.h>

// SDK
#include <SDK/Drivers/PrintingModes.h>

namespace SDK {
namespace PaymentProcessor {

@@ -30,6 +33,9 @@ public slots:
/// Проверка принтера на возможность печати чека. Если aRealCheck - true, то результат придёт в сигнале printerChecked.
bool checkPrinter(bool aRealCheck);

/// Проверка возможности использования фискального регистратора
bool checkFiscalRegister();

/// Печать типизированного чека с параметрами aParameters.
void printReceipt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aTemplate, bool aContinuousMode = false);

@@ -55,6 +61,11 @@ signals:
/// Срабатывает после проверки принтеров.
void printerChecked(bool aReady);

public:
/// Печать типизированного чека с параметрами aParameters.
/// Перегрузка со слотами не работает. Поэтому, так.
void printReceiptExt(const QString & aReceiptType, const QVariantMap & aParameters, const QString & aTemplate, DSDK::EPrintingModes::Enum aPrintingMode = DSDK::EPrintingModes::None);

protected:
void privateCheckPrinter();



+ 69
- 0
3.0/src/includes/SDK/Plugins/PluginBase.h View File

@@ -0,0 +1,69 @@
/* @file Базовый плагин. */

// Qt
#include <Common/QtHeadersBegin.h>
#include <QtCore/QString>
#include <QtCore/QVariantMap>
#include <Common/QtHeadersEnd.h>

// SDK
#include <SDK/Plugins/IPlugin.h>
#include <SDK/Plugins/IPluginEnvironment.h>
#include <SDK/Plugins/IExternalInterface.h>
#include <SDK/Plugins/PluginInitializer.h>

//------------------------------------------------------------------------------
template <class T>
class PluginBase : public SDK::Plugin::IPlugin, public T
{
public:
PluginBase(const QString & aName, SDK::Plugin::IEnvironment * aEnvironment, const QString & aInstancePath) :
mInstanceName(aInstancePath),
mEnvironment(aEnvironment),
mPluginName(aName)
{
setLog(aEnvironment->getLog(aName));
}

virtual ~PluginBase() {}

/// Возвращает название плагина.
virtual QString getPluginName() const
{
return mPluginName;
}

/// Возвращает параметры плагина.
virtual QVariantMap getConfiguration() const
{
return QVariantMap();
}

/// Настраивает плагин.
virtual void setConfiguration(const QVariantMap & /*aParameters*/) {}

/// Сохраняет конфигурацию плагина в постоянное хранилище (.ini файл или хранилище прикладной программы).
virtual bool saveConfiguration()
{
return true;
}

/// Возвращает имя файла конфигурации без расширения (ключ + идентификатор).
virtual QString getConfigurationName() const
{
return mInstanceName;
}

/// Проверяет успешно ли инициализировался плагин при создании.
virtual bool isReady() const
{
return true;
}

private:
QString mPluginName;
QString mInstanceName;
SDK::Plugin::IEnvironment * mEnvironment;
};

//--------------------------------------------------------------------------------

+ 1
- 0
3.0/src/interface/modern/confirm_payment_scene.qml View File

@@ -55,6 +55,7 @@ Widgets.SceneBase2 {
for (var i in global.provider.fields) {
if (!global.handlerParameters.fields.hasOwnProperty(global.provider.fields[i].id)) continue;
if (!global.provider.fields[i].title || !global.handlerParameters.fields[global.provider.fields[i].id].value) continue;
if (global.provider.fields[i]["behavior"] === "hidden") continue;
table += "<tr><td width='40%'>";
table += String(global.provider.fields[i].title).toUpperCase();


+ 8
- 6
3.0/src/interface/modern/scenario/payment_scenario.js View File

@@ -343,19 +343,20 @@ function checkEnterHandler(aParameters) {
for (var i in aProvider.fields) {
if (aProvider.fields[i].isRequired) {
if (aProvider.fields[i].dependency && Core.userProperties.get("operator_dependency_fields").hasOwnProperty(aProvider.fields[i].id)
&& !Core.userProperties.get("operator_dependency_fields")[aProvider.fields[i].id]) { continue; }
&& !Core.userProperties.get("operator_dependency_fields")[aProvider.fields[i].id]) { GUI.log("SKIP field %1 by dependency".arg(aProvider.fields[i].id)); continue; }
if(aProvider.fields[i].type == "html") { continue; }
if(aProvider.fields[i].type == "html") { GUI.log("SKIP field %1 by HTML type".arg(aProvider.fields[i].id)); continue; }
if (!aFields.hasOwnProperty(aProvider.fields[i].id)) { return false; }
if (!aFields.hasOwnProperty(aProvider.fields[i].id)) { GUI.log("SKIP field %1 by field not found".arg(aProvider.fields[i].id)); return false; }
if(!aFields[aProvider.fields[i].id].rawValue) { return false; }
if(!aFields[aProvider.fields[i].id].rawValue) { GUI.log("SKIP field %1 by empty value".arg(aProvider.fields[i].id)); return false; }
if (aProvider.fields[i].type == "number" || aProvider.fields[i].type == "number:float") {
if (Number(aFields[aProvider.fields[i].id].rawValue).toString() == "NaN") { return false; }
if (Number(aFields[aProvider.fields[i].id].rawValue).toString() == "NaN") { GUI.log("SKIP field %1 by NaN number to string".arg(aProvider.fields[i].id)); return false; }
}
}
}
return true;
}
@@ -706,7 +707,8 @@ function finishEnterHandler(aParameters) {
}
}
else {
printReceipt(Scenario.Payment.ReceiptType.Payment, RECEIPT_STATE, false, true);
// Если есть фисальный регистратор, то печатаем, иначе - только сохраняем копию чека
printReceipt(Scenario.Payment.ReceiptType.Payment, RECEIPT_STATE, false, !Core.printer.checkFiscalRegister());
GUI.notify(Scenario.Payment.Event.ReceiptPrinted, {receipt_printed: false});
}
}


+ 4
- 10
3.0/src/modules/DatabaseProxy/DatabaseProxy.qbs View File

@@ -1,15 +1,9 @@
import qbs 1.0

StaticLibrary {
name: "DatabaseProxy"
import "../../qbs/libTemplate.qbs" as TCLib

Depends { name: 'cpp' }
Depends { name: "Qt"; submodules: ["core", "sql"] }
Depends { name: "Core" }
TCLib {
name: "DatabaseProxy"

files: [
"src/*.h",
"src/*.cpp"
]
Depends { name: "Qt"; submodules: ["sql"] }
}


+ 19
- 17
3.0/src/modules/Hardware/CashDispensers/src/DispenserBase.cpp View File

@@ -17,7 +17,7 @@ using namespace SDK::Driver;

//---------------------------------------------------------------------------
template <class T>
DispenserBase<T>::DispenserBase() : mUnits(0), mNeedGetUnits(false), mUnitError(false)
DispenserBase<T>::DispenserBase() : mUnits(0), mNeedGetUnits(false), mUnitError(false), mResetIsPossible(true)
{
// описатель статус-кодов
mStatusCodesSpecification = DeviceStatusCode::PSpecifications(new DispenserStatusCode::CSpecifications());
@@ -46,7 +46,7 @@ bool DispenserBase<T>::updateParameters()
return false;
}

if (!reset())
if (mResetIsPossible && !reset())
{
toLog(LogLevel::Error, mDeviceName + ": Failed to reset.");
return false;
@@ -89,26 +89,28 @@ void DispenserBase<T>::adjustUnitList(bool aConfigData)
{
mUnitError = !mUnits;

if (!mUnitError)
if (mUnitError)
{
TUnitData & unitData = aConfigData ? mUnitConfigData : mUnitData;
mUnitData = unitData.mid(0, mUnits);
int newUnits = mUnitData.size();
return;
}

if (newUnits < mUnits)
{
mUnitData << TUnitData(mUnits - newUnits, 0);
}
TUnitData & unitData = aConfigData ? mUnitConfigData : mUnitData;
mUnitData = unitData.mid(0, mUnits);
int newUnits = mUnitData.size();

onPoll();
if (newUnits < mUnits)
{
mUnitData << TUnitData(mUnits - newUnits, 0);
}

for (int i = 0; i < unitData.size(); ++i)
onPoll();

for (int i = 0; i < unitData.size(); ++i)
{
if ((mStatusCollection.contains(CDispenser::StatusCodes::Data[i].empty) ||
mStatusCollection.contains(DispenserStatusCode::Error::AllUnitsEmpty)) && unitData[i])
{
if ((mStatusCollection.contains(CDispenser::StatusCodes::Data[i].empty) ||
mStatusCollection.contains(DispenserStatusCode::Error::AllUnitsEmpty)) && unitData[i])
{
emitUnitEmpty(i, " during status filtration");
}
emitUnitEmpty(i, " during status filtration");
}
}
}


+ 3
- 0
3.0/src/modules/Hardware/CashDispensers/src/DispenserBase.h View File

@@ -89,6 +89,9 @@ protected:

/// Последние девайс-коды для логгирования смены статуса.
QByteArray mLastDeviceStatusCodes;

/// Резет возможен.
bool mResetIsPossible;
};

//--------------------------------------------------------------------------------

+ 39
- 12
3.0/src/modules/Hardware/CashDispensers/src/Suzo/SuzoHopper.cpp View File

@@ -28,6 +28,7 @@ SuzoHopper::SuzoHopper()
mAllModelData = PAllModelData(new CCCTalk::Dispenser::CModelData());
mUnits = 1;
mSingleMode = false;
mResetIsPossible = false;

setConfigParameter(CHardware::ProtocolType, CHardware::CashDevice::CCTalkTypes::CRC8);
}
@@ -39,12 +40,37 @@ QStringList SuzoHopper::getProtocolTypes()
}

//--------------------------------------------------------------------------------
bool SuzoHopper::reset()
bool SuzoHopper::updateParameters()
{
// нет ни ответа, ни каких-либо действий диспенсера
//processCommand(CCCTalk::Command::Reset);
if (!CCTalkDeviceBase<PortDispenser>::updateParameters())
{
return false;
}

// ответа нет. Неизвестно, работает команда или нет.
processCommand(CCCTalk::Command::SetPayoutCapacity, CSuzo::MaxPayoutCapacity);

return true;
}

//---------------------------------------------------------------------------
TResult SuzoHopper::execCommand(const QByteArray & aCommand, const QByteArray & aCommandData, QByteArray * aAnswer)
{
TResult result;
int index = 0;

do
{
if (index)
{
SleepHelper::msleep(CSuzo::Pause::CommandIteration);
}

return true;
result = CCTalkDeviceBase<PortDispenser>::execCommand(aCommand, aCommandData, aAnswer);
}
while(!result && (++index < CSuzo::CommandMaxIteration) && (aCommand != QByteArray(1, CCCTalk::Command::SetPayoutCapacity)));

return result;
}

//---------------------------------------------------------------------------
@@ -112,8 +138,14 @@ bool SuzoHopper::getStatus(TStatusCodes & aStatusCodes)
bool SuzoHopper::setEnable(bool aEnabled)
{
char enabled = aEnabled ? CSuzo::Enable : ASCII::NUL;
bool result = processCommand(CCCTalk::Command::EnableHopper, QByteArray(1, enabled));

return processCommand(CCCTalk::Command::EnableHopper, QByteArray(1, enabled));
if (!aEnabled)
{
SleepHelper::msleep(CSuzo::Pause::Disabling);
}

return result;
}

//---------------------------------------------------------------------------
@@ -141,7 +173,7 @@ void SuzoHopper::performDispense(int aUnit, int aItems)
return;
}

if (!setEnable(true) || !setSingleMode(false))
if (!setSingleMode(true) || !setEnable(true))
{
return;
}
@@ -175,7 +207,7 @@ void SuzoHopper::performDispense(int aUnit, int aItems)

while (getDispensingStatus(status) && status.remains)
{
SleepHelper::msleep(CSuzo::DispensingPause);
SleepHelper::msleep(CSuzo::Pause::Dispensing);
}

emitDispensed(0, status.paid);
@@ -185,11 +217,6 @@ void SuzoHopper::performDispense(int aUnit, int aItems)
toLog(LogLevel::Error, mDeviceName + QString(": Cannot pay out %1 coins").arg(status.unpaid));

onPoll();

if (mStatusCollection[EWarningLevel::Error].isEmpty())
{
emitUnitEmpty(0);
}
}

setEnable(false);


+ 6
- 3
3.0/src/modules/Hardware/CashDispensers/src/Suzo/SuzoHopper.h View File

@@ -39,12 +39,15 @@ public:
static QStringList getModelList();

protected:
/// Инициализация устройства.
virtual bool updateParameters();

/// Выполнить команду.
virtual TResult execCommand(const QByteArray & aCommand, const QByteArray & aCommandData, QByteArray * aAnswer = nullptr);

/// Получить статус.
virtual bool getStatus(TStatusCodes & aStatusCodes);

/// Сброс.
virtual bool reset();

/// Установить режим выдачи: 1 / набор.
bool setSingleMode(bool aEnable);



+ 18
- 2
3.0/src/modules/Hardware/CashDispensers/src/Suzo/SuzoHopperData.h View File

@@ -14,8 +14,24 @@ namespace CSuzo
/// Включить на выдачу.
const char Enable = '\xA5';

/// Пауза между запросами статуса на выдачи денег.
const int DispensingPause = 300;
/// Паузы.
namespace Pause
{
/// Между запросами статуса на выдачу денег.
const int Dispensing = 300;

/// После отключения на выдачу денег.
const int Disabling = 500;

/// Между повторами команды, если нет ответа.
const int CommandIteration = 100;
}

/// Максимальное количество монет, которое можно установить.
const char MaxPayoutCapacity[] = "\xFF\xFF";

/// Максимальное количество повторов для команды.
const int CommandMaxIteration = 3;

//--------------------------------------------------------------------------------
/// Спецификация статусов.


+ 1
- 0
3.0/src/modules/Hardware/Common/msvc/Common.vcxproj View File

@@ -288,6 +288,7 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ProjectName)\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ProjectName)\$(ConfigurationName)\moc_%(Filename).cpp" -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 -DUNICODE -DWIN32 -DQT_THREAD_SUPPORT -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQCOMPORTWIN_LIB -DCYBERPLAT_DRIVER "-I$(TC_DIR)\." "-I$(TC_INCLUDE_DIR)\." "-I$(THIRDPARTY_DIR)\." "-I.\src" "-I$(QTDIR)\include"</Command>
</CustomBuild>
<ClInclude Include="..\..\..\..\includes\Common\ExitAction.h" />
<ClInclude Include="..\..\..\..\includes\Hardware\Common\BaseStatusTypes.h" />
<ClInclude Include="..\..\..\..\includes\Hardware\Common\ConfigCleaner.h" />
<ClInclude Include="..\..\..\..\includes\Hardware\Common\ContainerProxy.h" />


+ 3
- 0
3.0/src/modules/Hardware/Common/msvc/Common.vcxproj.filters View File

@@ -378,6 +378,9 @@
<ClInclude Include="..\..\..\..\includes\Hardware\Common\ContainerProxy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\includes\Common\ExitAction.h">
<Filter>Utils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\src\locale\common_ru.ts">


+ 3
- 0
3.0/src/modules/Hardware/Common/src/Base/DeviceBase.h View File

@@ -7,6 +7,9 @@
#include <QtCore/QSet>
#include <Common/QtHeadersEnd.h>
// Common
#include "Common/ExitAction.h"
// Project
#include "Hardware/Common/PollingExpector.h"
#include "Hardware/Common/BaseStatusDescriptions.h"


+ 2
- 2
3.0/src/modules/Hardware/Common/src/Polling/PollingDeviceBase.cpp View File

@@ -139,9 +139,9 @@ void PollingDeviceBase<T>::postPollingAction(const TStatusCollection & aNewStatu
{
for (int i = 0; i < mPPTaskList.size(); ++i)
{
mPPTaskList[i]();
mPPTaskList[i]();
mPPTaskList.removeAt(i--);
mPPTaskList.removeAt(i--);
}
}


+ 1
- 1
3.0/src/modules/Hardware/Common/src/Polling/PollingDeviceBase.h View File

@@ -29,7 +29,7 @@ public:
/// Освобождает ресурсы, связанные с устройством, возвращается в состояние до вызова initialize().
virtual bool release();
protected:
/// Завершение инициализации.
virtual void finaliseInitialization();


+ 0
- 14
3.0/src/modules/Hardware/Common/src/Utils/DeviceUtils.h View File

@@ -12,20 +12,6 @@
#include "Hardware/Common/FunctionTypes.h"

//---------------------------------------------------------------------------
// Класс для выполнения функционала при выходе из области видимости.
// Если отпадает необъходимость в его вызове - вызвать reset().
class ExitAction
{
public:
ExitAction(const TVoidMethod & aAction) : mAction(aAction) {}
~ExitAction() { if (mAction) mAction(); }

bool reset() { mAction = TVoidMethod(); return true; }

private:
TVoidMethod mAction;
};

/// Данные устройств.
typedef QMap<QString, QString> TDeviceData;



+ 1
- 0
3.0/src/modules/Hardware/FR/src/Atol/AtolModelData.cpp View File

@@ -49,6 +49,7 @@ CModelData::CModelData()
addOnlineTrade(64, 36, Models::Atol52F, true, 6, CAtolFR::OnlineTradeBuild, false);
addOnlineTrade(62, 36, Models::Atol55F, true, 6);
addOnlineTrade(69, 48, Models::Atol77F, true, 6, CAtolFR::OnlineTradeBuild, false);
addOnlineTrade(82, 32, Models::Atol91F, true, 3, CAtolFR::OnlineTradeBuild, false);
addOnlineTrade(63, 48, Models::FPrint22PTK, true, 6, CAtolFR::OnlineTradeBuild, false);


+ 1
- 0
3.0/src/modules/Hardware/FR/src/Atol/AtolModelData.h View File

@@ -68,6 +68,7 @@ namespace CAtolFR
const char Atol52F[] = "ATOL-52F";
const char Atol55F[] = "ATOL-55F";
const char Atol77F[] = "ATOL-77F";
const char Atol91F[] = "ATOL-91F";
const char Paymaster[] = "Sensis Kaznachej";
const char FPrint22PTK[] = "ATOL FPrint-22PTK";


+ 2
- 2
3.0/src/modules/Hardware/FR/src/Atol/Ejector/AtolVKP80BasedFR.cpp View File

@@ -131,7 +131,7 @@ template <class T>
bool AtolVKP80BasedFR<T>::processReceipt(const QStringList & aReceipt, bool aProcessing)
{
//TODO: проверить необходимость реализации печати картинки
char ejectorMode = mEjectorSettings.receipt | (char(mNextDocument) * mEjectorSettings.nextMask);
char ejectorMode = mEjectorSettings.receipt | (char(mPrintingMode == EPrintingModes::Continuous) * mEjectorSettings.nextMask);
setEjectorMode(ejectorMode);
return AtolEjectorFR<T>::processReceipt(aReceipt, aProcessing);
@@ -141,7 +141,7 @@ bool AtolVKP80BasedFR<T>::processReceipt(const QStringList & aReceipt, bool aPro
template <class T>
bool AtolVKP80BasedFR<T>::performFiscal(const QStringList & aReceipt, const SPaymentData & aPaymentData, quint32 * aFDNumber)
{
char ejectorMode = mEjectorSettings.receipt | (char(mNextDocument) * mEjectorSettings.nextMask);
char ejectorMode = mEjectorSettings.receipt | (char(mPrintingMode == EPrintingModes::Continuous) * mEjectorSettings.nextMask);
setEjectorMode(ejectorMode);
return AtolEjectorFR<T>::performFiscal(aReceipt, aPaymentData, aFDNumber);


+ 10
- 3
3.0/src/modules/Hardware/FR/src/Base/FFEngine.cpp View File

@@ -881,9 +881,17 @@ bool FFEngine::checkAgentFlagOnPayment(SPaymentData & aPaymentData)
}
//--------------------------------------------------------------------------------
void FFEngine::logRemovedFields(const QStringList & aOldTextKeys, SDK::Driver::TFiscalPaymentData & aFPData) const
{
CFR::FiscalFields::TFields removedFields = mFFData.getKeys((aOldTextKeys.toSet() - aFPData.keys().toSet()).toList());
toLog(LogLevel::Normal, mDeviceName + QString(": fiscal fields %1 have been removed from the fiscal payment data").arg(mFFData.getLogFromList(removedFields)));
}
//--------------------------------------------------------------------------------
void FFEngine::filterAfterPayment(TFiscalPaymentData & aFPData, TComplexFiscalPaymentData & aPSData)
{
CFR::FiscalFields::TFields removedFields;
QStringList textKeys = aFPData.keys();
foreach(int field, CFR::FiscalFields::FiscalTotals)
{
@@ -891,12 +899,11 @@ void FFEngine::filterAfterPayment(TFiscalPaymentData & aFPData, TComplexFiscalPa
if (!aFPData.value(textKey).toInt())
{
removedFields << field;
aFPData.remove(textKey);
}
}
toLog(LogLevel::Normal, mDeviceName + QString(": fiscal fields %1 have been removed from the fiscal payment data").arg(mFFData.getLogFromList(removedFields)));
logRemovedFields(textKeys, aFPData);
setFPData(aFPData, CFR::FiscalFields::FDName);
checkFPData(aFPData, CFR::FiscalFields::PayOffType);


+ 3
- 0
3.0/src/modules/Hardware/FR/src/Base/FFEngine.h View File

@@ -99,6 +99,9 @@ public:
/// Добавить/удалить/скорректировать фискальные теги, полученные после платежа.
void filterAfterPayment(SDK::Driver::TFiscalPaymentData & aFPData, SDK::Driver::TComplexFiscalPaymentData & aPSData);
/// Логгировать удаленные фискальные теги.
void logRemovedFields(const QStringList & aOldTextKeys, SDK::Driver::TFiscalPaymentData & aFPData) const;