Browse Source

refs #795 Syncronizing with release commit:244a7e05682c3683bd83f2d456be26b088660cb9 build:201801191720.

git-svn-id: https://help.cyberplat.com/svn@701 03a3ef96-f0a9-4432-b0b0-a3692ed642c1
tags/3.11.0
svn 4 years ago
parent
commit
8a5f43c205
47 changed files with 732 additions and 326 deletions
  1. +23
    -22
      3.0/src/apps/PaymentProcessor/src/Services/PrintingCommands.cpp
  2. +15
    -8
      3.0/src/apps/PaymentProcessor/src/Services/PrintingService.cpp
  3. +3
    -2
      3.0/src/apps/PaymentProcessor/src/Services/TerminalService.cpp
  4. +33
    -0
      3.0/src/includes/Common/PropertyTree.h
  5. +1
    -0
      3.0/src/includes/Hardware/Common/HardwareConstants.h
  6. +1
    -0
      3.0/src/includes/Hardware/Common/Specifications.h
  7. +35
    -17
      3.0/src/includes/Hardware/FR/FRBaseConstants.h
  8. +32
    -14
      3.0/src/includes/Hardware/FR/FiscalFieldDescriptions.h
  9. +4
    -0
      3.0/src/includes/Hardware/FR/ProtoFR.h
  10. +1
    -0
      3.0/src/includes/Hardware/Plugins/DevicePluginBase.h
  11. +2
    -1
      3.0/src/includes/Hardware/Printers/POSPrinterData.h
  12. +2
    -2
      3.0/src/includes/SDK/Drivers/FR/FiscalDataTypes.h
  13. +16
    -7
      3.0/src/includes/SDK/Drivers/FR/FiscalFields.h
  14. +1
    -0
      3.0/src/includes/SDK/Drivers/HardwareConstants.h
  15. +11
    -1
      3.0/src/includes/SDK/Drivers/IFiscalPrinter.h
  16. +2
    -2
      3.0/src/includes/SDK/PaymentProcessor/FiscalRegister/IFiscalRegister.h
  17. +2
    -2
      3.0/src/modules/Hardware/CashAcceptors/src/CCNet/FirmwareVersions.h
  18. +2
    -1
      3.0/src/modules/Hardware/Common/src/Base/DeviceBase.cpp
  19. +2
    -0
      3.0/src/modules/Hardware/Common/src/Meta/MetaDevice.cpp
  20. +12
    -5
      3.0/src/modules/Hardware/FR/src/Atol/Base/AtolFRBase.cpp
  21. +2
    -2
      3.0/src/modules/Hardware/FR/src/Atol/Base/AtolFRBase.h
  22. +22
    -11
      3.0/src/modules/Hardware/FR/src/Atol/Online/AtolOnlineFRBase.cpp
  23. +117
    -55
      3.0/src/modules/Hardware/FR/src/Base/FRBase.cpp
  24. +10
    -4
      3.0/src/modules/Hardware/FR/src/Base/FRBase.h
  25. +10
    -5
      3.0/src/modules/Hardware/FR/src/Kasbi/KasbiFRBase.cpp
  26. +2
    -2
      3.0/src/modules/Hardware/FR/src/Kasbi/KasbiFRBase.h
  27. +1
    -1
      3.0/src/modules/Hardware/FR/src/OPOSMStarTUPK/OPOSMStarTUPK.h
  28. +16
    -3
      3.0/src/modules/Hardware/FR/src/Prim/PrimFRBase.cpp
  29. +4
    -4
      3.0/src/modules/Hardware/FR/src/Prim/PrimFRBase.h
  30. +1
    -0
      3.0/src/modules/Hardware/FR/src/Prim/PrimFRConstants.h
  31. +16
    -1
      3.0/src/modules/Hardware/FR/src/Shtrih/Base/ProtoShtrihFR.cpp
  32. +3
    -0
      3.0/src/modules/Hardware/FR/src/Shtrih/Base/ProtoShtrihFR.h
  33. +12
    -2
      3.0/src/modules/Hardware/FR/src/Shtrih/Online/ShtrihFROnlineConstants.h
  34. +55
    -7
      3.0/src/modules/Hardware/FR/src/Shtrih/Online/ShtrihOnlineFRBase.cpp
  35. +7
    -4
      3.0/src/modules/Hardware/FR/src/Spark/SparkFR.cpp
  36. +2
    -2
      3.0/src/modules/Hardware/FR/src/Spark/SparkFR.h
  37. +1
    -1
      3.0/src/modules/Hardware/IOPorts/src/COM/windows/AsyncSerialPort.cpp
  38. +13
    -1
      3.0/src/modules/Hardware/Printers/src/POSPrinters/Common/POSPrinter.cpp
  39. +1
    -0
      3.0/src/modules/Hardware/Printers/src/POSPrinters/CustomPrinters.cpp
  40. +2
    -0
      3.0/src/modules/Packer/Packer.qbs
  41. +3
    -6
      3.0/src/modules/Packer/msvc/Packer.vcxproj
  42. +0
    -5
      3.0/src/modules/Packer/msvc/Packer.vcxproj.filters
  43. +0
    -101
      3.0/src/modules/Packer/src/Crc32.h
  44. +216
    -19
      3.0/src/modules/Packer/src/Packer.cpp
  45. +4
    -1
      3.0/src/modules/Packer/src/Packer.h
  46. +4
    -0
      3.0/src/modules/SDK/PaymentProcessor/src/TerminalSettings.cpp
  47. +8
    -5
      3.0/src/modules/SDK/PaymentProcessor/src/TerminalSettings.h

+ 23
- 22
3.0/src/apps/PaymentProcessor/src/Services/PrintingCommands.cpp View File

@@ -151,35 +151,33 @@ bool PrintFiscalCommand::getFiscalInfo(QVariantMap & aParameters, QStringList &
{
PPSDK::IFiscalRegister * fr = mService->getFiscalRegister();

if (!fr || !fr->haveCapability(PPSDK::IFiscalRegister::Receipt))
{
return true;
}

QStringList parameterNames = fr->getParameterNames();

// Если в параметрах платежа ещё нет информации о фискальном номере
bool OK = !parameterNames.toSet().intersect(aParameters.keys().toSet()).isEmpty();
if (!OK)
if (fr && fr->haveCapability(PPSDK::IFiscalRegister::Receipt))
{
qint64 paymentId = aParameters.value(PPSDK::CPayment::Parameters::ID).toLongLong();
QDateTime creationDate = aParameters.value(PPSDK::CPayment::Parameters::CreationDate, "").toDateTime();
QStringList parameterNames = fr->getParameterNames();

auto fiscalParameters = fr->createFiscalTicket(paymentId, creationDate, getPaymentData(aParameters));
OK = !fiscalParameters.isEmpty();
// Если в параметрах платежа ещё нет информации о фискальном номере
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);
aParameters.unite(fiscalParameters);

mService->setFiscalNumber(paymentId, fiscalParameters);
}
mService->setFiscalNumber(paymentId, fiscalParameters);
}

if (OK)
{
aReceiptLines = fr->getReceipt(aParameters);
if (OK)
{
aReceiptLines = fr->getReceipt(paymentId, aParameters);
}

return OK;
}

return OK;
return false;
}

//---------------------------------------------------------------------------
@@ -236,7 +234,10 @@ bool PrintPayment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParamet

if (!mFiscalPaymentData.isEmpty())
{
#define ADD_FISCAL_TAG(aTranstation, aFiscalTag) receipt << aTranstation + ": " + mFiscalPaymentData[DSDK::FiscalFields::aFiscalTag].toString();
#define ADD_FISCAL_TAG(aTranstation, aFiscalTag) \
if (DSDK::FiscalFields::isMoney(DSDK::FiscalFields::aFiscalTag)) \
{ receipt << QString("%1: %2").arg(aTranstation).arg(mFiscalPaymentData[DSDK::FiscalFields::aFiscalTag].toInt() / 100.0, 0, 'f', 2); } \
else { receipt << QString("%1: %2").arg(aTranstation).arg(mFiscalPaymentData[DSDK::FiscalFields::aFiscalTag].toString()); }

ADD_FISCAL_TAG(tr("#taxation"), TaxSystem);
ADD_FISCAL_TAG(tr("#kkt_timestamp"), FDDateTime);


+ 15
- 8
3.0/src/apps/PaymentProcessor/src/Services/PrintingService.cpp View File

@@ -143,9 +143,6 @@ bool PrintingService::initialize()
//------------------------------------------------------------------------------
void PrintingService::finishInitialize()
{
auto settings = SettingsService::instance(mApplication)->getAdapter<SDK::PaymentProcessor::TerminalSettings>();

mRandomReceiptsID = settings->getCommonSettings().randomReceiptsID;
}

//---------------------------------------------------------------------------
@@ -1396,13 +1393,12 @@ void PrintingService::updateHardwareConfiguration()
.arg(DSDK::CComponents::Printer).arg(DSDK::CComponents::DocumentPrinter).arg(DSDK::CComponents::FiscalRegistrator);
QStringList printerNames = settings->getDeviceList().filter(QRegExp(regExpData));

mRandomReceiptsID = settings->getCommonSettings().randomReceiptsID;
QTime autoZReportTime = settings->getCommonSettings().autoZReportTime;

mPrinterDevices.clear();
mAvailablePrinters.clear();

QVariantMap delalerSettings;
delalerSettings.insert(CHardwareSDK::FR::DealerTaxation, mStaticParameters.value(CPrintConstants::DealerTaxation));
delalerSettings.insert(CHardwareSDK::FR::DealerAgentFlag, mStaticParameters.value(CPrintConstants::DealerAgentFlag));

// Запрашиваем устройства.
foreach (const QString & printerName, printerNames)
{
@@ -1410,6 +1406,10 @@ void PrintingService::updateHardwareConfiguration()

if (device)
{
QVariantMap dealerSettings;
dealerSettings.insert(CHardwareSDK::FR::DealerTaxation, mStaticParameters.value(CPrintConstants::DealerTaxation));
dealerSettings.insert(CHardwareSDK::FR::DealerAgentFlag, mStaticParameters.value(CPrintConstants::DealerAgentFlag));

mPrinterDevices.append(device);

// Подписываемся на события принтера.
@@ -1419,9 +1419,16 @@ void PrintingService::updateHardwareConfiguration()
if (dynamic_cast<DSDK::IFiscalPrinter *>(device))
{
device->subscribe(SDK::Driver::IFiscalPrinter::FRSessionClosedSignal, this, SLOT(onFRSessionClosed(const QVariantMap &)));

if (autoZReportTime.isValid() && !autoZReportTime.isNull())
{
toLog(LogLevel::Normal, QString("Setup auto z-report time: %1.").arg(autoZReportTime.toString("hh:mm:ss")));

dealerSettings.insert(CHardwareSDK::FR::ZReportTime, autoZReportTime);
}
}

device->setDeviceConfiguration(delalerSettings);
device->setDeviceConfiguration(dealerSettings);
}
else
{


+ 3
- 2
3.0/src/apps/PaymentProcessor/src/Services/TerminalService.cpp View File

@@ -580,10 +580,11 @@ void TerminalService::sendFeedback(const QString & aSenderSubsystem, const QStri

zipArray += "]";

QByteArray gz;
if (Packer::gzipCompress(zipArray, QString("payment_%1.json").arg(paymentId), gz))
{
sendBody += "pluslog_val=";
sendBody += Packer::compressToGZ(zipArray, QString("payment_%1.json").arg(paymentId)).toBase64().toPercentEncoding() + "&";
toLog(LogLevel::Debug, QString("sizeof zippped log: %1").arg(zipArray.size()));
sendBody += gz.toBase64().toPercentEncoding() + "&";
}
}



+ 33
- 0
3.0/src/includes/Common/PropertyTree.h View File

@@ -14,6 +14,7 @@
// Qt
#include <Common/QtHeadersBegin.h>
#include <QtCore/QString>
#include <QtCore/QTime>
#include <Common/QtHeadersEnd.h>

//---------------------------------------------------------------------------
@@ -165,6 +166,22 @@ inline std::wstring WStringTranslator<bool>::put_value(const bool & aValue) cons
}

//---------------------------------------------------------------------------
template<>
inline QTime WStringTranslator<QTime>::get_value(const std::wstring & aValue) const
{
QString v = QString::fromStdWString(aValue);

return QTime::fromString(v);
};

//---------------------------------------------------------------------------
template<>
inline std::wstring WStringTranslator<QTime>::put_value(const QTime & aValue) const
{
return aValue.toString("hh:mm:ss").toStdWString();
}

//---------------------------------------------------------------------------
// For std::string with utf-8 encoding
//---------------------------------------------------------------------------

@@ -316,3 +333,19 @@ inline std::string StringTranslator<bool>::put_value(const bool & aValue) const
}

//---------------------------------------------------------------------------
template<>
inline QTime StringTranslator<QTime>::get_value(const std::string & aValue) const
{
QString v = QString::fromUtf8(aValue.c_str());

return QTime::fromString(v);
};

//---------------------------------------------------------------------------
template<>
inline std::string StringTranslator<QTime>::put_value(const QTime & aValue) const
{
return aValue.toString("hh:mm:ss").toStdString();
}

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

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

@@ -16,6 +16,7 @@ namespace CHardware
const char UpdatingFilenameExtension[] = "updating_filename_extension";
const char PluginParameterNames[] = "plugin_parameter_names";
const char RequiredResourceNames[] = "required_resource_names";
const char PluginPath[] = "plugin_path";

/// Типы вызова функционала драйвера.
namespace CallingTypes


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

@@ -57,6 +57,7 @@ public:
return result.join(", ");
}

protected:
void addBit(int aBit, const char * aParameter)
{
append(T(1) << aBit, QString::fromUtf8(aParameter));


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

@@ -11,6 +11,7 @@
#include <numeric>

// SDK
#include <SDK/Drivers/FR/FiscalFields.h>
#include <SDK/Drivers/FR/FiscalDataTypes.h>

// Modules
@@ -95,6 +96,9 @@ namespace CFR
/// Количество секунд в сутках.
const int SecsInDay = 24 * 60 * 60;

/// Количество миллисекунд в сутках.
const int MSecsInDay = SecsInDay * 1000;

/// Константные данные ФФД.
struct SFFDData
{
@@ -271,7 +275,7 @@ namespace CFR
append(SimplifiedIncomeMinusExpense, "УСН доход - расход");
append(SingleImputedIncome, "ЕНВД");
append(SingleAgricultural, "ЕСН");
append(Patent, "патент");
append(Patent, "Патент");
}
};

@@ -334,28 +338,42 @@ namespace CFR
static CPayOffTypes PayOffTypes;

//--------------------------------------------------------------------------------
/// Наименование фискального чека.
const QString CashFDName = QString::fromUtf8("КАССОВЫЙ ЧЕК");
const QString FDName = QString::fromUtf8("КАССОВЫЙ ЧЕК"); /// ПФ тега 1000 (Наименование фискального документа).
const QString LotteryMode = QString::fromUtf8("ПРОВЕДЕНИЕ ЛОТЕРЕИ"); /// ПФ тега 1126 (Признак проведения лотереи).
const QString GamblingMode = QString::fromUtf8("ПРОВЕДЕНИЕ АЗАРТНОЙ ИГРЫ"); /// ПФ тега 1193 (Признак проведения азартных игр).
const QString ExcisableUnitMode = QString::fromUtf8("ПОДАКЦИЗНЫЕ ТОВАРЫ"); /// ПФ тега 1207 (Признак торговли подакцизными товарами).

//--------------------------------------------------------------------------------
/// Режимы работы.
class COperationModes : public CBitmapDescription<char>
namespace OperationModes
{
public:
COperationModes()
struct SData
{
using namespace SDK::Driver::EOperationModes;

append(Encrypting, "шифрование");
append(Autonomous, "автономный режим");
append(Automatic, "автоматический режим");
append(ServicesArea, "сфера услуг");
append(FixedReporting, "БСО");
append(Internet, "интернет");
}
};
int field;
QString description;

SData(): field(0) {}
SData(int aField, const QString & aDescription): field(aField), description(aDescription) {}
};

static COperationModes OperationModes;
#define ADD_OPERATION_MODE(aName, aDescription) append(SDK::Driver::EOperationModes::aName, SData(SDK::Driver::FiscalFields::aName##Mode, QString::fromUtf8(aDescription)))

class CData: public CSpecification<char, SData>
{
public:
CData()
{
ADD_OPERATION_MODE(Encryption, "ШФД");
ADD_OPERATION_MODE(Autonomous, "АВТОНОМН. РЕЖИМ");
ADD_OPERATION_MODE(Automatic, "АВТОМАТ. РЕЖИМ");
ADD_OPERATION_MODE(ServiceArea, "ККТ ДЛЯ УСЛУГ");
ADD_OPERATION_MODE(FixedReporting, "АС БСО");
ADD_OPERATION_MODE(Internet, "ККТ ДЛЯ ИНТЕРНЕТ");
}
};

static CData Data;
}
}

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

+ 32
- 14
3.0/src/includes/Hardware/FR/FiscalFieldDescriptions.h View File

@@ -12,6 +12,8 @@
namespace CHardware { namespace FiscalFields
{
const char FDName[] = "fd_name"; // 1000 (Наименование фискального документа).
const char AutomaticMode[] = "automatic_mode"; // 1001 (Признак автоматического режима).
const char AutonomousMode[] = "autonomous_mode"; // 1002 (Признак автономного режима).
const char UserContact[] = "user_contact"; // 1008 (Телефон или электронный адрес покупателя).
const char PayOffAddress[] = "payoff_address"; // 1009 (Адрес расчетов).
const char FDDateTime[] = "fd_date_time"; // 1012 (Дата и время ФД).
@@ -32,6 +34,7 @@ namespace CHardware { namespace FiscalFields
const char LegalOwner[] = "legal_owner"; // 1048 (Наименование юр. лица владельца).
const char PayOffType[] = "payoff_type"; // 1054 (Признак расчета).
const char TaxSystem[] = "tax_system"; // 1055 (СНО на платеже).
const char EncryptionMode[] = "encryption_mode"; // 1056 (Признак шифрования).
const char AgentFlagsRegistered[] = "agent_flags_registered"; // 1057 (Признак(и) платежного агента из итогов регистрации).
const char PayOffSubject[] = "payoff_subject"; // 1059 (Предмет расчета).
const char FTSURL[] = "fts_url"; // 1060 (Адрес сайта ФНС).
@@ -52,13 +55,19 @@ namespace CHardware { namespace FiscalFields
const char TaxAmount06[] = "tax_amount_06"; // 1106 (Сумма НДС чека по расчетной ставке 18/118).
const char TaxAmount07[] = "tax_amount_07"; // 1107 (Сумма НДС чека по расчетной ставке 10/110).

const char PayOffPlace[] = "payoff_place"; // 1187 (Место расчетов).
const char VATRate[] = "vat_rate"; // 1199 (Ставка НДС).
const char CashierINN[] = "cashier_inn"; // 1203 (ИНН кассира).
const char OFDURL[] = "ofd_url"; // 1208 (Адрес сайта для получения чека).
const char PayOffSubjectType[] = "payoff_subject_type"; // 1212 (Признак предмета расчета).
const char PayOffMethodType[] = "payoff_method_type"; // 1214 (Признак способа расчета).
const char AgentFlag[] = "agent_flags"; // 1222 (Признак платежного агента на платеже).
const char InternetMode[] = "internet_mode"; // 1108 (Признак работы с интернет (без принтера).
const char ServiceAreaMode[] = "service_area_mode"; // 1109 (Признак применения в сфере услуг).
const char FixedReportingMode[] = "fixed_reporting_mode"; // 1110 (Признак работы с бланками строгой отчетности (БСО).
const char LotteryMode[] = "lottery_mode"; // 1126 (Признак проведения лотереи).
const char PayOffPlace[] = "payoff_place"; // 1187 (Место расчетов).
const char GamblingMode[] = "gambling_mode"; // 1193 (Признак проведения азартных игр).
const char VATRate[] = "vat_rate"; // 1199 (Ставка НДС).
const char CashierINN[] = "cashier_inn"; // 1203 (ИНН кассира).
const char ExcisableUnitMode[] = "excisable_unit_mode"; // 1207 (Признак торговли подакцизными товарами).
const char OFDURL[] = "ofd_url"; // 1208 (Адрес сайта для получения чека).
const char PayOffSubjectType[] = "payoff_subject_type"; // 1212 (Признак предмета расчета).
const char PayOffMethodType[] = "payoff_method_type"; // 1214 (Признак способа расчета).
const char AgentFlag[] = "agent_flag"; // 1222 (Признак платежного агента на платеже).

}} // namespace CHardware::FiscalFields

@@ -150,6 +159,8 @@ namespace CFR { namespace FiscalFields
#define ADD_FISCAL_FIELD(aName, aType) append(SDK::Driver::FiscalFields::aName, SData(ETypes::aType, CHardware::FiscalFields::aName))

ADD_FISCAL_FIELD(FDName, String); // 1000 (Наименование фискального документа).
ADD_FISCAL_FIELD(AutomaticMode, Byte); // 1001 (Признак автоматического режима).
ADD_FISCAL_FIELD(AutonomousMode, Byte); // 1002 (Признак автономного режима).
ADD_FISCAL_FIELD(UserContact, String); // 1008 (Телефон или электронный адрес покупателя).
ADD_FISCAL_FIELD(PayOffAddress, String); // 1009 (Адрес расчетов).
ADD_FISCAL_FIELD(FDDateTime, UnixTime); // 1012 (Дата и время ФД).
@@ -170,6 +181,7 @@ namespace CFR { namespace FiscalFields
ADD_FISCAL_FIELD(LegalOwner, String); // 1048 (Наименование юр. лица владельца).
ADD_FISCAL_FIELD(PayOffType, Byte); // 1054 (Признак расчета).
ADD_FISCAL_FIELD(TaxSystem, Byte); // 1055 (СНО на платеже).
ADD_FISCAL_FIELD(EncryptionMode, Byte); // 1056 (Признак шифрования).
ADD_FISCAL_FIELD(AgentFlagsRegistered, Byte); // 1057 (Признак(и) платежного агента из итогов регистрации).
ADD_FISCAL_FIELD(PayOffSubject, STLV); // 1059 (Предмет расчета).
ADD_FISCAL_FIELD(FTSURL, String); // 1060 (Адрес сайта ФНС).
@@ -190,13 +202,19 @@ namespace CFR { namespace FiscalFields
ADD_FISCAL_FIELD(TaxAmount06, VLN); // 1106 (Сумма НДС чека по расчетной ставке 18/118).
ADD_FISCAL_FIELD(TaxAmount07, VLN); // 1107 (Сумма НДС чека по расчетной ставке 10/110).

ADD_FISCAL_FIELD(PayOffPlace, String); // 1187 (Место расчетов).
ADD_FISCAL_FIELD(VATRate, Byte); // 1199 (Ставка НДС).
ADD_FISCAL_FIELD(CashierINN, String); // 1203 (ИНН кассира).
ADD_FISCAL_FIELD(OFDURL, String); // 1208 (Адрес сайта для получения чека).
ADD_FISCAL_FIELD(PayOffSubjectType, Byte); // 1212 (Признак предмета расчета).
ADD_FISCAL_FIELD(PayOffMethodType, Byte); // 1214 (Признак способа расчета).
ADD_FISCAL_FIELD(AgentFlag, Byte); // 1222 (Признак платежного агента на платеже).
ADD_FISCAL_FIELD(InternetMode, Byte); // 1108 (Признак работы с интернет (без принтера).
ADD_FISCAL_FIELD(ServiceAreaMode, Byte); // 1109 (Признак применения в сфере услуг).
ADD_FISCAL_FIELD(FixedReportingMode, Byte); // 1110 (Признак работы с бланками строгой отчетности (БСО).
ADD_FISCAL_FIELD(LotteryMode, Byte); // 1126 (Признак проведения лотереи).
ADD_FISCAL_FIELD(PayOffPlace, String); // 1187 (Место расчетов).
ADD_FISCAL_FIELD(GamblingMode, Byte); // 1193 (Признак проведения азартных игр).
ADD_FISCAL_FIELD(VATRate, Byte); // 1199 (Ставка НДС).
ADD_FISCAL_FIELD(CashierINN, String); // 1203 (ИНН кассира).
ADD_FISCAL_FIELD(ExcisableUnitMode, Byte); // 1207 (Признак торговли подакцизными товарами).
ADD_FISCAL_FIELD(OFDURL, String); // 1208 (Адрес сайта для получения чека).
ADD_FISCAL_FIELD(PayOffSubjectType, Byte); // 1212 (Признак предмета расчета).
ADD_FISCAL_FIELD(PayOffMethodType, Byte); // 1214 (Признак способа расчета).
ADD_FISCAL_FIELD(AgentFlag, Byte); // 1222 (Признак платежного агента на платеже).
}
};



+ 4
- 0
3.0/src/includes/Hardware/FR/ProtoFR.h View File

@@ -18,6 +18,10 @@ class ProtoFR: public ProtoDevice, public SDK::Driver::IFiscalPrinter
signals :
/// Данные о закрытой сессии.
void FRSessionClosed(const QVariantMap & aOutData);

protected slots:
/// Выполнить Z-отчет.
virtual void onExecZReport() {}
};

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

+ 1
- 0
3.0/src/includes/Hardware/Plugins/DevicePluginBase.h View File

@@ -58,6 +58,7 @@ public:
QVariantMap configuration;
configuration.insert(CHardware::PluginParameterNames, pluginParameterNames);
configuration.insert(CHardware::RequiredResourceNames, requiredResourceNames);
configuration.insert(CHardware::PluginPath, makeDriverPath<T>());
T::setDeviceConfiguration(configuration);
}
}


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

@@ -29,13 +29,14 @@ namespace CPOSPrinter
const char PrintImage[] = "\x1D\x76\x30"; /// Печать картинки.
const char AlignLeft[] = "\x1B\x61\x30"; /// Выравнивание по левому краю.

/// Штрих-коды.
namespace Barcode
{
const char Height[] = "\x1D\x68"; /// Высота штрих-кода - 20.25 мм.
const char HRIPosition[] = "\x1D\x48"; /// Позиционирование символов штрих-кода - выше штрих-кода.
const char FontSize[] = "\x1D\x66"; /// Размер шрифта штрих-кода.
const char Width[] = "\x1D\x77"; /// Ширина линии - 0.25 мм.
const char Print[] = "\x1D\x6B"; /// Ширина линии - 0.25 мм.
const char Print[] = "\x1D\x6B"; /// Печать.
}
}



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

@@ -128,10 +128,10 @@ namespace EOperationModes
enum Enum
{
None = 0x00, /// Отсутствует
Encrypting = 0x01, /// Шифрование
Encryption = 0x01, /// Шифрование
Autonomous = 0x02, /// Автономный режим
Automatic = 0x04, /// Автоматический режим
ServicesArea = 0x08, /// Применение в сфере услуг
ServiceArea = 0x08, /// Применение в сфере услуг
FixedReporting = 0x10, /// Бланк строгой отчетности (БСО)
Internet = 0x20 /// Применение в интернете
};


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

@@ -8,6 +8,8 @@ namespace Driver {
namespace FiscalFields
{
const int FDName = 1000; // Наименование фискального документа.
const int AutomaticMode = 1001; // Признак автоматического режима.
const int AutonomousMode = 1002; // Признак автономного режима.
const int UserContact = 1008; // Телефон или электронный адрес покупателя.
const int PayOffAddress = 1009; // Адрес расчетов.
const int FDDateTime = 1012; // Дата и время ФД.
@@ -28,6 +30,7 @@ namespace FiscalFields
const int LegalOwner = 1048; // Наименование юр. лица владельца.
const int PayOffType = 1054; // Признак расчета.
const int TaxSystem = 1055; // СНО на платеже.
const int EncryptionMode = 1056; // Признак шифрования.
const int AgentFlagsRegistered = 1057; // Признак(и) платежного агента из итогов регистрации.
const int PayOffSubject = 1059; // Предмет расчета.
const int FTSURL = 1060; // Адрес сайта ФНС.
@@ -48,13 +51,19 @@ namespace FiscalFields
const int TaxAmount06 = 1106; // Сумма НДС чека по расчетной ставке 18/118.
const int TaxAmount07 = 1107; // Сумма НДС чека по расчетной ставке 10/110.

const int PayOffPlace = 1187; // Место расчетов.
const int VATRate = 1199; // Ставка НДС.
const int CashierINN = 1203; // ИНН кассира.
const int OFDURL = 1208; // Адрес сайта для получения чека.
const int PayOffSubjectType = 1212; // Признак предмета расчета.
const int PayOffMethodType = 1214; // Признак способа расчета.
const int AgentFlag = 1222; // Признак платежного агента на платеже.
const int InternetMode = 1108; // Признак работы с интернет (без принтера).
const int ServiceAreaMode = 1109; // Признак применения в сфере услуг.
const int FixedReportingMode = 1110; // Признак работы с бланками строгой отчетности (БСО).
const int LotteryMode = 1126; // Признак проведения лотереи.
const int PayOffPlace = 1187; // Место расчетов.
const int GamblingMode = 1193; // Признак проведения азартных игр.
const int VATRate = 1199; // Ставка НДС.
const int CashierINN = 1203; // ИНН кассира.
const int ExcisableUnitMode = 1207; // Признак торговли подакцизными товарами.
const int OFDURL = 1208; // Адрес сайта для получения чека.
const int PayOffSubjectType = 1212; // Признак предмета расчета.
const int PayOffMethodType = 1214; // Признак способа расчета.
const int AgentFlag = 1222; // Признак платежного агента на платеже.

// Является ли поле денежным.
inline bool isMoney(int aField)


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

@@ -58,6 +58,7 @@ namespace CAllHardware
const char DealerAgentFlag[] = "dealer_agent_flag";
const char UserPhone[] = "user_phone";
const char UserMail[] = "user_mail";
const char ZReportTime[] = "z_report_time";
}

/// Константы принтера.


+ 11
- 1
3.0/src/includes/SDK/Drivers/IFiscalPrinter.h View File

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

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

class IFiscalPrinter: public IPrinter
{
public:
@@ -39,7 +49,7 @@ public:
virtual bool isFiscalReady(bool aOnline, EFiscalPrinterCommand::Enum aCommand = EFiscalPrinterCommand::Sale) = 0;

/// Открыта ли сессия.
virtual bool isSessionOpened() = 0;
//virtual ESessionState::Enum getSessionState() = 0;

/// Находится ли в фискальном режиме.
virtual bool isFiscal() const = 0;


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

@@ -40,10 +40,10 @@ public:
virtual bool haveCapability(quint32 aCapabilityFlags) = 0;

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

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

/// Получить отчёт по балансу ФР
virtual QStringList balance() = 0;


+ 2
- 2
3.0/src/modules/Hardware/CashAcceptors/src/CCNet/FirmwareVersions.h View File

@@ -24,12 +24,12 @@ namespace CCCNet
{
data()[Models::CashcodeGX ][Currency::RUB][true] = TFimwareVersionSet() << 1205;

data()[Models::CashcodeSM ][Currency::RUB][true] = TFimwareVersionSet() << 1350;
data()[Models::CashcodeSM ][Currency::RUB][true] = TFimwareVersionSet() << 1351;

data()[Models::CashcodeSM ][Currency::RUB][false] = TFimwareVersionSet() << 1378 << 1434;
data()[Models::CashcodeMSM][Currency::RUB][false] = TFimwareVersionSet() << 1114;
data()[Models::CashcodeMSM][Currency::EUR][false] = TFimwareVersionSet() << 1130 << 1228 << 1329 << 1411 << 1527;
data()[Models::CashcodeMVU][Currency::RUB][false] = TFimwareVersionSet() << 1329;
data()[Models::CashcodeMVU][Currency::RUB][false] = TFimwareVersionSet() << 1330;
data()[Models::CashcodeMFL][Currency::RUB][false] = TFimwareVersionSet() << 1140;
data()[Models::CashcodeSL ][Currency::RUB][false] = TFimwareVersionSet() << 1013 << 2004 << 3003 << 0005;



+ 2
- 1
3.0/src/modules/Hardware/Common/src/Base/DeviceBase.cpp View File

@@ -265,8 +265,9 @@ void DeviceBase<T>::initialize()
processStatusCodes(TStatusCodes() << DeviceStatusCode::Error::NotAvailable);
}

QString pluginPath = QString("\n%1 : %2").arg(CHardware::PluginPath).arg(getConfigParameter(CHardware::PluginPath).toString());
SLogData logData = getDeviceData();
setConfigParameter(CHardwareSDK::DeviceData, logData.pluginConfig + logData.device + logData.requiedDevicePluginConfig);
setConfigParameter(CHardwareSDK::DeviceData, pluginPath + logData.pluginConfig + logData.device + logData.requiedDevicePluginConfig);
logDeviceData(logData);
removeConfigParameter(CHardware::CallingType);



+ 2
- 0
3.0/src/modules/Hardware/Common/src/Meta/MetaDevice.cpp View File

@@ -206,6 +206,8 @@ bool MetaDevice::containsDeviceParameter(const QString & aName) const
//---------------------------------------------------------------------------
void MetaDevice::logDeviceData(const SLogData & aData) const
{
toLog(LogLevel::Normal, "Plugin path: " + getConfigParameter(CHardware::PluginPath).toString());

if (!aData.pluginConfig.isEmpty())
{
toLog(LogLevel::Normal, "Plugin data:" + aData.pluginConfig);


+ 12
- 5
3.0/src/modules/Hardware/FR/src/Atol/Base/AtolFRBase.cpp View File

@@ -309,7 +309,7 @@ TResult AtolFRBase::execCommand(const QByteArray & aCommand, const QByteArray &

if (mModelData.ZBufferSize && ((aCommand[0] == CAtolFR::Commands::OpenDocument) || (aCommand[0] == CAtolFR::Commands::Encashment)))
{
isSessionInZBufferOpened = !isSessionOpened();
isSessionInZBufferOpened = getSessionState() == ESessionState::Closed;
}

QByteArray commandData = aCommand + aCommandData;
@@ -397,7 +397,7 @@ void AtolFRBase::setErrorFlags(char aError, const QByteArray & /*aCommand*/)
//--------------------------------------------------------------------------------
bool AtolFRBase::openFRSession()
{
if (isSessionOpened())
if (getSessionState() == ESessionState::Opened)
{
return true;
}
@@ -1375,7 +1375,7 @@ bool AtolFRBase::execZReport(bool aAuto)

bool success = false;

if (isSessionOpened())
if (getSessionState() == ESessionState::Opened)
{
char innerMode = mMode;

@@ -1464,11 +1464,18 @@ void AtolFRBase::checkZBufferState()
}

//--------------------------------------------------------------------------------
bool AtolFRBase::isSessionOpened()
ESessionState::Enum AtolFRBase::getSessionState()
{
QByteArray data;

return getLongStatus(data) && bool(data[9] & CAtolFR::States::SessionOpen);
if (!getLongStatus(data) || (data.size() <= 9))
{
return ESessionState::Error;
}

bool result = bool(data[9] & CAtolFR::States::SessionOpen);

return result ? ESessionState::Opened : ESessionState::Closed;
}

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


+ 2
- 2
3.0/src/modules/Hardware/FR/src/Atol/Base/AtolFRBase.h View File

@@ -135,7 +135,7 @@ protected:
bool exitInnerMode();

/// Выполнить Z-отчет.
bool execZReport(bool aAuto);
virtual bool execZReport(bool aAuto);

/// Установить параметры ФР.
virtual bool setFRParameters();
@@ -162,7 +162,7 @@ protected:
void checkZBufferState();

/// Узнать, открыта ли смена.
bool isSessionOpened();
virtual SDK::Driver::ESessionState::Enum getSessionState();

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


+ 22
- 11
3.0/src/modules/Hardware/FR/src/Atol/Online/AtolOnlineFRBase.cpp View File

@@ -64,7 +64,9 @@ bool AtolOnlineFRBase::updateParameters()
return false;
}

if (!processCommand(CAtolOnlineFR::Commands::FS::GetFiscalizationResume, &data) || (data.size() <= 40))
int reregistrationNumber = getDeviceParameter(CDeviceData::FR::ReregistrationNumber).toInt();

if (!processCommand(CAtolOnlineFR::Commands::FS::GetFiscalizationResume, QByteArray(1, char(reregistrationNumber)), &data) || (data.size() <= 40))
{
return false;
}
@@ -76,12 +78,22 @@ bool AtolOnlineFRBase::updateParameters()

using namespace CFR::FiscalFields;

ERequired::Enum required = (mTaxations.size() > 1) ? ERequired::Yes : ERequired::No;
mFiscalFieldData.data()[FiscalFields::TaxSystem].required = required;
ERequired::Enum taxationRequired = (mTaxations.size() > 1) ? ERequired::Yes : ERequired::No;
ERequired::Enum agentFlagRequired = (mAgentFlags.size() > 1) ? ERequired::Yes : ERequired::No;

mFiscalFieldData.data()[FiscalFields::TaxSystem].required = taxationRequired;
mFiscalFieldData.data()[FiscalFields::AgentFlag].required = agentFlagRequired;

#define SET_LCONFIG_FISCAL_FIELD(aName) QString aName##Log = QString("fiscal tag %1 (%2)").arg(FiscalFields::aName).arg(CHardware::FiscalFields::aName); \
if (getTLV(FiscalFields::aName, data)) { setLConfigParameter(CHardware::FiscalFields::aName, data); \
QString value = getConfigParameter(CHardware::FiscalFields::aName, data).toString(); \
toLog(LogLevel::Normal, QString("%1: Add %2 = \"%3\" to config data").arg(mDeviceName).arg(aName##Log).arg(value)); } \
else toLog(LogLevel::Error, QString("%1: Failed to add %2 to config data").arg(mDeviceName).arg(aName##Log));

#define SET_LCONFIG_FISCAL_FIELD(aName) if (getTLV(FiscalFields::aName, data)) { setLConfigParameter(CHardware::FiscalFields::aName, data); \
toLog(LogLevel::Normal, QString("%1: Set fiscal tag %2 (%3) = \"%4\" to config data") \
.arg(mDeviceName).arg(FiscalFields::aName).arg(CHardware::FiscalFields::aName).arg(getConfigParameter(CHardware::FiscalFields::aName, data).toString())); }
#define SET_BCONFIG_FISCAL_FIELD(aName) QString aName##Log = QString("fiscal tag %1 (%2)").arg(FiscalFields::aName).arg(CHardware::FiscalFields::aName); \
if (getTLV(FiscalFields::aName, data)) { char value = data[0]; setConfigParameter(CHardware::FiscalFields::aName, value); \
toLog(LogLevel::Normal, QString("%1: Add %2 = %3 to config data").arg(mDeviceName).arg(aName##Log).arg(int(value))); } \
else toLog(LogLevel::Error, QString("%1: Failed to add %2 to config data").arg(mDeviceName).arg(aName##Log));

SET_LCONFIG_FISCAL_FIELD(FTSURL);
SET_LCONFIG_FISCAL_FIELD(OFDURL);
@@ -90,12 +102,11 @@ bool AtolOnlineFRBase::updateParameters()
SET_LCONFIG_FISCAL_FIELD(PayOffAddress);
SET_LCONFIG_FISCAL_FIELD(PayOffPlace);

if (getTLV(FiscalFields::AgentFlagsRegistered, data))
{
return checkAgentFlags(data[0]);
}
SET_BCONFIG_FISCAL_FIELD(LotteryMode);
SET_BCONFIG_FISCAL_FIELD(GamblingMode);
SET_BCONFIG_FISCAL_FIELD(ExcisableUnitMode);

return true;
return getTLV(FiscalFields::AgentFlagsRegistered, data) && !data.isEmpty() && checkAgentFlags(data[0]);
}

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


+ 117
- 55
3.0/src/modules/Hardware/FR/src/Base/FRBase.cpp View File

@@ -80,7 +80,6 @@ void FRBase<T>::setInitialData()
mZBufferFull = false;
mZBufferOverflow = false;
mPrinterCollapse = false;
mSessionOpened = true;
mFiscalized = true;
mZBufferError = false;
mFiscalCollapse = false;
@@ -157,7 +156,7 @@ void FRBase<T>::finaliseInitialization()

foreach(char operationMode, mOperationModes)
{
operationModedata.insert(EOperationModes::Enum(operationMode), CFR::OperationModes[operationMode]);
operationModedata.insert(EOperationModes::Enum(operationMode), CFR::OperationModes::Data[operationMode].description);
}

setDeviceParameter(CDeviceData::FS::SerialNumber, mFSSerialNumber);
@@ -176,6 +175,41 @@ void FRBase<T>::finaliseInitialization()
}

T::finaliseInitialization();

checkZReportOnTimer();
}

//---------------------------------------------------------------------------
template <class T>
void FRBase<T>::onExecZReport()
{
toLog(LogLevel::Normal, mDeviceName + ": Z-report timer has fired");

execZReport(true);

checkZReportOnTimer();
}

//---------------------------------------------------------------------------
template <class T>
void FRBase<T>::checkZReportOnTimer()
{
QTime ZReportTime = getConfigParameter(CHardwareSDK::FR::ZReportTime).toTime();

if (ZReportTime.isValid())
{
QTime current = QTime::currentTime();
int delta = current.msecsTo(ZReportTime);

if (delta < 0)
{
delta += CFR::MSecsInDay;
}

toLog(LogLevel::Normal, mDeviceName + ": Timer for Z-report is scheduled for " + ZReportTime.toString(CFR::TimeLogFormat));

QTimer::singleShot(delta, this, SLOT(onExecZReport()));
}
}

//---------------------------------------------------------------------------
@@ -250,7 +284,7 @@ bool FRBase<T>::checkOperationModes(char aData)

if (aData & operationMode)
{
if (!CFR::OperationModes.data().contains(operationMode))
if (!CFR::OperationModes::Data.data().contains(operationMode))
{
errorLog << toHexLog(operationMode);
}
@@ -351,6 +385,11 @@ void FRBase<T>::checkFSFlags(char aFlags, TStatusCodes & aStatusCodes)
template <class T>
void FRBase<T>::checkOFDNotSentCount(int aOFDNotSentCount, TStatusCodes & aStatusCodes)
{
if (mOperationModes.contains(EOperationModes::Autonomous))
{
return;
}

if (aOFDNotSentCount < 0)
{
aStatusCodes.insert(DeviceStatusCode::Warning::Unknown);
@@ -643,6 +682,7 @@ bool FRBase<T>::printFiscal(const QStringList & aReceipt, const SPaymentData & a
if (mTaxations.contains(taxationData))
{
paymentData.taxation = dealerTaxation;
setConfigParameter(CHardware::FiscalFields::TaxSystem, taxationData);
}
else if (mTaxations.size() == 1)
{
@@ -684,6 +724,7 @@ bool FRBase<T>::printFiscal(const QStringList & aReceipt, const SPaymentData & a
if (mAgentFlags.contains(agentFlagData))
{
paymentData.agentFlag = dealerAgentFlag;
setConfigParameter(CHardware::FiscalFields::AgentFlag, agentFlagData);
}
else if (mAgentFlags.size() == 1)
{
@@ -746,67 +787,81 @@ bool FRBase<T>::printFiscal(const QStringList & aReceipt, const SPaymentData & a
aFPData.clear();
aPSData.clear();

bool result = processNonReentrant(std::bind(&FRBase::performFiscal, this, std::ref(receipt), std::ref(paymentData), std::ref(aFPData), std::ref(aPSData)));
if (!processNonReentrant(std::bind(&FRBase::performFiscal, this, std::ref(receipt), std::ref(paymentData), std::ref(aFPData), std::ref(aPSData))))
{
return false;
}

if (result)
foreach (int field, FiscalTotals)
{
foreach (int field, FiscalTotals)
if (!aFPData.value(field).toInt())
{
if (!aFPData.value(field).toInt())
{
aFPData.remove(field);
}
aFPData.remove(field);
}
}

EPayOffTypes::Enum payOffType = aPaymentData.back ? EPayOffTypes::DebitBack : EPayOffTypes::Debit;

aFPData.insert(FiscalFields::FDName, CFR::CashFDName);
aFPData.insert(FiscalFields::PayOffType, CFR::PayOffTypes[payOffType]);
aFPData.insert(FiscalFields::TaxSystem, CFR::Taxations[char(paymentData.taxation)]);
aFPData.insert(FiscalFields::SerialFSNumber, mFSSerialNumber);
aFPData.insert(FiscalFields::INN, mINN);
aFPData.insert(FiscalFields::RNM, mRNM);
aFPData.insert(FiscalFields::SerialFRNumber, mSerial);
aFPData.insert(FiscalFields::FTSURL, getConfigParameter(CHardware::FiscalFields::FTSURL));
aFPData.insert(FiscalFields::OFDURL, getConfigParameter(CHardware::FiscalFields::OFDURL));
aFPData.insert(FiscalFields::OFDName, getConfigParameter(CHardware::FiscalFields::OFDName));
aFPData.insert(FiscalFields::LegalOwner, getConfigParameter(CHardware::FiscalFields::LegalOwner));
aFPData.insert(FiscalFields::PayOffAddress, getConfigParameter(CHardware::FiscalFields::PayOffAddress));
aFPData.insert(FiscalFields::PayOffPlace, getConfigParameter(CHardware::FiscalFields::PayOffPlace));

if (paymentData.agentFlag != EAgentFlags::None)
{
aFPData.insert(FiscalFields::AgentFlag, CFR::AgentFlags[char(paymentData.taxation)]);
}
EPayOffTypes::Enum payOffType = aPaymentData.back ? EPayOffTypes::DebitBack : EPayOffTypes::Debit;

if (containsDeviceParameter(CDeviceData::FR::AutomaticNumber))
{
aFPData.insert(FiscalFields::AutomaticNumber, getDeviceParameter(CDeviceData::FR::AutomaticNumber));
}
aFPData.insert(FiscalFields::FDName, CFR::FDName);
aFPData.insert(FiscalFields::PayOffType, CFR::PayOffTypes[payOffType]);
aFPData.insert(FiscalFields::TaxSystem, CFR::Taxations[char(paymentData.taxation)]);
aFPData.insert(FiscalFields::SerialFSNumber, mFSSerialNumber);
aFPData.insert(FiscalFields::INN, mINN);
aFPData.insert(FiscalFields::RNM, mRNM);
aFPData.insert(FiscalFields::SerialFRNumber, mSerial);
aFPData.insert(FiscalFields::FTSURL, getConfigParameter(CHardware::FiscalFields::FTSURL));
aFPData.insert(FiscalFields::OFDURL, getConfigParameter(CHardware::FiscalFields::OFDURL));
aFPData.insert(FiscalFields::OFDName, getConfigParameter(CHardware::FiscalFields::OFDName));
aFPData.insert(FiscalFields::LegalOwner, getConfigParameter(CHardware::FiscalFields::LegalOwner));
aFPData.insert(FiscalFields::PayOffAddress, getConfigParameter(CHardware::FiscalFields::PayOffAddress));
aFPData.insert(FiscalFields::PayOffPlace, getConfigParameter(CHardware::FiscalFields::PayOffPlace));

int sessionNumber = getSessionNumber();
if (paymentData.agentFlag != EAgentFlags::None)
{
aFPData.insert(FiscalFields::AgentFlag, CFR::AgentFlags[char(paymentData.taxation)]);
}

if (sessionNumber)
{
aFPData.insert(FiscalFields::SessionNumber, sessionNumber);
}
if (containsDeviceParameter(CDeviceData::FR::AutomaticNumber))
{
aFPData.insert(FiscalFields::AutomaticNumber, getDeviceParameter(CDeviceData::FR::AutomaticNumber));
}

int sessionNumber = getSessionNumber();

if (sessionNumber)
{
aFPData.insert(FiscalFields::SessionNumber, sessionNumber);
}

QByteArray FDSignData = aFPData.value(FiscalFields::FDSign).toByteArray();
qulonglong FDSign = FDSignData.right(4).toHex().toULongLong(0, 16);
QString FDSignTextData = QString("%1").arg(FDSign, CFR::FDSignSize, 10, QChar(ASCII::Zero));
aFPData.insert(FiscalFields::FDSign, FDSignTextData);
QByteArray FDSignData = aFPData.value(FiscalFields::FDSign).toByteArray();
qulonglong FDSign = FDSignData.right(4).toHex().toULongLong(0, 16);
QString FDSignTextData = QString("%1").arg(FDSign, CFR::FDSignSize, 10, QChar(ASCII::Zero));
aFPData.insert(FiscalFields::FDSign, FDSignTextData);

QDateTime dateTime = aFPData.value(FiscalFields::FDDateTime).toDateTime();
QDateTime dateTime = aFPData.value(FiscalFields::FDDateTime).toDateTime();

if (!dateTime.isValid())
if (!dateTime.isValid())
{
dateTime = getDateTime();
}

aFPData.insert(FiscalFields::FDDateTime, dateTime.toString(CFR::DateTimeShortLogFormat));

for (int i = 0; i < mOperationModes.size(); ++i)
{
CFR::OperationModes::SData modeData = CFR::OperationModes::Data[mOperationModes[i]];

if (modeData.field)
{
dateTime = getDateTime();
aFPData.insert(modeData.field, modeData.description);
}

aFPData.insert(FiscalFields::FDDateTime, dateTime.toString(CFR::DateTimeShortLogFormat));
}

return result;
if (getConfigParameter(CHardware::FiscalFields::LotteryMode, 0).toInt()) aFPData.insert(FiscalFields::LotteryMode, CFR::LotteryMode);
if (getConfigParameter(CHardware::FiscalFields::GamblingMode, 0).toInt()) aFPData.insert(FiscalFields::GamblingMode, CFR::GamblingMode);
if (getConfigParameter(CHardware::FiscalFields::ExcisableUnitMode, 0).toInt()) aFPData.insert(FiscalFields::ExcisableUnitMode, CFR::ExcisableUnitMode);

return true;
}

//--------------------------------------------------------------------------------
@@ -991,9 +1046,9 @@ bool FRBase<T>::performEncashment(const QStringList & aReceipt, double aAmount)

//--------------------------------------------------------------------------------
template <class T>
bool FRBase<T>::isSessionOpened()
ESessionState::Enum FRBase<T>::getSessionState()
{
return mSessionOpened;
return ESessionState::Error;
}

//--------------------------------------------------------------------------------
@@ -1032,14 +1087,21 @@ bool FRBase<T>::processStatus(TStatusCodes & aStatusCodes)
aStatusCodes.insert(FRStatusCode::Warning::FFDFS);
}

if (mFSError) aStatusCodes.insert(FRStatusCode::Error::FS);
if (mOFDDataError) aStatusCodes.insert(FRStatusCode::Warning::OFDData);
if (mFSError)
{
aStatusCodes.insert(FRStatusCode::Error::FS);
}

if (mOFDDataError && !mOperationModes.contains(EOperationModes::Autonomous))
{
aStatusCodes.insert(FRStatusCode::Warning::OFDData);
}

if (containsConfigParameter(CHardwareSDK::FR::DealerTaxation))
{
char dealerTaxation = char(getConfigParameter(CHardwareSDK::FR::DealerTaxation).toInt());

if ((dealerTaxation != ETaxations::None) && !mTaxations.isEmpty() && !mTaxations.contains(dealerTaxation))
if (!mTaxations.isEmpty() && !mTaxations.contains(dealerTaxation))
{
int taxationStatus = (mTaxations.size() == 1) ? FRStatusCode::Warning::WrongTaxation : FRStatusCode::Error::WrongTaxation;
aStatusCodes.insert(taxationStatus);
@@ -1050,7 +1112,7 @@ bool FRBase<T>::processStatus(TStatusCodes & aStatusCodes)
{
char dealerAgentFlag = char(getConfigParameter(CHardwareSDK::FR::DealerAgentFlag).toInt());

if ((dealerAgentFlag != EAgentFlags::None) && !mAgentFlags.isEmpty() && !mAgentFlags.contains(dealerAgentFlag))
if (!mAgentFlags.isEmpty() && !mAgentFlags.contains(dealerAgentFlag))
{
int agentFlagStatus = (mAgentFlags.size() == 1) ? FRStatusCode::Warning::WrongAgentFlag : FRStatusCode::Error::WrongAgentFlag;
aStatusCodes.insert(agentFlagStatus);


+ 10
- 4
3.0/src/modules/Hardware/FR/src/Base/FRBase.h View File

@@ -56,7 +56,7 @@ public:
virtual bool printEncashment(const QStringList & aReceipt, double aAmount);

/// Открыта ли сессия.
virtual bool isSessionOpened();
virtual SDK::Driver::ESessionState::Enum getSessionState();

/// Находится ли в фискальном режиме.
virtual bool isFiscal() const;
@@ -122,6 +122,15 @@ protected:
/// Получить массив байтов TLV-структуры для установки тега VLN-типа.
QByteArray getDigitTLVData(qulonglong aValue);

/// Проверить Z-отчет по таймеру.
void checkZReportOnTimer();

/// Выполнить Z-отчет.
virtual void onExecZReport();

/// Выполнить Z-отчет.
virtual bool execZReport(bool /*aAuto*/) { return false; }

/// Печать Z-отчета.
virtual bool performZReport(bool aPrintDeferredReports) = 0;

@@ -188,9 +197,6 @@ protected:
/// Глобальная ошибка принтерной части части ФР, печать невозможна.
bool mPrinterCollapse;

/// Открыта ли сессия.
bool mSessionOpened;

/// Признак фискализированности ККМ.
bool mFiscalized;



+ 10
- 5
3.0/src/modules/Hardware/FR/src/Kasbi/KasbiFRBase.cpp View File

@@ -422,17 +422,22 @@ bool KasbiFRBase::getFSData(CKasbiFR::SFSData & aData)
}

//--------------------------------------------------------------------------------
bool KasbiFRBase::isSessionOpened()
ESessionState::Enum KasbiFRBase::getSessionState()
{
CKasbiFR::SFSData data;

return !getFSData(data) || data.sessionOpened;
if (!getFSData(data))
{
return ESessionState::Error;
}

return data.sessionOpened ? ESessionState::Opened : ESessionState::Closed;
}

//--------------------------------------------------------------------------------
bool KasbiFRBase::openSession()
{
if (isSessionOpened())
if (getSessionState() == ESessionState::Opened)
{
toLog(LogLevel::Warning, mDeviceName + ": Session is opened already");
return true;
@@ -460,7 +465,7 @@ bool KasbiFRBase::execZReport(bool aAuto)

toLog(LogLevel::Normal, mDeviceName + QString(": Begin processing %1Z-report").arg(aAuto ? "auto-" : ""));

if (!isSessionOpened())
if (getSessionState() == ESessionState::Closed)
{
toLog(LogLevel::Error, mDeviceName + QString(": Session is closed, exit!"));
return false;
@@ -505,7 +510,7 @@ bool KasbiFRBase::sale(const SAmountData & aAmountData)
//--------------------------------------------------------------------------------
bool KasbiFRBase::performFiscal(const QStringList & aReceipt, const SPaymentData & aPaymentData, TFiscalPaymentData & aFPData, TComplexFiscalPaymentData & aPSData)
{
if (!isSessionOpened() && !openSession())
if ((getSessionState() == ESessionState::Closed) && !openSession())
{
return false;
}


+ 2
- 2
3.0/src/modules/Hardware/FR/src/Kasbi/KasbiFRBase.h View File

@@ -57,7 +57,7 @@ protected:
void processDeviceData(const QByteArray & aRegistrationData);

/// Открыта ли смена. Если будет ошибка - по умолчанию открыта.
bool isSessionOpened();
virtual SDK::Driver::ESessionState::Enum getSessionState();

/// Открыт ли документ. Если будет ошибка - по умолчанию закрыт.
bool isDocumentOpened();
@@ -66,7 +66,7 @@ protected:
bool getFSData(CKasbiFR::SFSData & aData);

/// Выполнить Z-отчет.
bool execZReport(bool aAuto);
virtual bool execZReport(bool aAuto);

/// Открыть смену.
bool openSession();


+ 1
- 1
3.0/src/modules/Hardware/FR/src/OPOSMStarTUPK/OPOSMStarTUPK.h View File

@@ -109,7 +109,7 @@ protected:
bool getZBufferSlots(int & aSlots, bool aFilled);

/// Z отчет.
bool execZReport(bool aAuto);
virtual bool execZReport(bool aAuto);

/// Печать отложенных Z отчетов.
bool printDeferredZReports();


+ 16
- 3
3.0/src/modules/Hardware/FR/src/Prim/PrimFRBase.cpp View File

@@ -394,9 +394,6 @@ TResult PrimFRBase::processCommand(char aCommand, const CPrimFR::TData & aComman
return result;
}

ushort state = QString(answerData[2]).toUShort(0, 16);
mSessionOpened = qToBigEndian(state) & CPrimFR::SessionOpenedMask;

if (aAnswer)
{
*aAnswer = answerData;
@@ -446,6 +443,22 @@ TResult PrimFRBase::processCommand(char aCommand, const CPrimFR::TData & aComman
}

//--------------------------------------------------------------------------------
ESessionState::Enum PrimFRBase::getSessionState()
{
CPrimFR::TData answer;

if (!processCommand(CPrimFR::Commands::GetDateTime, &answer))
{
return ESessionState::Error;
}

ushort state = QString(answer[2]).toUShort(0, 16);
bool result = qToBigEndian(state) & CPrimFR::SessionOpenedMask;

return result ? ESessionState::Opened : ESessionState::Closed;
}

//--------------------------------------------------------------------------------
TResult PrimFRBase::checkAnswer(TResult aResult, const QByteArray & aAnswer, CPrimFR::TData & aAnswerData)
{
if (aResult == CommandResult::NoAnswer)


+ 4
- 4
3.0/src/modules/Hardware/FR/src/Prim/PrimFRBase.h View File

@@ -56,7 +56,7 @@ protected:
virtual bool performZReport(bool aPrintDeferredReports);

/// Печать Z отчета.
bool execZReport(bool aAuto);
virtual bool execZReport(bool aAuto);

/// Выполнить Z-отчет.
virtual TResult doZReport(bool aAuto);
@@ -134,13 +134,13 @@ protected:
/// Распарсить реал-тайм статусы принтера по реал-тайм коду.
TStatusCodes parseRTStatus(int aCommand, char aAnswer);

/// Узнать, открыта ли смена.
virtual SDK::Driver::ESessionState::Enum getSessionState();

/// Получить ASCII-представление 1-байтного целочисленного числа.
inline QString int2String(int aValue);
inline QByteArray int2ByteArray(int aValue);

/// Таймер для выполнения отложенных действий.
QTimer mDeferredAction;

/// Режим работы.
EFRMode::Enum mMode;



+ 1
- 0
3.0/src/modules/Hardware/FR/src/Prim/PrimFRConstants.h View File

@@ -161,6 +161,7 @@ namespace CPrimFR
const char EReport = '\x34';
const char EDocument = '\x3E';
const char GetLastCVCNumber = '\x3F';
const char GetDateTime = '\x43';
const char SetMoneyBoxSettings = '\x44';
const char GetMoneyBoxSettings = '\x45';
const char SetFDTypeNames = '\x47';


+ 16
- 1
3.0/src/modules/Hardware/FR/src/Shtrih/Base/ProtoShtrihFR.cpp View File

@@ -1021,7 +1021,6 @@ TResult ProtoShtrihFR<T>::getLongStatus(QByteArray & aAnswer)
{
mMode = aAnswer[15] & CShtrihFR::InnerModes::Mask;
mSubmode = aAnswer[16];
mSessionOpened = (mMode == CShtrihFR::InnerModes::SessionOpened) || (mMode == CShtrihFR::InnerModes::NeedCloseSession);
}

return result;
@@ -1029,6 +1028,22 @@ TResult ProtoShtrihFR<T>::getLongStatus(QByteArray & aAnswer)

//--------------------------------------------------------------------------------
template<class T>
ESessionState::Enum ProtoShtrihFR<T>::getSessionState()
{
QByteArray data;

if (!getLongStatus(data))
{
return ESessionState::Error;
}

bool result = (mMode == CShtrihFR::InnerModes::SessionOpened) || (mMode == CShtrihFR::InnerModes::NeedCloseSession);

return result ? ESessionState::Opened : ESessionState::Closed;
}

//--------------------------------------------------------------------------------
template<class T>
void ProtoShtrihFR<T>::postPollingAction(const TStatusCollection & aNewStatusCollection, const TStatusCollection & aOldStatusCollection)
{
// если нет ошибок и нужно продолжать печать - продолжаем


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

@@ -117,6 +117,9 @@ protected:
/// Отрезка.
virtual bool cut();

/// Узнать, открыта ли смена.
virtual SDK::Driver::ESessionState::Enum getSessionState();

/// Установить значение в системной таблице.
bool setFRParameter(const CShtrihFR::FRParameters::SData & aData, const QVariant & aValue, char aSeries = 1);



+ 12
- 2
3.0/src/modules/Hardware/FR/src/Shtrih/Online/ShtrihFROnlineConstants.h View File

@@ -37,6 +37,9 @@ namespace CShtrihOnlineFR
/// Печатать все реквизиты пользователя (название юр. лица, адрес и место расчетов).
const int PrintFullUserData = 7;

/// Ряд кассира по умолчанию (сисадмин).
const int CashierSeries = 30;

/// Параметры автообновления.
namespace FirmwareUpdating
{
@@ -46,11 +49,16 @@ namespace CShtrihOnlineFR
const int Single = 0; /// Многократное обновление.
}

/// Типы фискальных чеков.
namespace DocumentTypes
{
const char Sale = '\x01'; /// Продажа.
const char SaleBack = '\x02'; /// Возврат продажи.
}

/// Параметры ФР.
namespace FRParameters
{
const int CashierSeries = 30; /// Ряд кассира по умолчанию (сисадмин).

using namespace CShtrihFR::FRParameters;

const SData Cashier = SData( 2, 2); /// Кассир по умолчанию (сисадмин).
@@ -59,6 +67,7 @@ namespace CShtrihOnlineFR
const SData PrintOFDData = SData(10, 17); /// Печатать данные ОФД.
const SData PrintUserData = SData(12, 17); /// Печатать реквизитов [суб]дилера.
const SData FFDFR = SData(17, 17); /// ФФД ФР.
const SData PrintCustomFields = SData(25, 17); /// Автопечать тегов, вводимых на платеже.
const SData SerialNumber = SData( 1, 18); /// Серийный номер.
const SData INN = SData( 2, 18); /// ИНН.
const SData RNM = SData( 3, 18); /// РНМ.
@@ -69,6 +78,7 @@ namespace CShtrihOnlineFR
const SData OFDURL = SData(11, 18); /// Aдрес сайта ОФД.
const SData FTSURL = SData(13, 18); /// Адрес сайта ФНС.
const SData PayOffPlace = SData(14, 18); /// Место расчетов.
const SData AgentFlag = SData(16, 18); /// Признак агента.
const SData OFDAddress = SData( 1, 19); /// Aдрес ОФД.
const SData OFDPort = SData( 2, 19); /// Порт ОФД.
const SData AutomaticNumber = SData( 1, 24); /// Номер автомата.


+ 55
- 7
3.0/src/modules/Hardware/FR/src/Shtrih/Online/ShtrihOnlineFRBase.cpp View File

@@ -72,6 +72,9 @@ bool ShtrihOnlineFRBase<T>::updateParameters()
// Печатать все реквизиты пользователя в чеках
setFRParameter(CShtrihOnlineFR::FRParameters::PrintUserData, CShtrihOnlineFR::PrintFullUserData);

// Печатать фискальные теги, вводимые на платеже
setFRParameter(CShtrihOnlineFR::FRParameters::PrintCustomFields, true);

if (mOperatorPresence)
{
if (!containsConfigParameter(CHardware::FiscalFields::Cashier))
@@ -82,7 +85,7 @@ bool ShtrihOnlineFRBase<T>::updateParameters()

QString cashier = getConfigParameter(CHardware::FiscalFields::Cashier).toString();

if (!setFRParameter(CShtrihOnlineFR::FRParameters::Cashier, cashier, CShtrihOnlineFR::FRParameters::CashierSeries))
if (!setFRParameter(CShtrihOnlineFR::FRParameters::Cashier, cashier, CShtrihOnlineFR::CashierSeries))
{
toLog(LogLevel::Error, QString("%1: Failed to set cashier fiscal field (%2)").arg(mDeviceName).arg(cashier));
return false;
@@ -91,13 +94,36 @@ bool ShtrihOnlineFRBase<T>::updateParameters()

QByteArray data;

if (!processCommand(CShtrihOnlineFR::Commands::FS::GetFiscalizationResume, &data) || (data.size() <= 41))
if (!processCommand(CShtrihOnlineFR::Commands::FS::GetFiscalizationResume, &data) || (data.size() <= 46))
{
toLog(LogLevel::Error, mDeviceName + ": Failed to get fiscalization resume");
return false;
}

return checkTaxationData(data[40]) && checkOperationModes(data[41]);
if (!checkTaxationData(data[40]) || !checkOperationModes(data[41]))
{
return false;
}

bool result = false;

if (processCommand(CShtrihOnlineFR::Commands::FS::StartFiscalTLVData, data.mid(43, 4)))
{
CFR::STLV TLV;

while (processCommand(CShtrihOnlineFR::Commands::FS::GetFiscalTLVData, &data))
{
if (parseTLV(data.mid(3), TLV))
{
if (TLV.field == FiscalFields::AgentFlagsRegistered)
{
result = checkAgentFlags(TLV.data[0]);
}
}
}
}

return result;
}

//---------------------------------------------------------------------------
@@ -230,9 +256,15 @@ void ShtrihOnlineFRBase<T>::processDeviceData()
if (getFRParameter(RNM, data)) mRNM = CFR::RNMToString(data);

#define SET_LCONFIG_FISCAL_FIELD(aName) QString aName##Log = QString("fiscal tag %1 (%2)").arg(FiscalFields::aName).arg(CHardware::FiscalFields::aName); \
if (getFRParameter(aName, data)) { setLConfigParameter(CHardware::FiscalFields::aName, data); QString value = getConfigParameter(CHardware::FiscalFields::aName, data).toString(); \
toLog(LogLevel::Normal, QString("%1: Set %2 = \"%3\" to config data").arg(mDeviceName).arg(aName##Log).arg(value)); } \
else toLog(LogLevel::Error, QString("%1: Failed to set %2 to config data").arg(mDeviceName).arg(aName##Log));
if (getFRParameter(aName, data)) { setLConfigParameter(CHardware::FiscalFields::aName, data); \
QString value = getConfigParameter(CHardware::FiscalFields::aName, data).toString(); \
toLog(LogLevel::Normal, QString("%1: Add %2 = \"%3\" to config data").arg(mDeviceName).arg(aName##Log).arg(value)); } \
else toLog(LogLevel::Error, QString("%1: Failed to add %2 to config data").arg(mDeviceName).arg(aName##Log));

#define SET_BCONFIG_FISCAL_FIELD(aName) QString aName##Log = QString("fiscal tag %1 (%2)").arg(FiscalFields::aName).arg(CHardware::FiscalFields::aName); \
if (getFRParameter(aName, data)) { char value = data[0]; setConfigParameter(CHardware::FiscalFields::aName, value); \
toLog(LogLevel::Normal, QString("%1: Add %2 = %3 to config data").arg(mDeviceName).arg(aName##Log).arg(value)); } \
else toLog(LogLevel::Error, QString("%1: Failed to add %2 to config data").arg(mDeviceName).arg(aName##Log));

SET_LCONFIG_FISCAL_FIELD(FTSURL);
SET_LCONFIG_FISCAL_FIELD(OFDURL);
@@ -241,6 +273,12 @@ void ShtrihOnlineFRBase<T>::processDeviceData()
SET_LCONFIG_FISCAL_FIELD(PayOffAddress);
SET_LCONFIG_FISCAL_FIELD(PayOffPlace);

/*
SET_BCONFIG_FISCAL_FIELD(LotteryMode);
SET_BCONFIG_FISCAL_FIELD(GamblingMode);
SET_BCONFIG_FISCAL_FIELD(ExcisableUnitMode);
*/

if (getFRParameter(SD::Status, data))
{
if (data[0] == CShtrihOnlineFR::SDNotConnected)
@@ -377,7 +415,7 @@ bool ShtrihOnlineFRBase<T>::sale(const SAmountData & aAmountData, bool aBack)
return ShtrihFRBase<T>::sale(aAmountData, aBack);
}

char documentType = aBack ? CShtrihFR::DocumentTypes::SaleBack : CShtrihFR::DocumentTypes::Sale;
char documentType = aBack ? CShtrihOnlineFR::DocumentTypes::SaleBack : CShtrihOnlineFR::DocumentTypes::Sale;
char taxIndex = char(mTaxData[aAmountData.VAT].group);
char section = (aAmountData.section == -1) ? CShtrihFR::SectionNumber : char(aAmountData.section);
QByteArray sum = getHexReverted(aAmountData.sum, 5, 2);
@@ -417,6 +455,16 @@ bool ShtrihOnlineFRBase<T>::performFiscal(const QStringList & aReceipt, const SP
return false;
}

/*
char agentFlag = char(aPaymentData.agentFlag);

if ((agentFlag != EAgentFlags::None) && (mAgentFlags.size() != 1) && !setFRParameter(CShtrihOnlineFR::FRParameters::AgentFlag, agentFlag))
{
toLog(LogLevel::Error, QString("%1: Failed to set agent flag %2 (%3)").arg(mDeviceName).arg(ProtocolUtils::toHexLog(agentFlag)).arg(CFR::AgentFlags[agentFlag]));
return false;
}
*/

bool result = ShtrihFRBase<T>::performFiscal(aReceipt, aPaymentData, aFPData, aPSData);

if (result)


+ 7
- 4
3.0/src/modules/Hardware/FR/src/Spark/SparkFR.cpp View File

@@ -958,7 +958,7 @@ bool SparkFR::isSessionExpired()
{
TKKMInfoData data;

return isSessionOpened() && getKKMData(data) && mSessionOpeningDT.daysTo(parseDateTime(data));
return (getSessionState() == ESessionState::Opened) && getKKMData(data) && mSessionOpeningDT.daysTo(parseDateTime(data));
}

//--------------------------------------------------------------------------------
@@ -970,9 +970,12 @@ int SparkFR::getLastDocumentNumber()
}

//--------------------------------------------------------------------------------
bool SparkFR::isSessionOpened()
ESessionState::Enum SparkFR::getSessionState()
{
return mSessionOpeningDT != CSparkFR::ClosedSession;
// Т.е. если дата и время начала смены валидны, то она открыта. Возможно - особенность нефискализированного аппарата.
bool result = mSessionOpeningDT != CSparkFR::ClosedSession;

return result ? ESessionState::Opened : ESessionState::Closed;
}

//--------------------------------------------------------------------------------
@@ -980,7 +983,7 @@ bool SparkFR::execZReport()
{
toLog(LogLevel::Normal, QString("%1: Begin processing %2-report").arg(mDeviceName).arg(CSparkFR::ZReport));

if (!isSessionOpened())
if (getSessionState() == ESessionState::Closed)
{
toLog(LogLevel::Error, mDeviceName + ": Session is closed, exit!");
return false;


+ 2
- 2
3.0/src/modules/Hardware/FR/src/Spark/SparkFR.h View File

@@ -89,10 +89,10 @@ protected:
bool processAnswer(char aError);

/// Выполнить Z-отчет.
bool execZReport();
virtual bool execZReport();

/// Узнать, открыта ли смена.
bool isSessionOpened();
virtual SDK::Driver::ESessionState::Enum getSessionState();

/// Получить номер последнего фискального документа.
int getLastDocumentNumber();


+ 1
- 1
3.0/src/modules/Hardware/IOPorts/src/COM/windows/AsyncSerialPort.cpp View File

@@ -126,7 +126,7 @@ void AsyncSerialPort::setDeviceConfiguration(const QVariantMap & aConfiguration)
mType = EPortTypes::COMEmulator;
}

if (!mExist)
if (!mExist && !mSystemName.isEmpty())
{
checkExistence();
}


+ 13
- 1
3.0/src/modules/Hardware/Printers/src/POSPrinters/Common/POSPrinter.cpp View File

@@ -429,7 +429,19 @@ bool POSPrinter::printImage(const QImage & aImage, const Tags::TTypes & aTags)
request.append((const char *)aImage.scanLine(i), widthInBytes);
}

return mIOPort->write(request);
if (!mIOPort->write(request))
{
return false;
}

//TODO: под рефакторинг.
//Причины необходимости задержки ясны не до конца, т.к. задержка начинает работать после фактической печати картинки.
//Задержка нужна тем большая, чем больше картинок печатается одновременно или почти одновременно, через какое-то количество строк текста.
int pause = qMin(int(double(request.size()) / 2), 5000);
toLog(LogLevel::Debug, mDeviceName + QString(": size = %1, pause = %2").arg(request.size()).arg(pause));
SleepHelper::msleep(pause);

return true;
}

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

+ 1
- 0
3.0/src/modules/Hardware/Printers/src/POSPrinters/CustomPrinters.cpp View File

@@ -7,6 +7,7 @@
#include <QtCore/qmath.h>
#include <Common/QtHeadersEnd.h>

// Project
#include "CustomPrinters.h"

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


+ 2
- 0
3.0/src/modules/Packer/Packer.qbs View File

@@ -8,6 +8,8 @@ StaticLibrary {

Depends { name: "Core" }

cpp.includePaths: [ Qt.core.incPath + "/../src/3rdparty/zlib" ]
files: [ "src/*.cpp", "src/*.h" ]
}


+ 3
- 6
3.0/src/modules/Packer/msvc/Packer.vcxproj View File

@@ -57,7 +57,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WINVER=0x0502;_WIN32_WINNT=0x0502;UNICODE;WIN32;QT_DLL;QT_CORE_LIB;SHEDULER_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(THIRDPARTY_DIR);$(THIRDPARTY_DIR)\boost;$(TC_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\src\3rdparty\zlib;$(THIRDPARTY_DIR);$(THIRDPARTY_DIR)\boost;$(TC_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Disabled</Optimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -73,7 +73,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WINVER=0x0502;_WIN32_WINNT=0x0502;UNICODE;WIN32;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;SHEDULER_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(THIRDPARTY_DIR);$(THIRDPARTY_DIR)\boost;$(TC_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\src\3rdparty\zlib;$(THIRDPARTY_DIR);$(THIRDPARTY_DIR)\boost;$(TC_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>
</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -89,7 +89,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithDebugInfo|Win32'">
<ClCompile>
<PreprocessorDefinitions>WINVER=0x0502;_WIN32_WINNT=0x0502;UNICODE;WIN32;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;SHEDULER_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(THIRDPARTY_DIR);$(THIRDPARTY_DIR)\boost;$(TC_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\src\3rdparty\zlib;$(THIRDPARTY_DIR);$(THIRDPARTY_DIR)\boost;$(TC_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
@@ -128,9 +128,6 @@
</Command>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\Crc32.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>


+ 0
- 5
3.0/src/modules/Packer/msvc/Packer.vcxproj.filters View File

@@ -36,9 +36,4 @@
<Filter>Source Files</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\Crc32.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

+ 0
- 101
3.0/src/modules/Packer/src/Crc32.h View File

@@ -1,101 +0,0 @@
#ifndef CRC32_H
#define CRC32_H

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

class Crc32
{
private:
quint32 mCrcTable[256];
QMap<int, quint32> instances;

public:
Crc32()
{
quint32 crc;

// initialize CRC table
for (int i = 0; i < 256; i++)
{
crc = i;
for (int j = 0; j < 8; j++)
crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320UL : crc >> 1;

mCrcTable[i] = crc;
}
}

quint32 fromFile(const QString & aFileName)
{
quint32 crc;
QFile file;

char buffer[16000];
int len, i;

crc = 0xFFFFFFFFUL;

file.setFileName(aFileName);
if (file.open(QIODevice::ReadOnly))
{
while (!file.atEnd())
{
len = file.read(buffer, 16000);
for (i = 0; i < len; i++)
crc = mCrcTable[(crc ^ buffer[i]) & 0xFF] ^ (crc >> 8);
}

file.close();
}

return crc ^ 0xFFFFFFFFUL;
}
quint32 fromByteArray(const QByteArray & aBuffer)
{
quint32 crc;

crc = 0xFFFFFFFFUL;

for (int i = 0; i < aBuffer.size(); i++)
crc = mCrcTable[(crc ^ aBuffer[i]) & 0xFF] ^ (crc >> 8);

return crc ^ 0xFFFFFFFFUL;
}

void initInstance(int i)
{
instances[i] = 0xFFFFFFFFUL;
}

void pushData(int i, char * aData, int aLen)
{
quint32 crc = instances[i];
if (crc)
{
for (int j = 0; j < aLen; j++)
crc = mCrcTable[(crc ^ aData[j]) & 0xFF] ^ (crc >> 8);

instances[i] = crc;
}
}

quint32 releaseInstance(int i)
{
quint32 crc32 = instances[i];
if (crc32) {
instances.remove(i);
return crc32 ^ 0xFFFFFFFFUL;
}
else {
return 0;
}
}
};

#endif // CRC32_H

+ 216
- 19
3.0/src/modules/Packer/src/Packer.cpp View File

@@ -8,6 +8,7 @@
#include <QtCore/QProcess>
#include <QtCore/QTextCodec>
#include <QtCore/QCryptographicHash>
#include <QtCore/QDateTime>
#include <Common/QtHeadersEnd.h>

// Modules
@@ -15,11 +16,18 @@

// Project
#include "Packer.h"
#include "Crc32.h"

// Qt 3rdparty
#include <zlib.h>

//------------------------------------------------------------------------------
namespace CPacker
{
const int DefaultTimeout = 300 * 1000; // таймаут распаковки/запаковки в мс.
// ported from https://stackoverflow.com/questions/2690328/qt-quncompress-gzip-data
const int GZIP_WINDOWS_BIT = 15 + 16;
const int GZIP_CHUNK_SIZE = 32 * 1024;
};

//------------------------------------------------------------------------------
@@ -58,32 +66,221 @@ void Packer::setUpdateMode(bool aUpdateMode)
}

//---------------------------------------------------------------------------
QByteArray Packer::compressToGZ(const QByteArray & aInBuffer, const QString & aFileName, int aLevel)
bool Packer::gzipCompress(const QByteArray & aInBuffer, const QString & aFileName, QByteArray & aOutBuffer, int aLevel)
{
const unsigned char gzipheader[10] = { 0x1f,0x8b,8,0,0,0,0,0,2,0 };
unsigned long crc = Crc32().fromByteArray(aInBuffer);
quint32 len = aInBuffer.size();
// Prepare output
aOutBuffer.clear();

QByteArray out = qCompress(aInBuffer, aLevel);
out.remove(0, 4); //qt makes first 4 bytes size of zipped data, i don't need it for gzip
out.remove(0, 2); // Remove Zlib header
out.chop(4); // Remove Zlib trailer
// Is there something to do?
if (aInBuffer.length())
{
// Declare vars
int flush = 0;

QByteArray gzBufer = QByteArray((const char *)gzipheader, 10);
// Prepare deflater status
z_stream strm;
memset(&strm, 0, sizeof(strm));

if (!aFileName.isEmpty())
{
gzBufer[3] = 8;
// Initialize deflater
int ret = deflateInit2(&strm, qMax(-1, qMin(9, aLevel)), Z_DEFLATED, CPacker::GZIP_WINDOWS_BIT, 8, Z_DEFAULT_STRATEGY);

if (ret != Z_OK)
{
return false;
}

gz_header header;
memset(&header, 0, sizeof(header));
QByteArray nameBuffer = aFileName.toLatin1();
nameBuffer.append('\0');
header.name = (Bytef *)nameBuffer.constData();
header.name_max = nameBuffer.size();
header.time = QDateTime::currentDateTime().toTime_t();

ret = deflateSetHeader(&strm, &header);
if (ret != Z_OK)
{
return false;
}

// Prepare output
aOutBuffer.clear();

// Extract pointer to input data
const char * input_data = aInBuffer.data();
int input_data_left = aInBuffer.length();

// Compress data until available
do
{
// Determine current chunk size
int chunk_size = qMin(CPacker::GZIP_CHUNK_SIZE, input_data_left);

// Set deflater references
strm.next_in = (unsigned char*)input_data;
strm.avail_in = chunk_size;

// Update interval variables
input_data += chunk_size;
input_data_left -= chunk_size;

// Determine if it is the last chunk
flush = (input_data_left <= 0 ? Z_FINISH : Z_NO_FLUSH);

// Deflate chunk and cumulate output
do
{
// Declare vars
char out[CPacker::GZIP_CHUNK_SIZE];

// Set deflater references
strm.next_out = (unsigned char*)out;
strm.avail_out = CPacker::GZIP_CHUNK_SIZE;

// Try to deflate chunk
ret = deflate(&strm, flush);

// Check errors
if (ret == Z_STREAM_ERROR)
{
// Clean-up
deflateEnd(&strm);

// Return
return false;
}

// Determine compressed size
int have = (CPacker::GZIP_CHUNK_SIZE - strm.avail_out);

gzBufer.append(aFileName.toLatin1());
gzBufer.append("\0", 1);
// Cumulate result
if (have > 0)
{
aOutBuffer.append((char*)out, have);
}
} while (strm.avail_out == 0);

} while (flush != Z_FINISH);

// Clean-up
deflateEnd(&strm);

// Return
return (ret == Z_STREAM_END);
}

gzBufer.append(out);
gzBufer.append((const char *)&crc, 4);
gzBufer.append((const char *)&len, 4);
return true;
}

//------------------------------------------------------------------------------
bool Packer::gzipUncompress(const QByteArray & aInBuffer, QString & aFileName, QByteArray & aOutBuffer)
{
// Prepare output
aFileName.clear();
aOutBuffer.clear();

// Is there something to do?
if (aInBuffer.length() > 0)
{
// Prepare inflater status
z_stream strm;
memset(&strm, 0, sizeof(strm));

// Initialize inflater
int ret = inflateInit2(&strm, CPacker::GZIP_WINDOWS_BIT);

if (ret != Z_OK)
{
return false;
}

gz_header header;
memset(&header, 0, sizeof(header));
QByteArray nameBuffer;
nameBuffer.fill('\0', 256);
header.name = (Bytef *)nameBuffer.data();
header.name_max = nameBuffer.size();

ret = inflateGetHeader(&strm, &header);
if (ret != Z_OK)
{
return false;
}

// Extract pointer to aInBuffer data
const char * input_data = aInBuffer.data();
int input_data_left = aInBuffer.length();

// Decompress data until available
do
{
// Determine current chunk size
int chunk_size = qMin(CPacker::GZIP_CHUNK_SIZE, input_data_left);

// Check for termination
if (chunk_size <= 0)
{
break;