@@ -54,8 +54,13 @@ | |||
<file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/plugins/cyberchange.dll" target="plugins/plugins/cyberchange.dll"/> | |||
<!-- Uniteller plugin --> | |||
<!-- <option target="user/user/plugins/uniteller.ini" key="PaymentProcessor.ChargeProvider.UnitellerChargeProvider.configuration_singleton/uniteller_runtime_path" value="C:/EFTPOS_3.0" /> --> | |||
<!-- <file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/plugins/uniteller.dll" target="plugins/plugins/uniteller.dll"/> --> | |||
<!-- UCS plugin --> | |||
<option target="user/user/plugins/ucs.ini" key="PaymentProcessor.ChargeProvider.UcsChargeProvider.configuration_singleton/ucs_runtime_path" value="C:/UCS/BIN" /> | |||
<file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/plugins/ucs.dll" target="plugins/plugins/ucs.dll"/> | |||
<!-- Драйверы, компонент drivers --> | |||
<file source="{QBS_RESULT_PATH}/plugins/drivers/fr.dll" target="drivers/plugins/drivers/fr.dll"/> | |||
@@ -86,6 +91,7 @@ | |||
<file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/locale/platru_ru.qm" target="locale/plugins/platru_ru.qm"/> | |||
<file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/locale/cyberchange_ru.qm" target="locale/plugins/cyberchange_ru.qm"/> | |||
<!-- <file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/locale/uniteller_ru.qm" target="locale/plugins/uniteller_ru.qm"/> --> | |||
<file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/locale/ucs_ru.qm" target="locale/plugins/ucs_ru.qm"/> --> | |||
<!-- ###################################################################################### --> | |||
@@ -111,6 +117,9 @@ | |||
<!-- Token plugin --> | |||
<file if="{TC_USE_TOKEN} && {CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/plugins/drivers/token.dll" target="drivers/plugins/drivers/token.dll"/> | |||
<!-- Fiscal client plugin --> | |||
<file if="{CYBERPLAT_BUILD}" source="{QBS_RESULT_PATH}/plugins/fiscal_client.dll" target="plugins/plugins/fiscal_client.dll"/> | |||
<!-- ###################################################################################### --> | |||
@@ -1,6 +1,7 @@ | |||
import qbs | |||
import qbs.TextFile | |||
import qbs.Environment | |||
import qbs.FileInfo | |||
Project { | |||
qbsSearchPaths: "../scripts/build/qbs" | |||
@@ -14,15 +15,16 @@ Project { | |||
"../tests/tests.qbs" | |||
] | |||
Product { | |||
CppApplication { | |||
name: "Core" | |||
qbsSearchPaths: "../scripts/build/qbs" | |||
type: [ "VersionUpdaterType" ] | |||
Depends { name: "cpp" } | |||
Depends { name: "VersionUpdater" } | |||
// cpp.useCxxPrecompiledHeader: true | |||
cpp.includePaths: [ "includes" ] | |||
files: [ | |||
@@ -45,6 +47,7 @@ Project { | |||
// cpp.warningLevel: "all" | |||
cpp.cLanguageVersion: "c11" | |||
cpp.cxxLanguageVersion: "c++14" | |||
// cpp.useCxxPrecompiledHeader: true | |||
cpp.includePaths: [ | |||
product.buildDirectory + "/includes", | |||
product.sourceDirectory + "/includes" | |||
@@ -59,6 +62,12 @@ Project { | |||
return defList; | |||
} | |||
/* Group { | |||
name: "precompiled headers" | |||
files: { return [ path + "/includes/Common/precompiled_headers.h" ]; } | |||
fileTags: ["cpp_pch_src"] | |||
} */ | |||
Properties { | |||
condition: qbs.toolchain.contains('msvc') | |||
@@ -79,6 +88,6 @@ Project { | |||
cpp.separateDebugInformation: true | |||
} | |||
} | |||
} | |||
} | |||
} | |||
@@ -4,9 +4,6 @@ call %QTDIR%\bin\qtvars.bat | |||
lupdate ..\src -ts "%~3\paymentprocessor_ru.ts" | |||
lrelease "%~3\paymentprocessor_ru.ts" -qm "%~1\%~2_ru.qm" | |||
lupdate ..\src -ts "%~3\paymentprocessor_ru_bankomat.ts" | |||
lrelease "%~3\paymentprocessor_ru_bankomat.ts" -qm "%~1\%~2_ru_bankomat.qm" | |||
lupdate ..\src -ts "%~3\paymentprocessor_en.ts" | |||
lrelease "%~3\paymentprocessor_en.ts" -qm "%~1\%~2_en.qm" | |||
@@ -63,7 +63,7 @@ | |||
</PreBuildEvent> | |||
<ClCompile> | |||
<Optimization>MaxSpeed</Optimization> | |||
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(THIRDPARTY_DIR)\boost;$(THIRDPARTY_DIR)\QtSolutions;$(TC_INCLUDE_DIR);.\GeneratedFiles\$(ProjectName);.\GeneratedFiles\$(ProjectName)\$(Configuration);$(ProjectDir)\..\src;.\..\src\Interface;.\..\src\Interface\FirstSetup;$(THIRDPARTY_DIR)\qntp\include;..\src\System;$(THIRDPARTY_DIR)\zint\backend_qt4;$(THIRDPARTY_DIR)\qBreakpad\handler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(THIRDPARTY_DIR)\boost;$(THIRDPARTY_DIR)\QtSolutions;$(TC_INCLUDE_DIR);.\GeneratedFiles\$(ProjectName);.\GeneratedFiles\$(ProjectName)\$(Configuration);$(ProjectDir)\..\src;.\..\src\Interface;.\..\src\Interface\FirstSetup;$(THIRDPARTY_DIR)\qntp\include;..\src\System;$(THIRDPARTY_DIR)\zint\backend_qt4;$(THIRDPARTY_DIR)\qBreakpad\handler;$(THIRDPARTY_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<PreprocessorDefinitions>WINVER=0x0502;_WIN32_WINNT=0x0502;UNICODE;WIN32;QT_THREAD_SUPPORT;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;_SCL_SECURE_NO_WARNINGS;QT_DLL;QT_SCRIPT_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> | |||
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType> | |||
@@ -107,7 +107,7 @@ | |||
</PreBuildEvent> | |||
<ClCompile> | |||
<Optimization>MaxSpeed</Optimization> | |||
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(THIRDPARTY_DIR)\boost;$(THIRDPARTY_DIR)\QtSolutions;$(TC_INCLUDE_DIR);.\GeneratedFiles\$(ProjectName);.\GeneratedFiles\$(ProjectName)\$(Configuration);$(ProjectDir)\..\src;.\..\src\Interface;.\..\src\Interface\FirstSetup;$(THIRDPARTY_DIR)\qntp\include;..\src\System;$(THIRDPARTY_DIR)\zint\backend_qt4;$(THIRDPARTY_DIR)\qBreakpad\handler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(THIRDPARTY_DIR)\boost;$(THIRDPARTY_DIR)\QtSolutions;$(TC_INCLUDE_DIR);.\GeneratedFiles\$(ProjectName);.\GeneratedFiles\$(ProjectName)\$(Configuration);$(ProjectDir)\..\src;.\..\src\Interface;.\..\src\Interface\FirstSetup;$(THIRDPARTY_DIR)\qntp\include;..\src\System;$(THIRDPARTY_DIR)\zint\backend_qt4;$(THIRDPARTY_DIR)\qBreakpad\handler;$(THIRDPARTY_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<PreprocessorDefinitions>WINVER=0x0502;_WIN32_WINNT=0x0502;UNICODE;WIN32;QT_THREAD_SUPPORT;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;_SCL_SECURE_NO_WARNINGS;QT_DLL;QT_SCRIPT_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> | |||
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType> | |||
@@ -149,7 +149,7 @@ | |||
</PreBuildEvent> | |||
<ClCompile> | |||
<Optimization>Disabled</Optimization> | |||
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(THIRDPARTY_DIR)\boost;$(THIRDPARTY_DIR)\QtSolutions;$(TC_INCLUDE_DIR);.\GeneratedFiles\$(ProjectName);.\GeneratedFiles\$(ProjectName)\$(Configuration);$(ProjectDir)\..\src;.\..\src\Interface;.\..\src\Interface\FirstSetup;$(THIRDPARTY_DIR)\qntp\include;$(THIRDPARTY_DIR)\VisualLeakDetector\include;..\src\System;$(THIRDPARTY_DIR)\zint\backend_qt4;$(THIRDPARTY_DIR)\qBreakpad\handler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(THIRDPARTY_DIR)\boost;$(THIRDPARTY_DIR)\QtSolutions;$(TC_INCLUDE_DIR);.\GeneratedFiles\$(ProjectName);.\GeneratedFiles\$(ProjectName)\$(Configuration);$(ProjectDir)\..\src;.\..\src\Interface;.\..\src\Interface\FirstSetup;$(THIRDPARTY_DIR)\qntp\include;..\src\System;$(THIRDPARTY_DIR)\zint\backend_qt4;$(THIRDPARTY_DIR)\qBreakpad\handler;$(THIRDPARTY_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<PreprocessorDefinitions>WINVER=0x0502;_WIN32_WINNT=0x0502;UNICODE;WIN32;QT_THREAD_SUPPORT;QT_CORE_LIB;_SCL_SECURE_NO_WARNINGS;_LIB;QT_DLL;QT_SCRIPT_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> | |||
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType> | |||
@@ -404,6 +404,7 @@ | |||
<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 -D_SCL_SECURE_NO_WARNINGS -DQT_DLL -DQT_SCRIPT_LIB "-I$(THIRDPARTY_DIR)\boost" "-I$(QTDIR)\include" "-I$(THIRDPARTY_DIR)\QtSolutions" "-I$(TC_INCLUDE_DIR)\." "-I.\GeneratedFiles\$(ProjectName)\." "-I.\GeneratedFiles\$(ProjectName)\$(Configuration)\." "-I$(ProjectDir)\..\src" "-I.\..\src\Interface" "-I.\..\src\Interface\FirstSetup" "-I$(THIRDPARTY_DIR)\qntp\include" "-I.\..\src\System"</Command> | |||
</CustomBuild> | |||
<ClInclude Include="..\src\Services\ServiceCommon.h" /> | |||
<ClInclude Include="..\src\Services\TerminalStatusDescriptions.h" /> | |||
<ClInclude Include="resource.h" /> | |||
<ClInclude Include="..\src\Services\CryptService.h" /> | |||
<ClInclude Include="..\src\Services\DatabaseService.h" /> | |||
@@ -965,10 +966,8 @@ | |||
<None Include="..\src\icons\PaymentProcessor.ico" /> | |||
<None Include="..\src\locale\paymentprocessor_de.ts" /> | |||
<None Include="..\src\locale\paymentprocessor_en.ts" /> | |||
<None Include="..\src\locale\paymentprocessor_en_bankomat.ts" /> | |||
<None Include="..\src\locale\paymentprocessor_kk.ts" /> | |||
<None Include="..\src\locale\paymentprocessor_ru.ts" /> | |||
<None Include="..\src\locale\paymentprocessor_ru_bankomat.ts" /> | |||
<None Include="..\src\SplashScreen\blocked.png"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | |||
@@ -1041,7 +1040,7 @@ | |||
</ImportGroup> | |||
<ProjectExtensions> | |||
<VisualStudio> | |||
<UserProperties MocDir=".\GeneratedFiles\$(ProjectName)\$(ConfigurationName)" QtVersion_x0020_Win32="$(DefaultQtVersion)" RccDir=".\GeneratedFiles\$(ProjectName)" UicDir=".\GeneratedFiles\$(ProjectName)" Qt5Version_x0020_Win32="$(DefaultQtVersion)" /> | |||
<UserProperties MocDir=".\GeneratedFiles\$(ProjectName)\$(ConfigurationName)" UicDir=".\GeneratedFiles\$(ProjectName)" RccDir=".\GeneratedFiles\$(ProjectName)" Qt5Version_x0020_Win32="4.8.7" QtVersion_x0020_Win32="$(DefaultQtVersion)" /> | |||
</VisualStudio> | |||
</ProjectExtensions> | |||
</Project> |
@@ -117,6 +117,9 @@ | |||
<ClInclude Include="..\src\Services\IntegratedDrivers.h"> | |||
<Filter>Services\Hardware</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\src\Services\TerminalStatusDescriptions.h"> | |||
<Filter>Services</Filter> | |||
</ClInclude> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ClCompile Include="..\src\Services\CryptService.cpp"> | |||
@@ -604,11 +607,5 @@ | |||
<None Include="..\src\locale\paymentprocessor_de.ts"> | |||
<Filter>Translation Files</Filter> | |||
</None> | |||
<None Include="..\src\locale\paymentprocessor_en_bankomat.ts"> | |||
<Filter>Translation Files</Filter> | |||
</None> | |||
<None Include="..\src\locale\paymentprocessor_ru_bankomat.ts"> | |||
<Filter>Translation Files</Filter> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -42,16 +42,20 @@ LogArchiver::LogArchiver(const QString & aName, const QString & aLogName, const | |||
{ | |||
IApplication * app = dynamic_cast<IApplication *>(BasicApplication::getInstance()); | |||
PPSDK::ICore * core = app->getCore(); | |||
PPSDK::TerminalSettings * terminalSettings = static_cast<PPSDK::TerminalSettings *>(core->getSettingsService()-> | |||
getAdapter(PPSDK::CAdapterNames::TerminalAdapter)); | |||
if (app) | |||
{ | |||
PPSDK::ICore * core = app->getCore(); | |||
PPSDK::TerminalSettings * terminalSettings = static_cast<PPSDK::TerminalSettings *>(core->getSettingsService()-> | |||
getAdapter(PPSDK::CAdapterNames::TerminalAdapter)); | |||
mMaxSize = terminalSettings->getLogsMaxSize(); | |||
mLogDir = QDir(app->getWorkingDirectory() + "/logs"); | |||
mKernelPath = app->getWorkingDirectory(); | |||
mMaxSize = terminalSettings->getLogsMaxSize(); | |||
mLogDir = QDir(app->getWorkingDirectory() + "/logs"); | |||
mKernelPath = app->getWorkingDirectory(); | |||
mPacker.setToolPath(mKernelPath); | |||
} | |||
mPacker.setLog(getLog()); | |||
mPacker.setToolPath(mKernelPath); | |||
} | |||
//--------------------------------------------------------------------------- | |||
@@ -19,7 +19,15 @@ void LogRotate::execute() | |||
{ | |||
IApplication * app = dynamic_cast<IApplication *>(BasicApplication::getInstance()); | |||
dynamic_cast<TerminalService *>(app->getCore()->getTerminalService())->getClient()->execute("close_logs"); | |||
if (app) | |||
{ | |||
auto terminalService = dynamic_cast<TerminalService *>(app->getCore()->getTerminalService()); | |||
if (terminalService) | |||
{ | |||
terminalService->getClient()->execute("close_logs"); | |||
} | |||
} | |||
ILog::logRotateAll(); | |||
@@ -146,22 +146,43 @@ bool CashAcceptorManager::shutdown() | |||
//--------------------------------------------------------------------------- | |||
QStringList CashAcceptorManager::getPaymentMethods() | |||
{ | |||
PPSDK::IPaymentService * ps = mApplication->getCore()->getPaymentService(); | |||
qint64 id = ps->getActivePayment(); | |||
QString procType = ps->getPaymentField(id, PPSDK::CPayment::Parameters::Type).value.toString(); | |||
PPSDK::TerminalSettings * settings = SettingsService::instance(mApplication)->getAdapter<PPSDK::TerminalSettings>(); | |||
QVariantMap chargeAccess = settings->getChargeProviderAccess(); | |||
QSet<QString> result; | |||
if (!mDeviceList.isEmpty()) | |||
auto checkMethod = [&chargeAccess, &procType](const QString & aName) -> bool | |||
{ | |||
result.insert(CCashAcceptor::CashPaymentMethod); | |||
} | |||
if ((!chargeAccess.isEmpty() && chargeAccess.value(procType).toStringList().contains(aName)) || | |||
(chargeAccess.isEmpty() && !aName.isEmpty())) | |||
{ | |||
return true; | |||
} | |||
return false; | |||
}; | |||
foreach (SDK::PaymentProcessor::IChargeProvider * provider, mChargeProviders) | |||
{ | |||
QString method = provider->getMethod(); | |||
if (!method.isEmpty()) | |||
if (checkMethod(method)) | |||
{ | |||
result.insert(method); | |||
result.insert(provider->getMethod()); | |||
} | |||
} | |||
// Устройство добавляем в случае, если настройки оплаты для типов процессинга не заданы | |||
// Или должно быть соответствуюшее разрешение | |||
if (!mDeviceList.isEmpty() && (chargeAccess.isEmpty() || | |||
checkMethod(CCashAcceptor::CashPaymentMethod))) | |||
{ | |||
result.insert(CCashAcceptor::CashPaymentMethod); | |||
} | |||
return result.toList(); | |||
} | |||
@@ -185,18 +206,8 @@ void CashAcceptorManager::updateHardwareConfiguration() | |||
{ | |||
mDeviceList.append(device); | |||
// Подписываемся на сигналы. | |||
if (mDisableAmountOverflow) | |||
{ | |||
device->subscribe(SDK::Driver::ICashAcceptor::EscrowSignal, this, SLOT(onEscrowChangeControl(SDK::Driver::SPar))); | |||
} | |||
else | |||
{ | |||
device->subscribe(SDK::Driver::ICashAcceptor::EscrowSignal, this, SLOT(onEscrow(SDK::Driver::SPar))); | |||
} | |||
// Подписываемся на статус. | |||
device->subscribe(SDK::Driver::IDevice::StatusSignal, this, SLOT(onStatusChanged(SDK::Driver::EWarningLevel::Enum, const QString &, int))); | |||
device->subscribe(SDK::Driver::ICashAcceptor::StackedSignal, this, SLOT(onStacked(SDK::Driver::TParList))); | |||
device->setParList(mWorkingParList); | |||
} | |||
@@ -251,9 +262,21 @@ bool CashAcceptorManager::enable(qint64 aPayment, const QString & aPaymentMethod | |||
if (acceptor->setEnable(true)) | |||
{ | |||
toLog(LogLevel::Debug, QString("Payment %2. %1 was added.").arg(acceptor->getName()).arg(mPaymentData->paymentId)); | |||
// Подписываемся на эскроу и стекед. | |||
if (mDisableAmountOverflow) | |||
{ | |||
acceptor->subscribe(SDK::Driver::ICashAcceptor::EscrowSignal, this, SLOT(onEscrowChangeControl(SDK::Driver::SPar))); | |||
} | |||
else | |||
{ | |||
acceptor->subscribe(SDK::Driver::ICashAcceptor::EscrowSignal, this, SLOT(onEscrow(SDK::Driver::SPar))); | |||
} | |||
acceptor->subscribe(SDK::Driver::ICashAcceptor::StackedSignal, this, SLOT(onStacked(SDK::Driver::TParList))); | |||
mPaymentData->validators.insert(acceptor); | |||
toLog(LogLevel::Debug, QString("Payment %2. %1 was added.").arg(acceptor->getName()).arg(mPaymentData->paymentId)); | |||
} | |||
} | |||
} | |||
@@ -303,7 +326,7 @@ bool CashAcceptorManager::disable(qint64 aPayment) | |||
// Даем команду на отключение устройств. | |||
foreach (DSDK::ICashAcceptor * acceptor, mDeviceList) | |||
{ | |||
if (!acceptor->setEnable(false)) | |||
if (mPaymentData->validators.contains(acceptor) && !acceptor->setEnable(false)) | |||
{ | |||
toLog(LogLevel::Error, QString("Failed to disable cash acceptor %1.").arg(mDeviceService->getDeviceConfigName(acceptor))); | |||
} | |||
@@ -475,9 +498,13 @@ void CashAcceptorManager::onStatusChanged(DSDK::EWarningLevel::Enum aLevel, cons | |||
} | |||
else if (acceptor && aStatus == DSDK::ECashAcceptorStatus::Disabled) | |||
{ | |||
// Отправляем сигнал об отключении купюроприемника. | |||
// Принят сигнал об отключении купюроприемника. | |||
toLog(LogLevel::Debug, acceptor->getName() + " is disabled."); | |||
// Отписываемся от эскроу и стекеда. | |||
acceptor->unsubscribe(SDK::Driver::ICashAcceptor::EscrowSignal, this); | |||
acceptor->unsubscribe(SDK::Driver::ICashAcceptor::StackedSignal, this); | |||
// Удаляем купюроприемник из списка включенных. | |||
if (mPaymentData) | |||
{ | |||
@@ -120,7 +120,7 @@ bool DatabaseService::initialize() | |||
{ | |||
// Отмечаем статус устройста, что БД была восстановлена | |||
EventService::instance(mApplication)->sendEvent( | |||
SDK::PaymentProcessor::Event(SDK::PaymentProcessor::EEventType::Warning, getName(), "Database integrity check failed. New database will be created.")); | |||
SDK::PaymentProcessor::Event(SDK::PaymentProcessor::EEventType::OK, getName(), "New database was created.")); | |||
} | |||
//TODO - Запускаем процедуру восстановления базы | |||
@@ -16,10 +16,10 @@ | |||
#include <SDK/Drivers/DeviceStatus.h> | |||
#include <SDK/Drivers/Components.h> | |||
#include <SDK/Drivers/HardwareConstants.h> | |||
#include <SDK/Drivers/FR/FiscalFields.h> | |||
// Modules | |||
#include "DeviceManager/DeviceManager.h" | |||
#include "Hardware/FR/FiscalFieldDescriptions.h" | |||
// Project | |||
#include "DatabaseUtils/IHardwareDatabaseUtils.h" | |||
@@ -76,10 +76,11 @@ bool DeviceService::Status::isMatched(SDK::Driver::EWarningLevel::Enum aLevel) c | |||
//------------------------------------------------------------------------------ | |||
DeviceService::DeviceService(IApplication * aApplication) | |||
: mAccessMutex(QMutex::Recursive), | |||
mLog(aApplication->getLog()), | |||
: mDeviceManager(nullptr), | |||
mAccessMutex(QMutex::Recursive), | |||
mApplication(aApplication), | |||
mDeviceManager(0) | |||
mLog(aApplication->getLog()), | |||
mDatabaseUtils(nullptr) | |||
{ | |||
connect(&mDetectionResult, SIGNAL(finished()), this, SLOT(onDetectionFinished())); | |||
@@ -287,7 +288,7 @@ DSDK::IDevice * DeviceService::acquireDevice(const QString & aInstancePath) | |||
if (keys.contains(0)) | |||
{ | |||
QVariantMap configuration; | |||
configuration.insert(CHardware::FiscalFields::AutomaticNumber, keys.value(0).ap); | |||
configuration.insert(CFiscalSDK::AutomaticNumber, keys.value(0).ap); | |||
device->setDeviceConfiguration(configuration); | |||
} | |||
@@ -332,8 +333,6 @@ PPSDK::IDeviceService::UpdateFirmwareResult DeviceService::updateFirmware(const | |||
return IDeviceService::NoDevice; | |||
} | |||
QVariantMap config = device->getDeviceConfiguration(); | |||
if (!device->canUpdateFirmware()) | |||
{ | |||
LOG(mLog, LogLevel::Error, "The device cannot be updated."); | |||
@@ -364,7 +363,7 @@ QString DeviceService::createDevice(const QString & aDriverPath, const QVariantM | |||
if (keys.contains(0)) | |||
{ | |||
QVariantMap configuration; | |||
configuration.insert(CHardware::FiscalFields::AutomaticNumber, keys.value(0).ap); | |||
configuration.insert(CFiscalSDK::AutomaticNumber, keys.value(0).ap); | |||
result.second->setDeviceConfiguration(configuration); | |||
} | |||
@@ -99,7 +99,7 @@ public: | |||
/// Возвращает имя сервиса. | |||
virtual QString getName() const; | |||
/// Поулчение списка зависимостей. | |||
/// Получение списка зависимостей. | |||
virtual const QSet<QString> & getRequiredServices() const; | |||
/// Получить параметры сервиса. | |||
@@ -140,7 +140,7 @@ public: | |||
/// Получение списка параметров драйвера. | |||
virtual SDK::Plugin::TParameterList getDriverParameters(const QString & aDriverPath) const; | |||
/// Получить конфигурацию утройства и всех, связынных с ним. | |||
/// Получить конфигурацию утройства и всех, связанных с ним. | |||
virtual QVariantMap getDeviceConfiguration(const QString & aConfigName); | |||
/// Устанавливает конфигурацию устройству. | |||
@@ -42,7 +42,8 @@ FirmwareUploadScenario::FirmwareUploadScenario(IApplication * aApplication) : | |||
Scenario(CFirmwareUploadScenario::Name, ILog::getInstance(CFirmwareUploadScenario::Name)), | |||
mApplication(aApplication), | |||
mRetryCount(2), | |||
mDevice(nullptr) | |||
mDevice(nullptr), | |||
mDeviceInitializedTimer(0) | |||
{ | |||
mReportBuilder = new ReportBuilder(mApplication->getWorkingDirectory()); | |||
} | |||
@@ -63,7 +63,7 @@ public: | |||
/// Получить параметры сервиса. | |||
virtual QVariantMap getParameters() const; | |||
/// Поулчение списка зависимостей. | |||
/// Получение списка зависимостей. | |||
virtual const QSet<QString> & getRequiredServices() const; | |||
/// Сброс служебной информации. | |||
@@ -523,6 +523,12 @@ bool GUIService::isDisabled() const | |||
} | |||
//--------------------------------------------------------------------------- | |||
void GUIService::reset() | |||
{ | |||
mGraphicsEngine.reset(); | |||
} | |||
//--------------------------------------------------------------------------- | |||
QRect GUIService::getScreenSize(int aIndex) const | |||
{ | |||
return aIndex ? mGraphicsEngine.getDisplayRectangle(aIndex) : QRect(0, 0, mWidth, mHeight); | |||
@@ -92,6 +92,9 @@ public: | |||
/// Остановлен ли интерфейс? | |||
virtual bool isDisabled() const; | |||
/// Удалает все объекты GraphicsItem, очищает сцену | |||
virtual void reset(); | |||
/// Ширина и высота экрана в пикселях. | |||
virtual QRect getScreenSize(int aIndex) const; | |||
@@ -31,7 +31,8 @@ IdleScenario::IdleScenario(IApplication * aApplication) | |||
mApplication(aApplication), | |||
mCommand(Command::None), | |||
mActive(false), | |||
mNoGui(false) | |||
mNoGui(false), | |||
mInterfaceLockedTimer(0) | |||
{ | |||
mApplication->getCore()->getEventService()->subscribe(this, SLOT(onEvent(const SDK::PaymentProcessor::Event &))); | |||
} | |||
@@ -236,8 +237,6 @@ void IdleScenario::updateState(const QString & aSignal, const QVariantMap & aPar | |||
findFaultyDeviceType(SDK::Driver::CComponents::FiscalRegistrator); | |||
bool hasCardReaderError = findFaultyDeviceType(SDK::Driver::CComponents::CardReader); | |||
namespace DbConstants = PPSDK::CDatabaseConstants; | |||
auto settings = SettingsService::instance(mApplication)->getAdapter<PPSDK::TerminalSettings>()->getCommonSettings(); | |||
bool hasKeysError = terminalService->isTerminalError(PPSDK::ETerminalError::KeyError); | |||
@@ -293,9 +292,31 @@ void IdleScenario::updateState(const QString & aSignal, const QVariantMap & aPar | |||
EventService::instance(mApplication)->sendEvent(PPSDK::EEventType::StartScenario, QVariantMap()); | |||
EventService::instance(mApplication)->sendEvent(SDK::PaymentProcessor::Event(SDK::PaymentProcessor::EEventType::OK, getName(), "OK")); | |||
if (mInterfaceLockedTimer) | |||
{ | |||
killTimer(mInterfaceLockedTimer); | |||
mInterfaceLockedTimer = 0; | |||
toLog(LogLevel::Normal, "Interface lock timer killed."); | |||
} | |||
terminalService->setTerminalError(PPSDK::ETerminalError::InterfaceLocked, false); | |||
toLog(LogLevel::Normal, QString("GUI unlocked.")); | |||
} | |||
else | |||
{ | |||
toLog(LogLevel::Error, QString("GUI locked by: %1.").arg(QStringList(parameters.keys()).join(","))); | |||
// Терминал заблокирован. | |||
// Создаём отложенное выставление сигнала о блокировке интерфейса | |||
if (mInterfaceLockedTimer == 0 && | |||
!terminalService->isTerminalError(PPSDK::ETerminalError::InterfaceLocked)) | |||
{ | |||
mInterfaceLockedTimer = startTimer(1 * 60 * 1000); | |||
toLog(LogLevel::Normal, "Interface lock timer started."); | |||
} | |||
} | |||
} | |||
//--------------------------------------------------------------------------- | |||
@@ -330,4 +351,20 @@ void IdleScenario::onEvent(const PPSDK::Event & aEvent) | |||
} | |||
} | |||
//--------------------------------------------------------------------------- | |||
void IdleScenario::timerEvent(QTimerEvent * aEvent) | |||
{ | |||
if (aEvent && aEvent->timerId() == mInterfaceLockedTimer) | |||
{ | |||
toLog(LogLevel::Normal, "Interface lock timer triggered."); | |||
killTimer(mInterfaceLockedTimer); | |||
mInterfaceLockedTimer = 0; | |||
// Терминал заблокирован. | |||
auto terminalService = TerminalService::instance(mApplication); | |||
terminalService->setTerminalError(PPSDK::ETerminalError::InterfaceLocked, true); | |||
} | |||
} | |||
//--------------------------------------------------------------------------- |
@@ -75,12 +75,16 @@ private slots: | |||
/// Обработчик события. | |||
void onEvent(const SDK::PaymentProcessor::Event & aEvent); | |||
protected: | |||
void timerEvent(QTimerEvent * aEvent); | |||
private: | |||
IApplication * mApplication; | |||
QString mDefaultScenario; | |||
Command mCommand; | |||
bool mActive; | |||
bool mNoGui; | |||
int mInterfaceLockedTimer; | |||
}; | |||
//--------------------------------------------------------------------------- |
@@ -371,6 +371,10 @@ void NetworkService::updateModemParameters() | |||
toLog(LogLevel::Error, QString("Failed to send USSD: '%1'.").arg(connectionTemplate.balanceNumber)); | |||
} | |||
} | |||
else | |||
{ | |||
toLog(LogLevel::Error, QString("Connection template '%1' not found. USSD request for balance undefined.").arg(getConnection().name)); | |||
} | |||
QString operatorName; | |||
@@ -42,6 +42,12 @@ | |||
#include "Services/ServiceCommon.h" | |||
#include "Services/NetworkService.h" | |||
// Thirdparty | |||
#if QT_VERSION < 0x050000 | |||
#include <Qt5Port/qt5port.h> | |||
#endif | |||
namespace PPSDK = SDK::PaymentProcessor; | |||
using namespace std::placeholders; | |||
@@ -79,6 +85,8 @@ PaymentService::PaymentService(IApplication * aApplication) | |||
: ILogable("Payments"), | |||
mApplication(aApplication), | |||
mEnabled(false), | |||
mDBUtils(nullptr), | |||
mCommandIndex(0), | |||
mPaymentLock(QMutex::Recursive), | |||
mOfflinePaymentID(-1), | |||
mOfflinePaymentLock(QMutex::Recursive), | |||
@@ -375,7 +383,7 @@ void PaymentService::deactivatePayment() | |||
} | |||
//--------------------------------------------------------------------------- | |||
QString PaymentService::createSignature(PPSDK::IPayment * aPayment) | |||
QString PaymentService::createSignature(PPSDK::IPayment * aPayment, bool aWithCRC /*= true*/) | |||
{ | |||
if (!aPayment) | |||
{ | |||
@@ -453,9 +461,29 @@ QString PaymentService::createSignature(PPSDK::IPayment * aPayment) | |||
signature += "\t"; | |||
signature += aPayment->getParameter(PPSDK::CPayment::Parameters::Step).value.toString(); | |||
#ifndef _DEBUG | |||
signature = QString::fromUtf8(QCryptographicHash::hash(signature.toUtf8(), QCryptographicHash::Md5).toHex().toUpper()); | |||
if (aWithCRC) | |||
{ | |||
signature += QString("\n%1:%2") | |||
.arg(PPSDK::CPayment::Parameters::CRC) | |||
.arg(aPayment->getParameter(PPSDK::CPayment::Parameters::CRC).value.toString()); | |||
#ifdef _DEBUG | |||
} | |||
#else | |||
#if QT_VERSION < 0x050000 | |||
signature = QString::fromLatin1(CCryptographicHash::hash(signature.toUtf8(), CCryptographicHash::Sha256).toHex()); | |||
#else | |||
signature = QString::fromLatin1(QCryptographicHash::hash(signature.toUtf8(), QCryptographicHash::Sha256).toHex()); | |||
#endif | |||
} | |||
else | |||
{ | |||
signature = QString::fromUtf8(QCryptographicHash::hash(signature.toUtf8(), QCryptographicHash::Md5).toHex().toUpper()); | |||
} | |||
#endif | |||
#ifndef _DEBUG | |||
ICryptEngine * crypt = static_cast<ICryptEngine *>(CryptService::instance(mApplication)->getCryptEngine()); | |||
QByteArray encodedSignature; | |||
@@ -486,15 +514,15 @@ bool PaymentService::verifySignature(PPSDK::IPayment * aPayment) | |||
return false; | |||
} | |||
QString runtimeSignature = createSignature(aPayment); | |||
QStringList runtimeSignatures; | |||
runtimeSignatures << createSignature(aPayment, true) << createSignature(aPayment, false); | |||
#ifndef _DEBUG | |||
ICryptEngine * crypt = static_cast<ICryptEngine *>(CryptService::instance(mApplication)->getCryptEngine()); | |||
QByteArray decodedSignature; | |||
QByteArray decodedRuntimeSignature; | |||
QString error; | |||
QByteArray decodedSignature; | |||
if (!crypt->decryptLong(-1, signature.toUtf8(), decodedSignature, error)) | |||
{ | |||
@@ -503,16 +531,23 @@ bool PaymentService::verifySignature(PPSDK::IPayment * aPayment) | |||
return false; | |||
} | |||
if (!crypt->decryptLong(-1, runtimeSignature.toUtf8(), decodedRuntimeSignature, error)) | |||
foreach (auto runtimeSignature, runtimeSignatures) | |||
{ | |||
toLog(LogLevel::Warning, QString("Payment %1. Failed to decrypt runtime signature. Error: %2.").arg(aPayment->getID()).arg(error)); | |||
QByteArray decodedRuntimeSignature; | |||
return false; | |||
if (!crypt->decryptLong(-1, runtimeSignature.toUtf8(), decodedRuntimeSignature, error)) | |||
{ | |||
toLog(LogLevel::Warning, QString("Payment %1. Failed to decrypt runtime signature. Error: %2.").arg(aPayment->getID()).arg(error)); | |||
} | |||
else if (decodedSignature == decodedRuntimeSignature) | |||
{ | |||
return true; | |||
} | |||
} | |||
return (decodedSignature == decodedRuntimeSignature); | |||
return false; | |||
#else | |||
return (signature == runtimeSignature); | |||
return runtimeSignatures.contains(signature); | |||
#endif // _DEBUG | |||
} | |||
@@ -197,7 +197,7 @@ public: | |||
protected: | |||
/// Формирование подписи платежа. | |||
QString createSignature(PPSDK::IPayment * aPayment); | |||
QString createSignature(PPSDK::IPayment * aPayment, bool aWithCRC = true); | |||
/// Проверка подписи для платежа. | |||
bool verifySignature(PPSDK::IPayment * aPayment); | |||
@@ -64,8 +64,10 @@ bool PluginService::initialize() | |||
mPluginLoader->addDirectory(mApplication->getPluginPath()); | |||
mPluginLoader->addDirectory(mApplication->getUserPluginPath()); | |||
#ifndef _DEBUG | |||
// Запустим фоновую проверку плагинов на наличие цифровой подписи | |||
mPluginVerifierSynchronizer.addFuture(QtConcurrent::run(this, &PluginService::verifyPlugins)); | |||
#endif | |||
return true; | |||
} | |||
@@ -29,6 +29,7 @@ namespace CPrintConstants | |||
const char * const OpBrand = "OPERATOR_BRAND"; | |||
const char * const OpName = "OPERATOR_NAME"; | |||
const char * const OpINN = "OPERATOR_INN"; | |||
const char * const OpPhone = "OPERATOR_PHONE"; | |||
const char * const RecipientInn = "RECIPIENT_INN"; | |||
const char * const RecipientName = "RECIPIENT_NAME"; | |||
const char * const ServiceType = "SERVICE_TYPE"; | |||
@@ -51,7 +52,7 @@ namespace CPrintConstants | |||
const char * const FDNumber = "KKM_FD_NUMBER"; // номер фискального чека | |||
const char * const FDSign = "KKM_FD_SIGN"; // фискальный признак данных | |||
const char * const TaxAmount02 = "TAX_AMOUNT_02"; // сумма НДС чека по ставке 18% (1102) | |||
const char * const TaxAmount02 = "TAX_AMOUNT_02"; // сумма НДС чека по ставке 18(20)% (1102) | |||
const char * const TaxAmount03 = "TAX_AMOUNT_03"; // сумма НДС чека по ставке 10% (1103) | |||
const char * const TaxAmount04 = "TAX_AMOUNT_04"; // сумма расчета по чеку с НДС по ставке 0% (1104) | |||
const char * const TaxAmount05 = "TAX_AMOUNT_05"; // сумма расчета по чеку без НДС (1105) | |||
@@ -38,6 +38,7 @@ PrintFiscalCommand::PrintFiscalCommand(const QString & aReceiptType, FiscalComma | |||
{ | |||
} | |||
#if 0 | |||
//--------------------------------------------------------------------------- | |||
QVariantMap toUpperCaseKeys(const QVariantMap & aParameters) | |||
{ | |||
@@ -50,11 +51,12 @@ QVariantMap toUpperCaseKeys(const QVariantMap & aParameters) | |||
return result; | |||
} | |||
#endif | |||
//--------------------------------------------------------------------------- | |||
SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & aParameters) | |||
{ | |||
DSDK::TAmountDataList fiscalAmountList; | |||
DSDK::TUnitDataList unitDataList; | |||
bool dealerIsBank = aParameters.value(CPrintConstants::DealerIsBank, false).toBool(); | |||
DSDK::TVAT dealerVAT = aParameters.value(CPrintConstants::DealerVAT, 0).toInt(); | |||
@@ -72,7 +74,7 @@ SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & | |||
.arg(aParameters[CPrintConstants::ServiceType].toString()) | |||
.arg(aParameters[CPrintConstants::OpBrand].toString()); | |||
fiscalAmountList << DSDK::SAmountData(amount, vat, paymentTitle, operatorINN, DSDK::EPayOffSubjectTypes::Payment); | |||
unitDataList << DSDK::SUnitData(amount, vat, paymentTitle, operatorINN, DSDK::EPayOffSubjectTypes::Payment); | |||
} | |||
else | |||
{ | |||
@@ -84,7 +86,7 @@ SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & | |||
// amount содержит список сумм для печати реестра нераспечатанных чеков | |||
for (int i = 0; i < amounts.size(); i++) | |||
{ | |||
fiscalAmountList << DSDK::SAmountData( | |||
unitDataList << DSDK::SUnitData( | |||
amounts.value(i).toDouble(), | |||
amountsVAT.value(i).toInt(), | |||
amountTitles.value(i).toString(), | |||
@@ -96,15 +98,15 @@ SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & | |||
if (!qFuzzyIsNull(fee)) | |||
{ | |||
QString dealerINN = aParameters.value(CPrintConstants::DealerInn).toString(); | |||
fiscalAmountList << (dealerIsBank ? | |||
DSDK::SAmountData(fee, dealerVAT, tr("#bank_fee"), dealerINN, DSDK::EPayOffSubjectTypes::Payment) : | |||
DSDK::SAmountData(fee, dealerVAT, tr("#dealer_fee"), dealerINN, DSDK::EPayOffSubjectTypes::AgentFee)); | |||
unitDataList << (dealerIsBank ? | |||
DSDK::SUnitData(fee, dealerVAT, tr("#bank_fee"), dealerINN, DSDK::EPayOffSubjectTypes::Payment) : | |||
DSDK::SUnitData(fee, dealerVAT, tr("#dealer_fee"), dealerINN, DSDK::EPayOffSubjectTypes::AgentFee)); | |||
} | |||
if (!qFuzzyIsNull(processingFee)) | |||
{ | |||
QString bankINN = aParameters.value(CPrintConstants::BankInn).toString(); | |||
fiscalAmountList << DSDK::SAmountData(processingFee, 0, tr("#processing_fee"), bankINN, DSDK::EPayOffSubjectTypes::Payment); | |||
unitDataList << DSDK::SUnitData(processingFee, 0, tr("#processing_fee"), bankINN, DSDK::EPayOffSubjectTypes::Payment); | |||
} | |||
bool EMoney = aParameters.value(PPSDK::CPayment::Parameters::PayTool).toInt() > 0; | |||
@@ -112,13 +114,19 @@ SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & | |||
auto taxSystem = aParameters.contains(CPrintConstants::DealerTaxSystem) ? static_cast<DSDK::ETaxSystems::Enum>(aParameters.value(CPrintConstants::DealerTaxSystem).toInt()) : DSDK::ETaxSystems::None; | |||
auto agentFlag = aParameters.contains(CPrintConstants::DealerAgentFlag) ? static_cast<DSDK::EAgentFlags::Enum>(aParameters.value(CPrintConstants::DealerAgentFlag).toInt()) : DSDK::EAgentFlags::None; | |||
DSDK::SPaymentData result(fiscalAmountList, false, payType, taxSystem, agentFlag); | |||
DSDK::SPaymentData result(unitDataList, false, payType, taxSystem, agentFlag); | |||
result.fiscalParameters[CHardwareSDK::FR::UserPhone] = QString(); | |||
result.fiscalParameters[CHardwareSDK::FR::UserMail] = QString(); | |||
#if 0 | |||
//TODO - решить как на верхнем уровне в интерфейсе мы будем давать возможность | |||
// вводить телефон/email для отправки чека ПЕРЕД печатью этого чека. | |||
// Отключено по жалобе дилеров 1 sms = 2руб в счете от ОФД | |||
// #60325 | |||
QVariantMap upperKeyParameters = toUpperCaseKeys(aParameters); | |||
QRegExp phoneRegexp("^9\\d{9}$"); | |||
result.fiscalParameters[CHardwareSDK::FR::UserPhone] = QString(); | |||
foreach (auto fieldName, QStringList() << "100" << "PHONE" << "CONTACT" << "101" << "102" << "103" << "104") | |||
{ | |||
if (upperKeyParameters.contains(fieldName) && phoneRegexp.exactMatch(upperKeyParameters.value(fieldName).toString())) | |||
@@ -128,8 +136,6 @@ SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & | |||
} | |||
} | |||
result.fiscalParameters[CHardwareSDK::FR::UserMail] = QString(); | |||
foreach (auto fieldName, QStringList() << "PAYER_EMAIL") | |||
{ | |||
if (upperKeyParameters.contains(fieldName)) | |||
@@ -142,6 +148,7 @@ SDK::Driver::SPaymentData PrintFiscalCommand::getPaymentData(const QVariantMap & | |||
} | |||
} | |||
} | |||
#endif | |||
return result; | |||
} | |||
@@ -205,10 +212,6 @@ bool PrintPayment::canPrint(DSDK::IPrinter * aPrinter, bool aRealCheck) | |||
//--------------------------------------------------------------------------- | |||
bool PrintPayment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParameters) | |||
{ | |||
QVariantMap parameters = aParameters; | |||
QStringList receipt; | |||
getFiscalInfo(parameters, receipt); | |||
// Добавляем строки основного чека | |||
QVariantMap configuration = aPrinter->getDeviceConfiguration(); | |||
bool onlineKKM = configuration[CHardwareSDK::CanOnline].toBool(); | |||
@@ -225,42 +228,53 @@ bool PrintPayment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParamet | |||
actualParameters.insert(CPrintConstants::KKM::SerialNumber, KKMSerialNumber); | |||
actualParameters.insert("ONLINE_KKM", onlineKKM ? 1 : 0); | |||
receipt.append(mService->getReceipt(mReceiptTemplate, actualParameters)); | |||
QStringList receipt = mService->getReceipt(mReceiptTemplate, actualParameters); | |||
QVariantMap parameters = aParameters; | |||
QStringList fiscalPart; | |||
bool hasFiscalInfo = getFiscalInfo(parameters, fiscalPart); | |||
if (hasFiscalInfo) | |||
{ | |||
receipt.append(fiscalPart); | |||
} | |||
bool result = false; | |||
// Повторно мы печатаем только нефискальные чеки | |||
if (!fiscalPrinting) | |||
{ | |||
result = canPrint(aPrinter, false) && aPrinter->print(receipt); | |||
// Если есть фискальный сервис, но нет фискальной информации и запрещено печатать чеки без ФП | |||
if (!mService->enableBlankFiscalData() && mService->getFiscalRegister() && !hasFiscalInfo) | |||
{ | |||
mService->toLog(LogLevel::Error, QString("[%1] Not print receipt with blank fiscal data.") | |||
.arg(aParameters[PPSDK::CPayment::Parameters::ID].toLongLong())); | |||
} | |||
else | |||
{ | |||
result = canPrint(aPrinter, false) && aPrinter->print(receipt); | |||
} | |||
} | |||
else if (canFiscalPrint(aPrinter, false)) | |||
{ | |||
DSDK::SPaymentData paymentData = getPaymentData(actualParameters); | |||
mFiscalPaymentData.clear(); | |||
mPayOffSubjectData.clear(); | |||
result = static_cast<DSDK::IFiscalPrinter *>(aPrinter)->printFiscal(receipt, paymentData, mFiscalPaymentData, mPayOffSubjectData); | |||
if (!mFiscalPaymentData.isEmpty()) | |||
if (result) | |||
{ | |||
#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("#tax_system"), TaxSystem); | |||
ADD_FISCAL_TAG(tr("#kkt_timestamp"), FDDateTime); | |||
ADD_FISCAL_TAG(tr("#kkt_znm"), SerialFRNumber); | |||
ADD_FISCAL_TAG(tr("#kkt_rnm"), RNM); | |||
ADD_FISCAL_TAG(tr("#kkt_session"), SessionNumber); | |||
ADD_FISCAL_TAG(tr("#kkt_fd_serial"), DocumentNumber); | |||
ADD_FISCAL_TAG(tr("#kkt_fn"), SerialFSNumber); | |||
ADD_FISCAL_TAG(tr("#kkt_fd"), FDNumber); | |||
ADD_FISCAL_TAG(tr("#kkt_fp"), FDSign); | |||
ADD_FISCAL_TAG(tr("#tax_amount_02"), TaxAmount02); | |||
ADD_FISCAL_TAG(tr("#tax_amount_03"), TaxAmount03); | |||
ADD_FISCAL_TAG(tr("#tax_amount_04"), TaxAmount04); | |||
ADD_FISCAL_TAG(tr("#tax_amount_05"), TaxAmount05); | |||
if (mFiscalFieldData.isEmpty()) | |||
{ | |||
mFiscalFieldData = aPrinter->getDeviceConfiguration().value(CHardwareSDK::FR::FiscalFieldData).value<DSDK::TFiscalFieldData>(); | |||
} | |||
addFiscalPaymentData(mFiscalPaymentData, receipt); | |||
for (int i = 0; i < mPayOffSubjectData.size(); ++i) | |||
{ | |||
addFiscalPaymentData(mPayOffSubjectData[i], receipt); | |||
} | |||
} | |||
} | |||
@@ -273,6 +287,28 @@ bool PrintPayment::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParamet | |||
} | |||
//--------------------------------------------------------------------------- | |||
void PrintPayment::addFiscalPaymentData(const DSDK::TFiscalPaymentData & aFPData, QStringList & aData) | |||
{ | |||
for (auto it = aFPData.begin(); it != aFPData.end(); ++it) | |||
{ | |||
DSDK::SFiscalFieldData FFData = mFiscalFieldData.value(it.key()); | |||
QString key = FFData.translationPF; | |||
QString value = FFData.isMoney ? QString("%1").arg(it->toInt() / 100.0, 0, 'f', 2) : it->toString(); | |||
QString text; | |||
if (!key.isEmpty() && !value.isEmpty()) text = key + " = " + value; | |||
else if (!key.isEmpty()) text = key; | |||
else if (!value.isEmpty()) text = value; | |||
if (!text.isEmpty()) | |||
{ | |||
aData << text.simplified(); | |||
} | |||
} | |||
} | |||
//--------------------------------------------------------------------------- | |||
const DSDK::TFiscalPaymentData & PrintPayment::getFiscalData() const | |||
{ | |||
return mFiscalPaymentData; | |||
@@ -423,6 +459,11 @@ bool PrintZReport::print(DSDK::IPrinter * aPrinter, const QVariantMap & /*aParam | |||
//--------------------------------------------------------------------------- | |||
bool PrintReceipt::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParameters) | |||
{ | |||
if (aPrinter == nullptr) | |||
{ | |||
return false; | |||
} | |||
QVariantMap configuration = aPrinter->getDeviceConfiguration(); | |||
QString KKMSerialNumber = configuration[CHardwareSDK::SerialNumber].toString(); | |||
@@ -435,9 +476,16 @@ bool PrintReceipt::print(DSDK::IPrinter * aPrinter, const QVariantMap & aParamet | |||
actualParameters.insert(CPrintConstants::KKM::SerialNumber, KKMSerialNumber); | |||
QStringList receipt = mService->getReceipt(mReceiptTemplate, actualParameters); | |||
mService->saveReceiptContent(QString("%1_%2").arg(QTime::currentTime().toString("hhmmsszzz")).arg(mReceiptTemplate), receipt); | |||
QString receiptFileName = QString("%1_%2").arg(QTime::currentTime().toString("hhmmsszzz")).arg(mReceiptTemplate); | |||
if (aParameters.contains(SDK::PaymentProcessor::CPayment::Parameters::ID)) | |||
{ | |||
receiptFileName += QString("_%1").arg(aParameters[SDK::PaymentProcessor::CPayment::Parameters::ID].toLongLong()); | |||
} | |||
mService->saveReceiptContent(receiptFileName, receipt); | |||
return aPrinter && aPrinter->print(receipt); | |||
return aPrinter->print(receipt); | |||
} | |||
//--------------------------------------------------------------------------- |
@@ -38,6 +38,7 @@ class PrintCommand | |||
public: | |||
PrintCommand(const QString & aReceiptType): | |||
mReceiptType(aReceiptType) {} | |||
virtual ~PrintCommand() {} | |||
/// Проверка возможности печати. | |||
virtual bool canPrint(SDK::Driver::IPrinter * aPrinter, bool aRealCheck) | |||
@@ -91,6 +92,7 @@ class PrintPayment : public PrintFiscalCommand | |||
SDK::Driver::TFiscalPaymentData mFiscalPaymentData; | |||
SDK::Driver::TComplexFiscalPaymentData mPayOffSubjectData; | |||
SDK::Driver::TFiscalFieldData mFiscalFieldData; | |||
public: | |||
PrintPayment(const QString & aReceiptType, PrintingService * aService): | |||
@@ -106,6 +108,9 @@ public: | |||
const SDK::Driver::TFiscalPaymentData & getFiscalData() const; | |||
private: | |||
/// Добавить данные платежа. | |||
void addFiscalPaymentData(const SDK::Driver::TFiscalPaymentData & aFPData, QStringList & aData); | |||
bool isFiscal(SDK::Driver::IPrinter * aPrinter); | |||
}; | |||
@@ -9,9 +9,7 @@ | |||
#include <QtCore/QDir> | |||
#include <QtCore/QDate> | |||
#include <QtCore/QBuffer> | |||
#include <QtCore/QTextStream> | |||
#include <QtScript/QScriptEngine> | |||
#include <QtCore/QTextCodec> | |||
#include <QtXML/QDomDocument> | |||
#include <QtXML/QXmlStreamWriter> | |||
#include <Common/QtHeadersEnd.h> | |||
@@ -67,12 +65,15 @@ namespace CPrintingService | |||
//--------------------------------------------------------------------------- | |||
PrintingService::PrintingService(IApplication * aApplication) : | |||
mApplication(aApplication), | |||
mDatabaseUtils(nullptr), | |||
mDeviceService(nullptr), | |||
mContinuousMode(false), | |||
mServiceOperation(false), | |||
mRandomReceiptsID(false), | |||
mNextReceiptIndex(1), | |||
mFiscalRegister(nullptr), | |||
mRandomGenerator(static_cast<unsigned>(QDateTime::currentDateTime().currentMSecsSinceEpoch())) | |||
mRandomGenerator(static_cast<unsigned>(QDateTime::currentDateTime().currentMSecsSinceEpoch())), | |||
mEnableBlankFiscalData(false), | |||
mFiscalRegister(nullptr) | |||
{ | |||
setLog(mApplication->getLog()); | |||
} | |||
@@ -221,27 +222,36 @@ int PrintingService::printReceipt(const QString & aReceiptType, const QVariantMa | |||
mContinuousMode = aContinuousMode; | |||
mServiceOperation = aServiceOperation; | |||
QString receiptTemplate = (QString("%1_%2").arg(aParameters[PPSDK::CPayment::Parameters::Type].toString()).arg(aReceiptTemplate)).toLower(); | |||
QStringList receiptTemplates; | |||
receiptTemplates | |||
// Извлекаем шаблон 'PROCESSING_TYPE'_aReceiptTemplate | |||
<< (QString("%1_%2").arg(aParameters[PPSDK::CPayment::Parameters::Type].toString()).arg(aReceiptTemplate)).toLower() | |||
// Извлекаем обычный шаблон для чека нужного типа. | |||
<< aReceiptTemplate.toLower() | |||
// Резервный шаблон | |||
<< SDK::PaymentProcessor::CReceiptType::Payment; | |||
// Извлекаем шаблон 'PROCESSING_TYPE'_aReceiptTemplate | |||
if (!mCachedReceipts.contains(receiptTemplate)) | |||
foreach (auto templateName, receiptTemplates) | |||
{ | |||
receiptTemplate = aReceiptTemplate.toLower(); | |||
if (templateName == SDK::PaymentProcessor::CReceiptType::Disabled) | |||
{ | |||
break; | |||
} | |||
// Извлекаем обычный шаблон для чека нужного типа. | |||
if (!mCachedReceipts.contains(receiptTemplate)) | |||
if (mCachedReceipts.contains(templateName)) | |||
{ | |||
toLog(LogLevel::Error, QString("Failed to print receipt. Missing receipt template : %1.").arg(receiptTemplate)); | |||
auto printCommand = getPrintCommand(aReceiptType); | |||
printCommand->setReceiptTemplate(templateName); | |||
QMetaObject::invokeMethod(this, "printEmptyReceipt", Qt::QueuedConnection, Q_ARG(int, 0), Q_ARG(bool, true)); | |||
return 0; | |||
return performPrint(printCommand, aParameters, mCachedReceipts[templateName]); | |||
} | |||
} | |||
auto printCommand = getPrintCommand(aReceiptType); | |||
printCommand->setReceiptTemplate(aReceiptTemplate); | |||
toLog(LogLevel::Error, QString("Failed to print receipt. Missing receipt template : %1.").arg(aReceiptTemplate)); | |||
QMetaObject::invokeMethod(this, "printEmptyReceipt", Qt::QueuedConnection, Q_ARG(int, 0), Q_ARG(bool, true)); | |||
return performPrint(printCommand, aParameters, mCachedReceipts[receiptTemplate]); | |||
return 0; | |||
} | |||
//--------------------------------------------------------------------------- | |||
@@ -1276,11 +1286,8 @@ void PrintingService::saveReceiptContent(const QString & aReceiptName, const QSt | |||
// Сохраняем чек. | |||
if (file.open(QIODevice::WriteOnly)) | |||
{ | |||
QTextStream ostream(&file); | |||
ostream << aContents.join("\r\n"); | |||
ostream.flush(); | |||
file.write(aContents.join("\r\n").toUtf8()); | |||
file.close(); | |||
} | |||
else | |||
{ | |||
@@ -1306,6 +1313,18 @@ void PrintingService::saveReceipt(const QVariantMap & aParameters, const QString | |||
} | |||
//--------------------------------------------------------------------------- | |||
QString & replaceTags(QString & aMessage) | |||
{ | |||
aMessage.replace("[br]", "\n", Qt::CaseInsensitive); | |||
aMessage.remove(QRegExp("\\[(b|dw|dh)\\]", Qt::CaseInsensitive)); | |||
aMessage.remove(QRegExp("\\[/(b|dw|dh)\\]", Qt::CaseInsensitive)); | |||
aMessage.remove(QRegExp("\\[img.?\\].*\\[/img\\]")); | |||
return aMessage; | |||
} | |||
//--------------------------------------------------------------------------- | |||
QString PrintingService::loadReceipt(qint64 aPaymentId) | |||
{ | |||
// Получаем имя папки с чеками. | |||
@@ -1320,18 +1339,24 @@ QString PrintingService::loadReceipt(qint64 aPaymentId) | |||
} | |||
QDir dir(path.path() + QDir::separator()); | |||
QStringList receipts = dir.entryList(QStringList() << QString("*%1.txt").arg(aPaymentId) << QString("*%1_not_printed.txt").arg(aPaymentId)); | |||
QStringList receiptFiles; | |||
receiptFiles | |||
<< QString("*_%1.txt").arg(aPaymentId) | |||
<< QString("*_%1_*.txt").arg(aPaymentId); | |||
QStringList receiptsBody; | |||
if (!receipts.isEmpty()) | |||
QStringList receipts = dir.entryList(receiptFiles); | |||
while (!receipts.isEmpty()) | |||
{ | |||
QFile f(dir.absolutePath() + QDir::separator() + receipts.takeFirst()); | |||
if (f.open(QIODevice::ReadOnly)) | |||
{ | |||
return QTextCodec::codecForName("Windows-1251")->toUnicode(f.readAll()); | |||
} | |||
receiptsBody << replaceTags(QString::fromUtf8(f.readAll())); | |||
} | |||
} | |||
return QString(); | |||
return receiptsBody.join("\n------------------------------\n"); | |||
} | |||
//--------------------------------------------------------------------------- | |||
@@ -1401,8 +1426,11 @@ 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; | |||
auto commonSettings = settings->getCommonSettings(); | |||
mRandomReceiptsID = commonSettings.randomReceiptsID; | |||
QTime autoZReportTime = commonSettings.autoZReportTime; | |||
mEnableBlankFiscalData = commonSettings.enableBlankFiscalData; | |||
mPrinterDevices.clear(); | |||
mAvailablePrinters.clear(); | |||
@@ -75,7 +75,7 @@ public: | |||
/// Завершение работы, освобождение ресурсов. | |||
virtual bool shutdown(); | |||
/// Поулчение списка зависимостей. | |||
/// Получение списка зависимостей. | |||
virtual const QSet<QString> & getRequiredServices() const; | |||
/// Получить параметры сервиса. | |||
@@ -109,6 +109,8 @@ public: | |||
#pragma endregion | |||
bool enableBlankFiscalData() const { return mEnableBlankFiscalData; } | |||
public: | |||
/// Получить объект фискального регистратора | |||
SDK::PaymentProcessor::IFiscalRegister * getFiscalRegister() const; | |||
@@ -229,6 +231,7 @@ private: | |||
bool mServiceOperation; | |||
bool mRandomReceiptsID; | |||
mutable std::mt19937 mRandomGenerator; | |||
bool mEnableBlankFiscalData; | |||
/// Индекс следующего задания на печать | |||
QAtomicInt mNextReceiptIndex; | |||
@@ -105,7 +105,8 @@ RemoteService * RemoteService::instance(IApplication * aApplication) | |||
RemoteService::RemoteService(IApplication * aApplication) | |||
: ILogable(CRemoteService::LogName), | |||
mApplication(aApplication), | |||
mDatabase(0), | |||
mDatabase(nullptr), | |||
mLastCommand(0), | |||
mGenerateKeyCommand(0), | |||
mSettings(aApplication->getWorkingDirectory() + CRemoteService::ConfigFileName, QSettings::IniFormat), | |||
mCommandMutex(QMutex::Recursive) | |||
@@ -179,9 +179,13 @@ void SchedulerService::setupAutoUpdate() | |||
//------------------------------------------------------------------------------ | |||
SchedulerService::Item::Item() : | |||
mFailExecuteCounter(0), | |||
mPeriod(0), | |||
mTriggeredOnStart(false), | |||
mOnlyOnce(false) | |||
mTimeThreshold(0), | |||
mRepeatCountIfFail(0), | |||
mRetryTimeout(0), | |||
mOnlyOnce(false), | |||
mFailExecuteCounter(0) | |||
{ | |||
} | |||
@@ -223,7 +227,7 @@ SchedulerService::Item::Item(const QString & aName, const QSettings & aSettings, | |||
} | |||
else | |||
{ | |||
mTime = mTime = QTime::currentTime().addSecs(60 * 60); | |||
mTime = QTime::currentTime().addSecs(60 * 60); | |||
} | |||
} | |||
else | |||
@@ -303,6 +303,11 @@ bool ServiceController::finalizeServices(const char * aRetrySlot) | |||
//--------------------------------------------------------------------------- | |||
void ServiceController::finalizeCoreItems() | |||
{ | |||
if (mCorePluginList.isEmpty()) | |||
{ | |||
return; | |||
} | |||
auto pluginLoader = PluginService::instance(mApplication)->getPluginLoader(); | |||
foreach(auto coreItem, mCorePluginList) | |||
@@ -253,16 +253,48 @@ void TerminalService::resetParameters(const QSet<QString> & aParameters) | |||
//--------------------------------------------------------------------------- | |||
void TerminalService::writeLockStatus(bool aIsLocked) | |||
{ | |||
// Если разблокируем, то все критические ошибки превращаем в некритические (кроме ошибки БД) | |||
if (!aIsLocked) | |||
{ | |||
foreach (auto key, mTerminalStatusHash.keys()) | |||
{ | |||
if (key != CServices::DatabaseService && | |||
mTerminalStatusHash[key].getType() >= PPSDK::EEventType::Warning) | |||
{ | |||
mTerminalStatusHash.remove(key); | |||
} | |||
else if (mTerminalStatusHash[key].getData().toString().contains("#alarm")) | |||
{ | |||
PPSDK::Event e = mTerminalStatusHash[key]; | |||
mTerminalStatusHash[key] = PPSDK::Event(e.getType(), e.getSender(), e.getData().toString().remove("#alarm")); | |||
} | |||
} | |||
// Сбрасываем "плохие" статусы при разблокировке | |||
TStatusCodes statuses = mDeviceErrorFlags.values(PPSDK::CDatabaseConstants::Devices::Terminal).toSet(); | |||
foreach (auto status, statuses) | |||
{ | |||
if (TerminalStatusCode::Specification[status].warningLevel >= SDK::Driver::EWarningLevel::Warning) | |||
{ | |||
mDeviceErrorFlags.remove(PPSDK::CDatabaseConstants::Devices::Terminal, status); | |||
} | |||
} | |||
} | |||
updateTerminalStatus(); | |||
// Проверка на "Уже записали статус в БД?", иначе при блокировке по ошибке БД мы зацикливаемся | |||
if (!mLocked.is_initialized() || mLocked.get() != aIsLocked) | |||
if (mLocked.is_initialized() && mLocked.get() == aIsLocked) | |||
{ | |||
return; | |||
} | |||
else | |||
{ | |||
mLocked = aIsLocked; | |||
mDbUtils->setDeviceParam(PPSDK::CDatabaseConstants::Devices::Terminal, PPSDK::CDatabaseConstants::Parameters::DisabledParam, aIsLocked); | |||
mDbUtils->addDeviceStatus(PPSDK::CDatabaseConstants::Devices::Terminal, | |||
aIsLocked ? SDK::Driver::EWarningLevel::Warning : SDK::Driver::EWarningLevel::OK, | |||
aIsLocked ? "Locked" : "Unlocked"); | |||
mDbUtils->setDeviceParam(PPSDK::CDatabaseConstants::Devices::Terminal, PPSDK::CDatabaseConstants::Parameters::DisabledParam, mLocked.get()); | |||
} | |||
} | |||
@@ -317,29 +349,18 @@ void TerminalService::onEvent(const SDK::PaymentProcessor::Event & aEvent) | |||
{ | |||
mTerminalStatusHash[aEvent.getSender()] = aEvent; | |||
auto status2LogLevel = [](PPSDK::EEventType::Enum aEventType) -> LogLevel::Enum { | |||
switch (aEventType) | |||
{ | |||
case PPSDK::EEventType::Warning: return LogLevel::Warning; | |||
case PPSDK::EEventType::Critical: return LogLevel::Error; | |||
default: return LogLevel::Normal; | |||
} | |||
}; | |||
bool writeStatusOK = true; | |||
auto status = getTerminalStatus(); | |||
if (mTerminalStatusCache != status) | |||
if (aEvent.getSender() == CServices::DatabaseService) | |||
{ | |||
toLog(status2LogLevel(eventType), QString("Terminal change status: %1.").arg(status.second)); | |||
writeStatusOK = mDbUtils->addDeviceStatus(PPSDK::CDatabaseConstants::Devices::Terminal, status.first, status.second); | |||
mTerminalStatusCache = status; | |||
setTerminalError(PPSDK::ETerminalError::DatabaseError, aEvent.getType() == PPSDK::EEventType::Critical); | |||
} | |||
if (aEvent.getSender() == "AccountBalance") | |||
else if (aEvent.getSender() == "AccountBalance") | |||
{ | |||
setTerminalError(PPSDK::ETerminalError::AccountBalanceError, eventType != PPSDK::EEventType::OK); | |||
} | |||
else | |||
{ | |||
updateTerminalStatus(); | |||
} | |||
break; | |||
} | |||
@@ -350,7 +371,7 @@ void TerminalService::onEvent(const SDK::PaymentProcessor::Event & aEvent) | |||
QPair<SDK::Driver::EWarningLevel::Enum, QString> TerminalService::getTerminalStatus() const | |||
{ | |||
QStringList resultMessage; | |||
SDK::Driver::EWarningLevel::Enum result = SDK::Driver::EWarningLevel::OK; | |||
SDK::Driver::EWarningLevel::Enum resultLevel = SDK::Driver::EWarningLevel::OK; | |||
auto convertStatus = [](PPSDK::EEventType::Enum aEventType) -> SDK::Driver::EWarningLevel::Enum { | |||
switch (aEventType) | |||
@@ -367,9 +388,9 @@ QPair<SDK::Driver::EWarningLevel::Enum, QString> TerminalService::getTerminalSta | |||
i.next(); | |||
auto status = convertStatus(static_cast<PPSDK::EEventType::Enum>(i.value().getType())); | |||
if (status > result) | |||
if (status > resultLevel) | |||
{ | |||
result = status; | |||
resultLevel = status; | |||
} | |||
QString data = i.value().getData().toString(); | |||
@@ -381,9 +402,27 @@ QPair<SDK::Driver::EWarningLevel::Enum, QString> TerminalService::getTerminalSta | |||
} | |||
} | |||
if (isLocked() && result <= SDK::Driver::EWarningLevel::OK) | |||
TStatusCodes statuses = mDeviceErrorFlags.values(PPSDK::CDatabaseConstants::Devices::Terminal).toSet(); | |||
if (statuses.isEmpty()) | |||
{ | |||
result = SDK::Driver::EWarningLevel::Warning; | |||
statuses << DeviceStatusCode::OK::OK; | |||
} | |||
foreach(int status, statuses) | |||
{ | |||
resultMessage << TerminalStatusCode::Specification[status].translation; | |||
if (resultLevel < TerminalStatusCode::Specification[status].warningLevel) | |||
{ | |||
resultLevel = TerminalStatusCode::Specification[status].warningLevel; | |||
} | |||
} | |||
if (isLocked()) | |||
{ | |||
resultMessage << "Locked"; | |||
resultLevel = SDK::Driver::EWarningLevel::Error; | |||
} | |||
if (resultMessage.isEmpty()) | |||
@@ -391,7 +430,7 @@ QPair<SDK::Driver::EWarningLevel::Enum, QString> TerminalService::getTerminalSta | |||
resultMessage << "OK"; | |||
} | |||
return QPair<SDK::Driver::EWarningLevel::Enum, QString>(result, resultMessage.join("\n")); | |||
return QPair<SDK::Driver::EWarningLevel::Enum, QString>(resultLevel, resultMessage.join("\n")); | |||
} | |||
//--------------------------------------------------------------------------- | |||
@@ -469,6 +508,8 @@ void TerminalService::setTerminalError(PPSDK::ETerminalError::Enum aErrorType, b | |||
if (changed) | |||
{ | |||
updateGUI(); | |||
updateTerminalStatus(); | |||
} | |||
} | |||
@@ -476,6 +517,7 @@ void TerminalService::setTerminalError(PPSDK::ETerminalError::Enum aErrorType, b | |||
void TerminalService::updateGUI() | |||
{ | |||
auto guiService = GUIService::instance(mApplication); | |||
if (guiService) | |||
{ | |||
guiService->disable(!getFaultyDevices(true).isEmpty() || isLocked()); | |||
@@ -485,7 +527,30 @@ void TerminalService::updateGUI() | |||
//--------------------------------------------------------------------------- | |||
bool TerminalService::isTerminalError(PPSDK::ETerminalError::Enum aErrorType) const | |||
{ | |||
return mDeviceErrorFlags.values(PPSDK::CDatabaseConstants::Devices::Terminal).contains(aErrorType) == true; | |||
return mDeviceErrorFlags.values(PPSDK::CDatabaseConstants::Devices::Terminal).contains(aErrorType); | |||
} | |||
//--------------------------------------------------------------------------- | |||
void TerminalService::updateTerminalStatus() | |||
{ | |||
auto warningLevel2LogLevel = [](SDK::Driver::EWarningLevel::Enum aEventType) -> LogLevel::Enum { | |||
switch (aEventType) | |||
{ | |||
case SDK::Driver::EWarningLevel::Warning: return LogLevel::Warning; | |||
case SDK::Driver::EWarningLevel::Error: return LogLevel::Error; | |||
default: return LogLevel::Normal; | |||
} | |||
}; | |||
auto status = getTerminalStatus(); | |||
if (mTerminalStatusCache != status) | |||
{ | |||
toLog(warningLevel2LogLevel(status.first), QString("Terminal status: %1.") | |||
.arg(status.second.replace("\r", "").replace("\n", ";"))); | |||
mDbUtils->addDeviceStatus(PPSDK::CDatabaseConstants::Devices::Terminal, status.first, status.second); | |||
} | |||
} | |||
//--------------------------------------------------------------------------- | |||
@@ -26,6 +26,10 @@ | |||
#include <WatchServiceClient/IWatchServiceClient.h> | |||
// Project | |||
#include "TerminalStatusDescriptions.h" | |||
class IHardwareDatabaseUtils; | |||
class IApplication; | |||
class GUIService; | |||
@@ -117,6 +121,10 @@ private: | |||
/// Отключаем/включаем графический интерфейс. | |||
void updateGUI(); | |||
/// Обновить статус терминала | |||
void updateTerminalStatus(); | |||
private slots: | |||
void onEvent(const SDK::PaymentProcessor::Event & aEvent); | |||
@@ -0,0 +1,50 @@ | |||
#pragma once | |||
// SDK | |||
#include <SDK/PaymentProcessor/Core/ITerminalService.h> | |||
// Project | |||
#include "Hardware/Common/BaseStatusDescriptions.h" | |||
//-------------------------------------------------------------------------------- | |||
namespace TerminalStatusCode | |||
{ | |||
using namespace SDK::PaymentProcessor; | |||
class CSpecifications : public TStatusCodeSpecification | |||
{ | |||
public: | |||
CSpecifications() | |||
{ | |||
append(DeviceStatusCode::OK::OK, SStatusCodeSpecification(SDK::Driver::EWarningLevel::OK, "OK", QCoreApplication::translate("TerminalStatuses", "#ok"))); | |||
append(ETerminalError::KeyError, SStatusCodeSpecification(SDK::Driver::EWarningLevel::Error, "KeyError", QCoreApplication::translate("TerminalStatuses", "#key_error"))); | |||
append(ETerminalError::ConfigError, SStatusCodeSpecification(SDK::Driver::EWarningLevel::Error, "ConfigError", QCoreApplication::translate("TerminalStatuses", "#config_error"))); | |||
append(ETerminalError::DatabaseError, SStatusCodeSpecification(SDK::Driver::EWarningLevel::Error, "DatabaseError", QCoreApplication::translate("TerminalStatuses", "#database_error"))); | |||
append(ETerminalError::NetworkError, SStatusCodeSpecification(SDK::Driver::EWarningLevel::Error, "NetworkError", QCoreApplication::translate("TerminalStatuses", "#network_error"))); | |||
append(ETerminalError::AccountBalanceError, SStatusCodeSpecification(SDK::Driver::EWarningLevel::Error, "AccountBalanceError", QCoreApplication::translate("TerminalStatuses", "#account_balance_error"))); | |||
append(ETerminalError::InterfaceLocked, SStatusCodeSpecification(SDK::Driver::EWarningLevel::Error, "InterfaceLocked", QCoreApplication::translate("TerminalStatuses", "#interface_locked"))); | |||
} | |||
SDK::Driver::EWarningLevel::Enum warningLevelByStatus(int aStatus) // именно статус, а не статус-код! | |||
{ | |||
foreach(const SStatusCodeSpecification & statusCodeSpecification, mBuffer.values()) | |||
{ | |||
if (statusCodeSpecification.status == aStatus) | |||
{ | |||
return statusCodeSpecification.warningLevel; | |||
} | |||
} | |||
return SDK::Driver::EWarningLevel::OK; | |||
} | |||
}; | |||
typedef QSharedPointer<CSpecifications> PSpecifications; | |||
static CSpecifications Specification; | |||
} | |||
#define GET_STATUS_DESCRIPTION(aCode) DeviceStatusCode::Specification[DeviceStatusCode::aCode].description | |||
//-------------------------------------------------------------------------------- |
@@ -20,86 +20,56 @@ | |||
<context> | |||
<name>PrintFiscalCommand</name> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="100"/> | |||
<location filename="../Services/PrintingCommands.cpp" line="102"/> | |||
<source>#bank_fee</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="101"/> | |||
<location filename="../Services/PrintingCommands.cpp" line="103"/> | |||
<source>#dealer_fee</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="107"/> | |||
<location filename="../Services/PrintingCommands.cpp" line="109"/> | |||
<source>#processing_fee</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
</context> | |||
<context> | |||
<name>PrintPayment</name> | |||
<name>TerminalStatuses</name> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="245"/> | |||
<source>#tax_system</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="19"/> | |||
<source>#ok</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="246"/> | |||
<source>#kkt_timestamp</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="21"/> | |||
<source>#key_error</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="247"/> | |||
<source>#kkt_znm</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="22"/> | |||
<source>#config_error</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="248"/> | |||
<source>#kkt_rnm</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="23"/> | |||
<source>#database_error</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="249"/> | |||
<source>#kkt_session</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="24"/> | |||
<source>#network_error</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="250"/> | |||
<source>#kkt_fd_serial</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="25"/> | |||
<source>#account_balance_error</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="251"/> | |||
<source>#kkt_fn</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="252"/> | |||
<source>#kkt_fd</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="253"/> | |||
<source>#kkt_fp</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="255"/> | |||
<source>#tax_amount_02</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="256"/> | |||
<source>#tax_amount_03</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="257"/> | |||
<source>#tax_amount_04</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="258"/> | |||
<source>#tax_amount_05</source> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="26"/> | |||
<source>#interface_locked</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
</context> | |||
@@ -108,22 +78,22 @@ | |||
<message> | |||
<location filename="../SplashScreen/splash_screen_scene.qml" line="48"/> | |||
<source>#terminal_not_available</source> | |||
<translation>Terminal ist temporär außer Betrieb.</translation> | |||
<translation type="unfinished">Terminal ist temporär außer Betrieb.</translation> | |||
</message> | |||
<message> | |||
<location filename="../SplashScreen/splash_screen_scene.qml" line="55"/> | |||
<source>#dont_power_off_terminal</source> | |||
<translation>Software wird aktualisiert. Stromversorgung nicht abschalten!</translation> | |||
<translation type="unfinished">Software wird aktualisiert. Stromversorgung nicht abschalten!</translation> | |||
</message> | |||
<message> | |||
<location filename="../SplashScreen/splash_screen_scene.qml" line="65"/> | |||
<source>#terminal</source> | |||
<translation>Terminal: %1</translation> | |||
<translation type="unfinished">Terminal: %1</translation> | |||
</message> | |||
<message> | |||
<location filename="../SplashScreen/splash_screen_scene.qml" line="74"/> | |||
<source>#support</source> | |||
<translation>Support-Telefon: %1</translation> | |||
<translation type="unfinished">Support-Telefon: %1</translation> | |||
</message> | |||
</context> | |||
</TS> |
@@ -20,87 +20,57 @@ | |||
<context> | |||
<name>PrintFiscalCommand</name> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="100"/> | |||
<location filename="../Services/PrintingCommands.cpp" line="102"/> | |||
<source>#bank_fee</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="101"/> | |||
<location filename="../Services/PrintingCommands.cpp" line="103"/> | |||
<source>#dealer_fee</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="107"/> | |||
<location filename="../Services/PrintingCommands.cpp" line="109"/> | |||
<source>#processing_fee</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
</context> | |||
<context> | |||
<name>PrintPayment</name> | |||
<name>TerminalStatuses</name> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="245"/> | |||
<source>#tax_system</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="19"/> | |||
<source>#ok</source> | |||
<translation>OK</translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="246"/> | |||
<source>#kkt_timestamp</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="21"/> | |||
<source>#key_error</source> | |||
<translation>Keys corrupted</translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="247"/> | |||
<source>#kkt_znm</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="22"/> | |||
<source>#config_error</source> | |||
<translation>Config files corrupted</translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="248"/> | |||
<source>#kkt_rnm</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="23"/> | |||
<source>#database_error</source> | |||
<translation>Database error</translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="249"/> | |||
<source>#kkt_session</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="24"/> | |||
<source>#network_error</source> | |||
<translation>Network error</translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="250"/> | |||
<source>#kkt_fd_serial</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="25"/> | |||
<source>#account_balance_error</source> | |||
<translation>Account balance error</translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="251"/> | |||
<source>#kkt_fn</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="252"/> | |||
<source>#kkt_fd</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="253"/> | |||
<source>#kkt_fp</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="255"/> | |||
<source>#tax_amount_02</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="256"/> | |||
<source>#tax_amount_03</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="257"/> | |||
<source>#tax_amount_04</source> | |||
<translation type="unfinished"></translation> | |||
</message> | |||
<message> | |||
<location filename="../Services/PrintingCommands.cpp" line="258"/> | |||
<source>#tax_amount_05</source> | |||
<translation type="unfinished"></translation> | |||
<location filename="../Services/TerminalStatusDescriptions.h" line="26"/> | |||
<source>#interface_locked</source> | |||
<translation>User interface locked</translation> | |||
</message> | |||