From 0fb36fd8b180057e2ca237689dba4d8ec49e5577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Fri, 11 Aug 2023 18:01:46 -0300 Subject: [PATCH 01/39] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20vers=C3=A3o=20Hor?= =?UTF-8?q?se=20pra=203.1.4=20e=20adi=C3=A7=C3=A3o=20de=20GitIgnore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ boss-lock.json | 20 +++++------ boss.json | 2 +- src/wsHorse.pas | 9 +++++ 4 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..706c5ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,90 @@ +# Uncomment these types if you want even more clean repository. But be careful. +# It can make harm to an existing project source. Read explanations below. +# +# Resource files are binaries containing manifest, project icon and version info. +# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. +#*.res +# +# Type library file (binary). In old Delphi versions it should be stored. +# Since Delphi 2009 it is produced from .ridl file and can safely be ignored. +#*.tlb +# +# Diagram Portfolio file. Used by the diagram editor up to Delphi 7. +# Uncomment this if you are not using diagrams or use newer Delphi version. +#*.ddp +# +# Visual LiveBindings file. Added in Delphi XE2. +# Uncomment this if you are not using LiveBindings Designer. +#*.vlb +# +# Deployment Manager configuration file for your project. Added in Delphi XE2. +# Uncomment this if it is not mobile development and you do not use remote debug feature. +#*.deployproj +# +# C++ object files produced when C/C++ Output file generation is configured. +# Uncomment this if you are not using external objects (zlib library for example). +#*.obj +# + +# Delphi compiler-generated binaries (safe to delete) +*.exe +*.dll +*.bpl +*.bpi +*.dcp +*.so +*.apk +*.drc +*.map +*.dres +*.rsm +*.tds +*.dcu +*.lib +*.a +*.o +*.ocx +*.res + +# Permitindo RLReport.res +!/**/RLReport.res + +# Delphi autogenerated files (duplicated info) +*.cfg +*.hpp +*Resource.rc + +# Delphi local files (user-specific info) +*.local +*.identcache +*.projdata +*.tvsconfig +*.dsk +*.deployproj + +# Delphi local directory +Linux64/ + +# Delphi history and backups +__history/ +__recovery/ +*.~* + +# Log do LSP +*.delphilsp.json + +# Castalia statistics file (since XE7 Castalia is distributed with Delphi) +*.stat +/*.skincfg +**/modules + +#/lib liberada para registrar alterações (temporárias) nas units do ACBr ou Fortes + +#Exe Folder +*/win32 +*/win64 +**/win64 + + +# Firebird databases +*.FBD \ No newline at end of file diff --git a/boss-lock.json b/boss-lock.json index 8705499..e0d2f93 100644 --- a/boss-lock.json +++ b/boss-lock.json @@ -4,40 +4,40 @@ "installedModules": { "github.com/hashload/horse": { "name": "horse", - "version": "v2.0.6", - "hash": "cca1769dfab681cfd26ae8499f9045e1", + "version": "3.1.4", + "hash": "713a199453748dff73e141f5110d3d9b", "artifacts": {}, "failed": false, "changed": false }, "github.com/hashload/jhonson": { "name": "jhonson", - "version": "1.0.7", - "hash": "e0a2cfad431f565769ebe2815299924b", + "version": "1.1.6", + "hash": "6408c0964998a945994d4bf29d2c88c5", "artifacts": {}, "failed": false, "changed": false }, "https://github.com/hashload/handle-exception": { "name": "handle-exception", - "version": "0.1.4", - "hash": "1152772d75f59dbb562cc7b7711a8ebe", + "version": "0.1.8", + "hash": "362736186bc6293dd9a716d7f7413455", "artifacts": {}, "failed": false, "changed": false }, "https://github.com/hashload/horse-octet-stream": { "name": "horse-octet-stream", - "version": "1.9.3", - "hash": "fcc0cde73c6b14672d22f5f5fb2335e2", + "version": "1.9.9", + "hash": "c7b52b334f166edea1313c94b2ac170c", "artifacts": {}, "failed": false, "changed": false }, "https://github.com/hashload/jhonson": { "name": "jhonson", - "version": "1.0.7", - "hash": "e0a2cfad431f565769ebe2815299924b", + "version": "1.1.6", + "hash": "6408c0964998a945994d4bf29d2c88c5", "artifacts": {}, "failed": false, "changed": true diff --git a/boss.json b/boss.json index 81c2bce..41939c1 100644 --- a/boss.json +++ b/boss.json @@ -6,7 +6,7 @@ "mainsrc": "./", "projects": [], "dependencies": { - "github.com/hashload/horse": "^v2.0.6", + "github.com/hashload/horse": "^3.1.4", "https://github.com/hashload/handle-exception": "^0.1.4", "https://github.com/hashload/horse-octet-stream": "^1.9.2", "https://github.com/hashload/jhonson": "^1.0.7" diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 69ab1e6..cef7ab8 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -39,6 +39,15 @@ procedure TWsHorse.AddMethods; begin with FHorse do begin + + Get('/api/version', + procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) + begin + var LVersao := TJsonObject.Create; + LVersao.AddPair('horseVersion', FHorse.Version); + Res.Send(LVersao); + end); + Get('/api/gtin/:id', procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) var From 0464e4cd3ec5649bdf46bfbf45c5974cf820607c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 09:32:55 -0300 Subject: [PATCH 02/39] =?UTF-8?q?Utilizando=20a=20lib=20de=20conex=C3=A3o?= =?UTF-8?q?=20de=20banco=20de=20dados=20ao=20inv=C3=A9s=20da=20main.baseda?= =?UTF-8?q?dos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGtin.Aplication.dproj | 504 ++++++++++++++++------------------- WsGtin.Aplication.res | Bin 59568 -> 112368 bytes WsGtin.Service.dproj | 455 ++++++++++++++++---------------- src/wsHorse.pas | 564 +++++++++++++++++++++------------------- 4 files changed, 744 insertions(+), 779 deletions(-) diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 0392914..6da1f8e 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -1,11 +1,11 @@  {91B0D264-9633-46D9-A661-37D36B990E57} - 18.8 + 19.5 VCL WsGTin.Aplication.dpr True - Release + Debug Win32 1 Application @@ -58,7 +58,9 @@ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png WsGTin_Aplication - modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;$(DCC_UnitSearchPath) + modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;..\pascal-database-engine\src;$(DCC_UnitSearchPath) + 1046 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= .\.dcu @@ -86,7 +88,6 @@ 1033 true false - true PerMonitorV2 @@ -117,10 +118,6 @@
BaseDados
dfm - - Cfg_2 - Base - Base @@ -128,6 +125,10 @@ Cfg_1 Base + + Cfg_2 + Base + Delphi.Personality.12 @@ -138,24 +139,13 @@ WsGTin.Aplication.dpr - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - Express Cross Platform Library Icon Library by Developer Express Inc. + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components - - - - WsGTin_Aplication.exe - true - - - - - WsGtin_Aplication.exe - true - - + + + 1 @@ -168,14 +158,14 @@ 0 - + classes - 1 + 64 classes - 1 + 64 @@ -220,7 +210,6 @@ 1 - library\lib\armeabi-v7a @@ -297,6 +286,16 @@ 1 + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + res\drawable-ldpi @@ -460,6 +459,11 @@ 1 .framework + + Contents\MacOS + 1 + .framework + 0 @@ -473,7 +477,7 @@ 1 .dylib - + 1 .dylib @@ -487,6 +491,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .dll;.bpl @@ -501,7 +510,7 @@ 1 .dylib - + 1 .dylib @@ -515,6 +524,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .bpl @@ -533,7 +547,7 @@ 0 - + 0 @@ -544,489 +558,417 @@ Contents\Resources\StartUp\ 0 + + Contents\Resources\StartUp\ + 0 + 0 - - - 1 - - + + 1 - + 1 - - - 1 - - + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - - + + + ..\ 1 - + + ..\ 1 - + + ..\ 1 - - + + + Contents 1 - + + Contents 1 - + + Contents 1 - - + + + Contents\Resources 1 - + + Contents\Resources 1 - + + Contents\Resources 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - + + library\lib\arm64-v8a 1 - - 1 1 - + 1 - - - - 1 - - + 1 - + + Contents\MacOS 1 - - - + + Contents\MacOS 1 - + + Contents\MacOS 1 - - 1 + + 0 - - - 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - - - 1 - - + + 1 - + 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\ 1 + ..\ 1 - + + ..\ 1 - + 1 1 - + 1 - - - 1 - + - 1 + ..\$(PROJECTNAME).launchscreen + 64 - - 1 + + ..\$(PROJECTNAME).launchscreen + 64 - + 1 1 - + 1 - - - 1 - - + + + Assets 1 - + + Assets 1 - - - 1 - - + + + Assets 1 - + + Assets 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - 1 - - - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - - ..\ - 1 - - - ..\ + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - ..\ + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - ..\ + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - Contents + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Contents + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Contents\Resources + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Contents\Resources + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - 1 - - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Contents\MacOS - 1 - - - Contents\MacOS - 1 - - - 0 - - - - library\lib\armeabi-v7a - 1 - - - - + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Assets + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Assets + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Assets + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Assets + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - + + + + + - - - - + + + True diff --git a/WsGtin.Aplication.res b/WsGtin.Aplication.res index b59d324edd90caa7073776238281cdf49facc94c..2c67ee1a3522d8e4e610e73b2dfa5334ad9140ac 100644 GIT binary patch literal 112368 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 ~`}xgtWVMY4lN(MqNx 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 M4gV6`QCimj2j^hrSpWb4 literal 59568 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 diff --git a/WsGtin.Service.dproj b/WsGtin.Service.dproj index 017c884..c2c36f5 100644 --- a/WsGtin.Service.dproj +++ b/WsGtin.Service.dproj @@ -1,7 +1,7 @@  {74221D93-CE31-4153-8CF8-83AAFE083CB7} - 18.8 + 19.5 VCL WsGTin.Service.dpr True @@ -67,14 +67,17 @@ $(BDS)\bin\delphi_PROJECTICON.ico $(BDS)\bin\delphi_PROJECTICNS.icns WsGTin_Service - $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src + $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src +
DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;fmx;FireDACIBDriver;xmlrtl;soapmidas;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage) android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;fmx;FireDACIBDriver;xmlrtl;soapmidas;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage) android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;Tee;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage) @@ -120,10 +123,6 @@ dfm TService - - Cfg_2 - Base - Base @@ -131,6 +130,10 @@ Cfg_1 Base + + Cfg_2 + Base + Delphi.Personality.12 @@ -141,13 +144,8 @@ WsGTin.Service.dpr - - - - WsGTin_Service.exe - true - - + + 1 @@ -160,14 +158,14 @@ 0 - + classes - 1 + 64 classes - 1 + 64 @@ -288,6 +286,16 @@ 1 + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + res\drawable-ldpi @@ -451,6 +459,11 @@ 1 .framework + + Contents\MacOS + 1 + .framework + 0 @@ -464,7 +477,7 @@ 1 .dylib - + 1 .dylib @@ -478,6 +491,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .dll;.bpl @@ -492,7 +510,7 @@ 1 .dylib - + 1 .dylib @@ -506,6 +524,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .bpl @@ -524,7 +547,7 @@ 0 - + 0 @@ -535,445 +558,417 @@ Contents\Resources\StartUp\ 0 + + Contents\Resources\StartUp\ + 0 + 0 - - - 1 - - + + 1 - + 1 - - - 1 - - + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - - + + + ..\ 1 - + + ..\ 1 - + + ..\ 1 - - + + + Contents 1 - + + Contents 1 - + + Contents 1 - - + + + Contents\Resources 1 - + + Contents\Resources 1 - + + Contents\Resources 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - + + library\lib\arm64-v8a 1 - - 1 1 - + 1 - - - - 1 - - + 1 - + + Contents\MacOS 1 - - - + + Contents\MacOS 1 - + + Contents\MacOS 1 - - 1 + + 0 - - + + + library\lib\armeabi-v7a 1 - + + + 1 - + 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\ 1 + ..\ 1 - + + ..\ 1 - + 1 1 - + 1 - - - 1 - + - 1 + ..\$(PROJECTNAME).launchscreen + 64 - - 1 + + ..\$(PROJECTNAME).launchscreen + 64 - + 1 1 - + 1 - - - 1 - - + + + Assets 1 - + + Assets 1 - - - 1 - - + + + Assets 1 - + + Assets 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - + - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - - 1 - - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - ..\ - 1 - + - ..\ + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - - - ..\ + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - ..\ + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - Contents + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - Contents + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - Contents\Resources + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Contents\Resources + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - 1 - - - Contents\MacOS - 1 - - - Contents\MacOS + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - 0 - - - - - library\lib\armeabi-v7a + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Assets + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Assets + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Assets + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Assets + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - + + + + + - - - - + + + False diff --git a/src/wsHorse.pas b/src/wsHorse.pas index cef7ab8..d0a62b8 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -3,14 +3,27 @@ interface uses Horse, Horse.Jhonson, Horse.OctetStream, Horse.HandleException, - System.SysUtils, System.Net.HttpClientComponent, System.Net.HttpClient; + System.SysUtils, System.Net.HttpClientComponent, System.Net.HttpClient, + + Database.Tipos; type + TConnectionDefDriverParams = Database.Tipos.TConnectionDefDriverParams; + TConnectionDefParams = Database.Tipos.TConnectionDefParams; + TConnectionDefPoolParams = Database.Tipos.TConnectionDefPoolParams; + TWsHorse = class private FHorse: THorse; FPath: String; + + FDBParams: TConnectionDefParams; + FDBDriverParams: TConnectionDefDriverParams; + FDBPoolParams: TConnectionDefPoolParams; + procedure AddMethods; + + procedure LoadDatabaseConfig; public constructor Create; function Port(Value: Integer): TWsHorse; @@ -26,7 +39,13 @@ TWsHorse = class implementation uses - System.Classes, System.IOUtils, main.view, main.basedados, system.JSON; + System.Classes, + System.IOUtils, + main.view, + //main.basedados, + system.JSON, + + Database.Factory; { TWsHorse } @@ -157,37 +176,34 @@ procedure TWsHorse.AddMethods; begin if Req.Params.Items['id'] <> '' then begin - if basedados.fdConnection1.Connected= false then - basedados.fdConnection1.Connected:=true; - if mainview.MemoHistorico.lines.count > 10000 then mainview.MemoHistorico.lines.clear; - with BaseDados.fdquery1 do + var ds:= TDatabaseFactory.New.SQL + .SQL('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean') + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open; + + if ds.IsEmpty = false then begin - close; - sql.Clear; -// sql.Add('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria, tributacao from cad_produtos where ean = :ean'); - sql.Add('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean'); - parambyname('ean').AsString:=Req.Params.Items['id']; - open; - if isempty = false then - begin - Res.Send(fieldbyname('nome').asstring).Status(200); - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+Req.Params.Items['id']+ '|' +fieldbyname('nome').asstring); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; + Res.Send(ds.FieldByName('nome').asstring).Status(200); + inc(cont200); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+ + Req.Params.Items['id']+ '|' +ds.FieldByName('nome').AsString); + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + inc(cont404); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+ + timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally end; end; end @@ -216,34 +232,32 @@ procedure TWsHorse.AddMethods; if mainview.MemoHistorico.lines.count > 10000 then mainview.MemoHistorico.lines.clear; - if basedados.fdConnection1.Connected= false then - basedados.fdConnection1.Connected:=true; + var ds := TDatabaseFactory.New.SQL + .SQL('select nome from unidade_medida where id = :id') + .ParamList + .AddString('id', Req.Params.Items['id']) + .&End + .Open; - with BaseDados.fdquery1 do + if not ds.IsEmpty then begin - close; - sql.Clear; - sql.Add('select nome from unidade_medida where id = :id'); - parambyname('id').AsString:=Req.Params.Items['id']; - open; - if isempty = false then - begin - Res.Send(fieldbyname('nome').asstring).Status(200); - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+Req.Params.Items['id']+ '|' +fieldbyname('nome').asstring); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; + Res.Send(ds.FieldByName('nome').asstring).Status(200); + inc(cont200); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ + timetostr(now)+'| Entregue descricao unidade medida: '+Req.Params.Items['id']+ '|' + + ds.FieldByName('nome').asstring); + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + + inc(cont404); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); + finally end; end; end @@ -274,44 +288,41 @@ procedure TWsHorse.AddMethods; if mainview.MemoHistorico.lines.count > 10000 then mainview.MemoHistorico.lines.clear; - if basedados.fdConnection1.Connected= false then - basedados.fdConnection1.Connected:=true; + var ds := TDatabaseFactory.New.SQL + .SQL('select id, nome from unidade_medida where id = :id') + .ParamList + .AddString('id', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('id',removeacento(ds.FieldByName('id').AsString))); + wjson.AddPair(tjsonpair.Create('nome',removeacento(ds.FieldByName('nome').AsString))); + Res.Send(wjson).Status(200);; + + inc(cont200); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+ + Req.Params.Items['id']+ '|' +ds.fieldbyname('nome').asstring); - with BaseDados.fdquery1 do + finally + end; + end + else begin - close; - sql.Clear; - sql.Add('select id, nome from unidade_medida where id = :id'); - parambyname('id').AsString:=Req.Params.Items['id']; - open; - if isempty = false then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('id',removeacento(fieldbyname('id').asstring))); - wjson.AddPair(tjsonpair.Create('nome',removeacento(fieldbyname('nome').asstring))); - Res.Send(wjson).Status(200);; - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+Req.Params.Items['id']+ '|' +fieldbyname('nome').asstring); - - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + + inc(cont404); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); + finally end; end; end @@ -342,61 +353,58 @@ procedure TWsHorse.AddMethods; if mainview.MemoHistorico.lines.count > 10000 then mainview.MemoHistorico.lines.clear; - if basedados.fdConnection1.Connected= false then - basedados.fdConnection1.Connected:=true; - with BaseDados.fdquery1 do + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then begin - close; - sql.Clear; -// sql.Add('SELECT base_produtos.cad_produtos.ean, base_produtos.cad_produtos.nome, base_produtos.cad_produtos.peso,'); - sql.Add('SELECT base_produtos.cad_produtos.ean, base_produtos.cad_produtos.nome, '); - sql.Add('base_produtos.cad_produtos.ncm, base_produtos.cad_produtos.cest_codigo, base_produtos.cad_produtos.embalagem, base_produtos.cad_produtos.quantidade_embalagem,'); -// sql.Add('base_produtos.cad_produtos.marca, base_produtos.cad_produtos.categoria, base_produtos.cad_produtos.id_categoria, base_produtos.cad_produtos.tributacao'); -// sql.Add('base_produtos.cad_produtos.marca, base_produtos.cad_produtos.categoria, base_produtos.cad_produtos.id_categoria'); - sql.Add('base_produtos.cad_produtos.marca, base_produtos.cad_produtos.categoria'); - sql.Add(' FROM base_produtos.cad_produtos'); - sql.Add('where ean = :ean'); - parambyname('ean').AsString:=Req.Params.Items['id']; - open; - - if isempty = false then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(fieldbyname('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(fieldbyname('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(fieldbyname('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(fieldbyname('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(fieldbyname('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(fieldbyname('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(fieldbyname('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(fieldbyname('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(fieldbyname('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(fieldbyname('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +fieldbyname('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); + wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); + wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); + wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); + wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); +// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); + wjson.AddPair(tjsonpair.Create('Peso','')); +// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); + wjson.AddPair(tjsonpair.Create('id_categoria','')); +// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); + wjson.AddPair(tjsonpair.Create('tributacao','')); + Res.Send(wjson).Status(200);; + + inc(cont200); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ + timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); + finally + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + + inc(cont404); + mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally end; end; end @@ -414,6 +422,7 @@ procedure TWsHorse.AddMethods; end; end; end); + //************ Get('/api/desc200/:id', @@ -425,71 +434,68 @@ procedure TWsHorse.AddMethods; if mainview.MemoHistorico.lines.count > 10000 then mainview.MemoHistorico.lines.clear; - if basedados.fdConnection1.Connected= false then - basedados.fdConnection1.Connected:=true; - with BaseDados.fdquery1 do + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); + wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); + wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); + wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); + wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); +// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); + wjson.AddPair(tjsonpair.Create('Peso','')); +// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); + wjson.AddPair(tjsonpair.Create('id_categoria','')); +// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); + wjson.AddPair(tjsonpair.Create('tributacao','')); + Res.Send(wjson).Status(200);; + + inc(cont200); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ + timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); + finally + end; + end + else begin - close; - sql.Clear; - sql.Add('SELECT base_produtos.cad_produtos.ean, base_produtos.cad_produtos.nome, '); -// sql.Add('SELECT base_produtos.cad_produtos.ean, base_produtos.cad_produtos.nome, base_produtos.cad_produtos.peso,'); - sql.Add('base_produtos.cad_produtos.ncm, base_produtos.cad_produtos.cest_codigo, base_produtos.cad_produtos.embalagem, base_produtos.cad_produtos.quantidade_embalagem,'); -// sql.Add('base_produtos.cad_produtos.marca, base_produtos.cad_produtos.categoria, base_produtos.cad_produtos.id_categoria, base_produtos.cad_produtos.tributacao'); -// sql.Add('base_produtos.cad_produtos.marca, base_produtos.cad_produtos.categoria, base_produtos.cad_produtos.id_categoria'); - sql.Add('base_produtos.cad_produtos.marca, base_produtos.cad_produtos.categoria'); - sql.Add(' FROM base_produtos.cad_produtos'); - sql.Add('where ean = :ean'); - parambyname('ean').AsString:=Req.Params.Items['id']; - open; - - if isempty = false then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(fieldbyname('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(fieldbyname('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(fieldbyname('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(fieldbyname('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(fieldbyname('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(fieldbyname('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(fieldbyname('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(fieldbyname('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(fieldbyname('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(fieldbyname('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +fieldbyname('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','404')); - wjson.AddPair(tjsonpair.Create('Nome','404')); - wjson.AddPair(tjsonpair.Create('Ncm','404')); - wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); - wjson.AddPair(tjsonpair.Create('Embalagem','404')); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); - wjson.AddPair(tjsonpair.Create('Marca','404')); - wjson.AddPair(tjsonpair.Create('Categoria','404')); - wjson.AddPair(tjsonpair.Create('Peso','0')); - wjson.AddPair(tjsonpair.Create('id_categoria','0')); - wjson.AddPair(tjsonpair.Create('tributacao','404')); - Res.Send(wjson).Status(200);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','404')); + wjson.AddPair(tjsonpair.Create('Nome','404')); + wjson.AddPair(tjsonpair.Create('Ncm','404')); + wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); + wjson.AddPair(tjsonpair.Create('Embalagem','404')); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); + wjson.AddPair(tjsonpair.Create('Marca','404')); + wjson.AddPair(tjsonpair.Create('Categoria','404')); + wjson.AddPair(tjsonpair.Create('Peso','0')); + wjson.AddPair(tjsonpair.Create('id_categoria','0')); + wjson.AddPair(tjsonpair.Create('tributacao','404')); + Res.Send(wjson).Status(200);; + + inc(cont404); + mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally end; end; end @@ -521,63 +527,58 @@ procedure TWsHorse.AddMethods; if mainview.MemoHistorico.lines.count > 10000 then mainview.MemoHistorico.lines.clear; - if basedados.fdConnection1.Connected= false then - basedados.fdConnection1.Connected:=true; - + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + oini:=TStringList.Create; + oini.Add('[GENERAL]'); + oini.Add('Nome='+removeacento(ds.FieldByName('nome').asstring)); + oini.Add('Ncm='+removeacento(ds.FieldByName('ncm').asstring)); + oini.Add('Cest_Codigo='+removeacento(ds.FieldByName('cest_codigo').asstring)); + oini.Add('Embalagem='+removeacento(ds.FieldByName('embalagem').asstring)); + oini.Add('QuantidadeEmbalagem='+removeacento(ds.FieldByName('quantidade_embalagem').asstring)); + oini.Add('Marca='+removeacento(ds.FieldByName('marca').asstring)); + oini.Add('Categoria='+removeacento(ds.FieldByName('categoria').asstring)); + oini.Add('Peso='+''); +// oini.Add('id_categoria='+removeacento(ds.FieldByName('id_categoria').asstring)); + oini.Add('id_categoria='+''); +// oini.Add('tributacao'+removeacento(ds.FieldByName('tributacao').asstring)); + oini.Add('tributacao='+''); + Res.Send(oini.TEXT).Status(200); + + freeandnil(oini); - with BaseDados.fdquery1 do + inc(cont200); + mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ + timetostr(now)+'| Entregue INI: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); + finally + end; + end + else begin - close; - sql.Clear; -// sql.Add('SELECT cad_produtos.ean, cad_produtos.nome, cad_produtos.peso,'); - sql.Add('SELECT cad_produtos.ean, cad_produtos.nome, '); - sql.Add('cad_produtos.ncm, cad_produtos.cest_codigo, cad_produtos.embalagem, cad_produtos.quantidade_embalagem,'); -// sql.Add('cad_produtos.marca, cad_produtos.categoria, cad_produtos.id_categoria, cad_produtos.tributacao'); -// sql.Add('cad_produtos.marca, cad_produtos.categoria, cad_produtos.id_categoria'); - sql.Add('cad_produtos.marca, cad_produtos.categoria'); - sql.Add(' FROM cad_produtos'); - sql.Add('where ean = :ean'); - parambyname('ean').AsString:=Req.Params.Items['id']; - open; - - if isempty = false then - begin - try - oini:=TStringList.Create; - oini.Add('[GENERAL]'); - oini.Add('Nome='+removeacento(fieldbyname('nome').asstring)); - oini.Add('Ncm='+removeacento(fieldbyname('ncm').asstring)); - oini.Add('Cest_Codigo='+removeacento(fieldbyname('cest_codigo').asstring)); - oini.Add('Embalagem='+removeacento(fieldbyname('embalagem').asstring)); - oini.Add('QuantidadeEmbalagem='+removeacento(fieldbyname('quantidade_embalagem').asstring)); - oini.Add('Marca='+removeacento(fieldbyname('marca').asstring)); - oini.Add('Categoria='+removeacento(fieldbyname('categoria').asstring)); - oini.Add('Peso='+''); -// oini.Add('id_categoria='+removeacento(fieldbyname('id_categoria').asstring)); - oini.Add('id_categoria='+''); -// oini.Add('tributacao'+removeacento(fieldbyname('tributacao').asstring)); - oini.Add('tributacao='+''); - Res.Send(oini.TEXT).Status(200); - - freeandnil(oini); - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue INI: '+Req.Params.Items['id']+ '|' +fieldbyname('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + + inc(cont404); + mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally end; end; end @@ -596,16 +597,15 @@ procedure TWsHorse.AddMethods; end; end; end); - //************ - - - + //************ end; end; constructor TWsHorse.Create; begin + LoadDatabaseConfig; + FHorse := THorse.Create; with FHorse do begin @@ -616,6 +616,34 @@ constructor TWsHorse.Create; AddMethods; end; +procedure TWsHorse.LoadDatabaseConfig; +begin + FDBParams.ConnectionDefName := 'bd_teste'; + FDBParams.Database := 'base_produtos'; + FDBParams.UserName := 'sacfiscal'; + FDBParams.Password := 'Abc123abcc#'; + FDBParams.Server := '127.0.0.1'; + FDBParams.Port := 3306; + + FDBDriverParams.DriverID := 'MySQL'; + FDBDriverParams.DriverDefName := 'MYSQL_DRIVER'; + FDBDriverParams.VendorLib := 'C:\#DEV\#Projetos\eanpictures4D\Win32\Debug\libmysql.dll'; + + FDBParams.LocalConnection := False; + FDBPoolParams.Pooled := True; + + FDBPoolParams.PoolMaximumItems := 50; + FDBPoolParams.PoolCleanupTimeout := 30000; + FDBPoolParams.PoolExpireTimeout := 60000; + + TDatabaseFactory.New + .Conexao + .SetConnectionDefDriverParams(FDBDriverParams) + .SetConnectionDefParams(FDBParams) + .SetConnectionDefPoolParams(FDBPoolParams) + .IniciaPoolConexoes; +end; + function TWsHorse.Port(Value: Integer): TWsHorse; begin Result := Self; From a868aed6a910f7da4e090dbc9c50621768afdf59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 09:41:24 -0300 Subject: [PATCH 03/39] Removido main.basedados do projeto --- WsGTin.Aplication.dpr | 4 +--- WsGtin.Aplication.dproj | 10 ++++++---- src/main.basedados.dfm | 4 ++-- src/main.view.dfm | 23 +++++++++++++---------- src/main.view.pas | 2 +- src/wsHorse.pas | 1 - 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index fc593f3..5b93ec7 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -4,8 +4,7 @@ uses Vcl.Forms, main.view in 'src\main.view.pas' {MainView}, wsHorse in 'src\wsHorse.pas', - main.control in 'src\main.control.pas', - main.basedados in 'src\main.basedados.pas' {BaseDados}; + main.control in 'src\main.control.pas'; {$R *.res} @@ -13,6 +12,5 @@ begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TMainView, MainView); - Application.CreateForm(TBaseDados, BaseDados); application.Run; end. diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 6da1f8e..23055b6 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -114,10 +114,6 @@ - -
BaseDados
- dfm -
Base @@ -145,6 +141,12 @@ + + + WsGtin_Aplication.exe + true + + diff --git a/src/main.basedados.dfm b/src/main.basedados.dfm index 3c1da1a..fa1d36f 100644 --- a/src/main.basedados.dfm +++ b/src/main.basedados.dfm @@ -2,8 +2,8 @@ object BaseDados: TBaseDados Left = 0 Top = 0 Caption = 'BaseDados' - ClientHeight = 231 - ClientWidth = 375 + ClientHeight = 230 + ClientWidth = 371 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText diff --git a/src/main.view.dfm b/src/main.view.dfm index a2e6b17..a412d75 100644 --- a/src/main.view.dfm +++ b/src/main.view.dfm @@ -2,39 +2,40 @@ object MainView: TMainView Left = 0 Top = 0 Caption = 'Servidor EanPictures 2.9 - Sac Fiscal | Firedac' - ClientHeight = 571 - ClientWidth = 1008 + ClientHeight = 570 + ClientWidth = 1004 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] - OldCreateOrder = False OnCreate = FormCreate - PixelsPerInch = 96 TextHeight = 13 object Panel1: TPanel Left = 0 Top = 0 - Width = 1008 + Width = 1004 Height = 41 Align = alTop Caption = 'Server' TabOrder = 0 + ExplicitWidth = 1012 end object Panel3: TPanel Left = 0 - Top = 530 - Width = 1008 + Top = 529 + Width = 1004 Height = 41 Align = alBottom TabOrder = 1 + ExplicitTop = 531 + ExplicitWidth = 1012 DesignSize = ( - 1008 + 1004 41) object btnPower: TBitBtn - Left = 862 + Left = 858 Top = 5 Width = 142 Height = 30 @@ -42,9 +43,10 @@ object MainView: TMainView Caption = 'Start' TabOrder = 0 OnClick = btnPowerClick + ExplicitLeft = 866 end object btnSaveConfig: TBitBtn - Left = 661 + Left = 658 Top = 5 Width = 75 Height = 30 @@ -52,6 +54,7 @@ object MainView: TMainView Caption = 'Save Config' TabOrder = 1 OnClick = btnSaveConfigClick + ExplicitLeft = 664 end end object Panel2: TPanel diff --git a/src/main.view.pas b/src/main.view.pas index fc6a48b..cabb03a 100644 --- a/src/main.view.pas +++ b/src/main.view.pas @@ -42,7 +42,7 @@ TMainView = class(TForm) // umerro, umok: integer; implementation -uses main.basedados; + {$R *.dfm} procedure TMainView.FormCreate(Sender: TObject); diff --git a/src/wsHorse.pas b/src/wsHorse.pas index d0a62b8..5c058fb 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -42,7 +42,6 @@ implementation System.Classes, System.IOUtils, main.view, - //main.basedados, system.JSON, Database.Factory; From c09f0f97a6f204023939aa419e509a39c8e6a0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 09:42:19 -0300 Subject: [PATCH 04/39] removido main.basedados do repositorio --- src/main.basedados.dfm | 32 -------------------------------- src/main.basedados.pas | 31 ------------------------------- 2 files changed, 63 deletions(-) delete mode 100644 src/main.basedados.dfm delete mode 100644 src/main.basedados.pas diff --git a/src/main.basedados.dfm b/src/main.basedados.dfm deleted file mode 100644 index fa1d36f..0000000 --- a/src/main.basedados.dfm +++ /dev/null @@ -1,32 +0,0 @@ -object BaseDados: TBaseDados - Left = 0 - Top = 0 - Caption = 'BaseDados' - ClientHeight = 230 - ClientWidth = 371 - Color = clBtnFace - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'Tahoma' - Font.Style = [] - TextHeight = 13 - object fdQuery1: TFDQuery - Connection = FdConnection1 - Left = 208 - Top = 96 - end - object FdConnection1: TFDConnection - Params.Strings = ( - 'Server=127.0.0.1' - 'User_Name=sacfiscal' - 'Password=Abc123abcc#' - 'Database=base_produtos' - 'DriverID=MySQL') - ResourceOptions.AssignedValues = [rvAutoReconnect] - ResourceOptions.AutoReconnect = True - LoginPrompt = False - Left = 123 - Top = 91 - end -end diff --git a/src/main.basedados.pas b/src/main.basedados.pas deleted file mode 100644 index c6a5dfe..0000000 --- a/src/main.basedados.pas +++ /dev/null @@ -1,31 +0,0 @@ -unit main.basedados; - -interface - -uses - Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, - Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, - FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, - FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, - FireDAC.Phys, FireDAC.Phys.MySQL, FireDAC.Phys.MySQLDef, FireDAC.VCLUI.Wait, - FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, - FireDAC.Comp.DataSet, FireDAC.Comp.Client; - -type - TBaseDados = class(TForm) - fdQuery1: TFDQuery; - FdConnection1: TFDConnection; - private - { Private declarations } - public - { Public declarations } - end; - -var - BaseDados: TBaseDados; - -implementation - -{$R *.dfm} - -end. From 5a5df342bdfaedc9a7f0109b5418080e79453ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 09:46:17 -0300 Subject: [PATCH 05/39] =?UTF-8?q?Adicionada=20nova=20depend=C3=AAncia=20ht?= =?UTF-8?q?tps://github.com/iagoocesaar/pascal-database-engine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGtin.Aplication.dproj | 2 +- WsGtin.Service.dproj | 2 +- boss-lock.json | 10 +++++++++- boss.json | 3 ++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 23055b6..d79f21a 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -58,7 +58,7 @@ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png WsGTin_Aplication - modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;..\pascal-database-engine\src;$(DCC_UnitSearchPath) + ..\pascal-database-engine\src;$(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src 1046 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
diff --git a/WsGtin.Service.dproj b/WsGtin.Service.dproj index c2c36f5..11151eb 100644 --- a/WsGtin.Service.dproj +++ b/WsGtin.Service.dproj @@ -67,7 +67,7 @@ $(BDS)\bin\delphi_PROJECTICON.ico $(BDS)\bin\delphi_PROJECTICNS.icns WsGTin_Service - $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src + $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;fmx;FireDACIBDriver;xmlrtl;soapmidas;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage) diff --git a/boss-lock.json b/boss-lock.json index e0d2f93..2f1fe4c 100644 --- a/boss-lock.json +++ b/boss-lock.json @@ -40,7 +40,15 @@ "hash": "6408c0964998a945994d4bf29d2c88c5", "artifacts": {}, "failed": false, - "changed": true + "changed": false + }, + "https://github.com/iagoocesaar/pascal-database-engine": { + "name": "pascal-database-engine", + "version": "0.0.4", + "hash": "15ca79fdcab92295975b461669913bff", + "artifacts": {}, + "failed": false, + "changed": false } } } \ No newline at end of file diff --git a/boss.json b/boss.json index 41939c1..9de7bd8 100644 --- a/boss.json +++ b/boss.json @@ -9,6 +9,7 @@ "github.com/hashload/horse": "^3.1.4", "https://github.com/hashload/handle-exception": "^0.1.4", "https://github.com/hashload/horse-octet-stream": "^1.9.2", - "https://github.com/hashload/jhonson": "^1.0.7" + "https://github.com/hashload/jhonson": "^1.0.7", + "https://github.com/iagoocesaar/pascal-database-engine": "^0.0.4" } } \ No newline at end of file From 3ed616ade988d9fc81d5409ee52fba294e5785b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 10:56:31 -0300 Subject: [PATCH 06/39] =?UTF-8?q?Iniciando=20cria=C3=A7=C3=A3o=20de=20cont?= =?UTF-8?q?rollers=20-=20controller=20de=20unidade=20de=20medidas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGTin.Aplication.dpr | 5 +- WsGtin.Aplication.dproj | 5 +- src/controllers/Ean.Controllers.Produto.pas | 26 +++ src/controllers/Ean.Controllers.Registry.pas | 23 +++ .../Ean.Controllers.UnidadeMedida.pas | 149 ++++++++++++++++++ src/wsHorse.pas | 123 +-------------- 6 files changed, 211 insertions(+), 120 deletions(-) create mode 100644 src/controllers/Ean.Controllers.Produto.pas create mode 100644 src/controllers/Ean.Controllers.Registry.pas create mode 100644 src/controllers/Ean.Controllers.UnidadeMedida.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 5b93ec7..4c97095 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -4,7 +4,10 @@ uses Vcl.Forms, main.view in 'src\main.view.pas' {MainView}, wsHorse in 'src\wsHorse.pas', - main.control in 'src\main.control.pas'; + main.control in 'src\main.control.pas', + Ean.Controllers.Registry in 'src\controllers\Ean.Controllers.Registry.pas', + Ean.Controllers.Produto in 'src\controllers\Ean.Controllers.Produto.pas', + Ean.Controllers.UnidadeMedida in 'src\controllers\Ean.Controllers.UnidadeMedida.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index d79f21a..8ab3b66 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -58,7 +58,7 @@ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png WsGTin_Aplication - ..\pascal-database-engine\src;$(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src + ..\pascal-database-engine\src;modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src;$(DCC_UnitSearchPath) 1046 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= @@ -114,6 +114,9 @@ + + + Base diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/Ean.Controllers.Produto.pas new file mode 100644 index 0000000..3f73483 --- /dev/null +++ b/src/controllers/Ean.Controllers.Produto.pas @@ -0,0 +1,26 @@ +unit Ean.Controllers.Produto; + +interface + +uses + Horse, + Horse.Exception; + +procedure Registry; +//procedure ConfigSwagger; + +implementation + +function RemoveAcento(const ptext: string):string; +type + usaascii20127 = type ansistring(20127); +begin + result := string(usaascii20127(ptext)); +end; + +procedure Registry; +begin + +end; + +end. diff --git a/src/controllers/Ean.Controllers.Registry.pas b/src/controllers/Ean.Controllers.Registry.pas new file mode 100644 index 0000000..fba77f1 --- /dev/null +++ b/src/controllers/Ean.Controllers.Registry.pas @@ -0,0 +1,23 @@ +unit Ean.Controllers.Registry; + +interface + +uses + Horse, + Horse.Exception; + +procedure DoRegistry; + +implementation + +uses + Ean.Controllers.Produto, + Ean.Controllers.UnidadeMedida; + +procedure DoRegistry; +begin + Ean.Controllers.Produto.Registry; + Ean.Controllers.UnidadeMedida.Registry; +end; + +end. diff --git a/src/controllers/Ean.Controllers.UnidadeMedida.pas b/src/controllers/Ean.Controllers.UnidadeMedida.pas new file mode 100644 index 0000000..c9a99ac --- /dev/null +++ b/src/controllers/Ean.Controllers.UnidadeMedida.pas @@ -0,0 +1,149 @@ +unit Ean.Controllers.UnidadeMedida; + +interface + +uses + Horse, + Horse.Exception; + +procedure Registry; + +implementation + +uses + System.JSON, + Database.Factory; + +function RemoveAcento(const ptext: string):string; +type + usaascii20127 = type ansistring(20127); +begin + result := string(usaascii20127(ptext)); +end; + +procedure GetDescricaoUnidadeMedida(Req: THorseRequest; Res: THorseResponse); +var wjson: tjsonobject; +begin + if Req.Params.Items['id'] <> '' then + begin + + {if mainview.MemoHistorico.lines.count > 10000 then + mainview.MemoHistorico.lines.clear;} // Alterar para estratégia de Log no Console + + var ds := TDatabaseFactory.New.SQL + .SQL('select nome from unidade_medida where id = :id') + .ParamList + .AddString('id', Req.Params.Items['id']) + .&End + .Open; + + if not ds.IsEmpty then + begin + Res.Send(ds.FieldByName('nome').asstring).Status(200); +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue descricao unidade medida: '+Req.Params.Items['id']+ '|' + +// ds.FieldByName('nome').asstring); + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); + finally + end; + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3')); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); + + finally + end; + end; +end; + +procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); +var wjson: tjsonobject; +begin + + if Req.Params.Items['id'] <> '' then + begin +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + var ds := TDatabaseFactory.New.SQL + .SQL('select id, nome from unidade_medida where id = :id') + .ParamList + .AddString('id', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('id',removeacento(ds.FieldByName('id').AsString))); + wjson.AddPair(tjsonpair.Create('nome',removeacento(ds.FieldByName('nome').AsString))); + Res.Send(wjson).Status(200);; + +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+ +// Req.Params.Items['id']+ '|' +ds.fieldbyname('nome').asstring); + + finally + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); + finally + end; + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3')); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); + + finally + end; + end; +end; + +procedure Registry; +begin + THorse + .Get('/api/um2/:id', GetDescricaoUnidadeMedida) + .Get('/api/um/:id', GetUnidadeMedida) + ; +end; + +end. diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 5c058fb..01a2ed7 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -44,7 +44,8 @@ implementation main.view, system.JSON, - Database.Factory; + Database.Factory, + Ean.Controllers.Registry; { TWsHorse } @@ -55,6 +56,8 @@ function TWsHorse.Active: Boolean; procedure TWsHorse.AddMethods; begin + Ean.Controllers.Registry.DoRegistry; + with FHorse do begin @@ -222,124 +225,8 @@ procedure TWsHorse.AddMethods; end); - Get('/api/um2/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var wjson: tjsonobject; - begin - if Req.Params.Items['id'] <> '' then - begin - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - var ds := TDatabaseFactory.New.SQL - .SQL('select nome from unidade_medida where id = :id') - .ParamList - .AddString('id', Req.Params.Items['id']) - .&End - .Open; - - if not ds.IsEmpty then - begin - Res.Send(ds.FieldByName('nome').asstring).Status(200); - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ - timetostr(now)+'| Entregue descricao unidade medida: '+Req.Params.Items['id']+ '|' + - ds.FieldByName('nome').asstring); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3')); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - - finally - end; - end; - end); - //*** - Get('/api/um/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var wjson: tjsonobject; - begin - - if Req.Params.Items['id'] <> '' then - begin - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - var ds := TDatabaseFactory.New.SQL - .SQL('select id, nome from unidade_medida where id = :id') - .ParamList - .AddString('id', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('id',removeacento(ds.FieldByName('id').AsString))); - wjson.AddPair(tjsonpair.Create('nome',removeacento(ds.FieldByName('nome').AsString))); - Res.Send(wjson).Status(200);; - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+ - Req.Params.Items['id']+ '|' +ds.fieldbyname('nome').asstring); - - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3')); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - - finally - end; - end; - end); + //**** From 2c3f1990da801cea4cb5195b3bd5510ad8ec001e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 12:58:43 -0300 Subject: [PATCH 07/39] Inicio controller produtos --- src/controllers/Ean.Controllers.Produto.pas | 60 +++++++++++++++- .../Ean.Controllers.UnidadeMedida.pas | 72 ++++++++++--------- src/wsHorse.pas | 53 -------------- 3 files changed, 97 insertions(+), 88 deletions(-) diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/Ean.Controllers.Produto.pas index 3f73483..5d32072 100644 --- a/src/controllers/Ean.Controllers.Produto.pas +++ b/src/controllers/Ean.Controllers.Produto.pas @@ -4,7 +4,9 @@ interface uses Horse, - Horse.Exception; + Horse.Exception, + System.JSON, + Database.Factory; procedure Registry; //procedure ConfigSwagger; @@ -18,9 +20,63 @@ function RemoveAcento(const ptext: string):string; result := string(usaascii20127(ptext)); end; -procedure Registry; +procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); +var wjson: tjsonobject; begin + if Req.Params.Items['id'] <> '' then + begin +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + var ds:= TDatabaseFactory.New.SQL + .SQL('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean') + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open; + + if ds.IsEmpty = false then + begin + Res.Send(ds.FieldByName('nome').asstring).Status(200); +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+ +// Req.Params.Items['id']+ '|' +ds.FieldByName('nome').AsString); + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally + end; + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally + end; + end; +end + +procedure Registry; +begin + THorse + .Get('/api/descricao/:id', GetDescricaoProduto) + ; end; end. diff --git a/src/controllers/Ean.Controllers.UnidadeMedida.pas b/src/controllers/Ean.Controllers.UnidadeMedida.pas index c9a99ac..c8d448c 100644 --- a/src/controllers/Ean.Controllers.UnidadeMedida.pas +++ b/src/controllers/Ean.Controllers.UnidadeMedida.pas @@ -78,49 +78,55 @@ procedure GetDescricaoUnidadeMedida(Req: THorseRequest; Res: THorseResponse); procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin - - if Req.Params.Items['id'] <> '' then + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3') + .AsString; + + var ds := TDatabaseFactory.New.SQL + .SQL('select id, nome from unidade_medida where id = :id') + .ParamList + .AddString('id', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then begin -// if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; - - var ds := TDatabaseFactory.New.SQL - .SQL('select id, nome from unidade_medida where id = :id') - .ParamList - .AddString('id', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('id',removeacento(ds.FieldByName('id').AsString))); - wjson.AddPair(tjsonpair.Create('nome',removeacento(ds.FieldByName('nome').AsString))); - Res.Send(wjson).Status(200);; + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('id',removeacento(ds.FieldByName('id').AsString))); + wjson.AddPair(tjsonpair.Create('nome',removeacento(ds.FieldByName('nome').AsString))); + Res.Send(wjson).Status(200);; // inc(cont200); // mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+ // Req.Params.Items['id']+ '|' +ds.fieldbyname('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; + finally + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; // inc(cont404); // mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; + finally end; + end; + + if Req.Params.Items['id'] <> '' then + begin +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + end else begin diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 01a2ed7..d60edeb 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -172,59 +172,6 @@ procedure TWsHorse.AddMethods; end; end); - Get('/api/descricao/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var wjson: tjsonobject; - begin - if Req.Params.Items['id'] <> '' then - begin - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - var ds:= TDatabaseFactory.New.SQL - .SQL('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean') - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open; - - if ds.IsEmpty = false then - begin - Res.Send(ds.FieldByName('nome').asstring).Status(200); - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+ - Req.Params.Items['id']+ '|' +ds.FieldByName('nome').AsString); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+ - timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; - - end); - //*** From 839a705ab1a2ca62922bfa24cc409c5c3c3f122e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 13:06:00 -0300 Subject: [PATCH 08/39] Migrando demais rotas relacionadas a produtos para o controllers/Ean.Controllers.Produto.pas --- src/controllers/Ean.Controllers.Produto.pas | 253 ++++++++++++++++++- src/wsHorse.pas | 260 -------------------- 2 files changed, 252 insertions(+), 261 deletions(-) diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/Ean.Controllers.Produto.pas index 5d32072..b305952 100644 --- a/src/controllers/Ean.Controllers.Produto.pas +++ b/src/controllers/Ean.Controllers.Produto.pas @@ -5,7 +5,9 @@ interface uses Horse, Horse.Exception, + System.SysUtils, System.JSON, + System.Classes, Database.Factory; procedure Registry; @@ -20,6 +22,95 @@ function RemoveAcento(const ptext: string):string; result := string(usaascii20127(ptext)); end; +procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); +var wjson: tjsonobject; +begin + if Req.Params.Items['id'] <> '' then + begin +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); + wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); + wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); + wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); + wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); +// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); + wjson.AddPair(tjsonpair.Create('Peso','')); +// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); + wjson.AddPair(tjsonpair.Create('id_categoria','')); +// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); + wjson.AddPair(tjsonpair.Create('tributacao','')); + Res.Send(wjson).Status(200);; + +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); + finally + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','404')); + wjson.AddPair(tjsonpair.Create('Nome','404')); + wjson.AddPair(tjsonpair.Create('Ncm','404')); + wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); + wjson.AddPair(tjsonpair.Create('Embalagem','404')); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); + wjson.AddPair(tjsonpair.Create('Marca','404')); + wjson.AddPair(tjsonpair.Create('Categoria','404')); + wjson.AddPair(tjsonpair.Create('Peso','0')); + wjson.AddPair(tjsonpair.Create('id_categoria','0')); + wjson.AddPair(tjsonpair.Create('tributacao','404')); + Res.Send(wjson).Status(200);; + +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally + end; + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + + finally + end; + end; +end; + procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin @@ -69,13 +160,173 @@ procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); finally end; end; +end; + +procedure GetProduto(Req: THorseRequest; Res: THorseResponse); +var wjson: tjsonobject; +begin + if Req.Params.Items['id'] <> '' then + begin +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); + wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); + wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); + wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); + wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); +// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); + wjson.AddPair(tjsonpair.Create('Peso','')); +// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); + wjson.AddPair(tjsonpair.Create('id_categoria','')); +// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); + wjson.AddPair(tjsonpair.Create('tributacao','')); + Res.Send(wjson).Status(200);; + +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); + finally + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally + end; + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally + end; + end; +end; + +procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); +var oini: tstringlist; +var wjson: tjsonobject; +begin + if Req.Params.Items['id'] <> '' then + begin +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', Req.Params.Items['id']) + .&End + .Open(); -end + if not ds.IsEmpty then + begin + try + oini:=TStringList.Create; + oini.Add('[GENERAL]'); + oini.Add('Nome='+removeacento(ds.FieldByName('nome').asstring)); + oini.Add('Ncm='+removeacento(ds.FieldByName('ncm').asstring)); + oini.Add('Cest_Codigo='+removeacento(ds.FieldByName('cest_codigo').asstring)); + oini.Add('Embalagem='+removeacento(ds.FieldByName('embalagem').asstring)); + oini.Add('QuantidadeEmbalagem='+removeacento(ds.FieldByName('quantidade_embalagem').asstring)); + oini.Add('Marca='+removeacento(ds.FieldByName('marca').asstring)); + oini.Add('Categoria='+removeacento(ds.FieldByName('categoria').asstring)); + oini.Add('Peso='+''); +// oini.Add('id_categoria='+removeacento(ds.FieldByName('id_categoria').asstring)); + oini.Add('id_categoria='+''); +// oini.Add('tributacao'+removeacento(ds.FieldByName('tributacao').asstring)); + oini.Add('tributacao='+''); + Res.Send(oini.TEXT).Status(200); + + freeandnil(oini); + +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue INI: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); + finally + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + finally + end; + end; + end + else + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + Res.Send(wjson).Status(404);; + +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + + finally + end; + end; +end; procedure Registry; begin THorse .Get('/api/descricao/:id', GetDescricaoProduto) + .Get('/api/desc200/:id', GetDescricao200Produto) + .Get('/api/desc/:id', GetProduto) + .Get('/api/desc_ini/:id', GetProdutoINI) ; end; diff --git a/src/wsHorse.pas b/src/wsHorse.pas index d60edeb..5c3bd26 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -172,266 +172,6 @@ procedure TWsHorse.AddMethods; end; end); -//*** - - -//**** - - Get('/api/desc/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var wjson: tjsonobject; - begin - if Req.Params.Items['id'] <> '' then - begin - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ - timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; - end); - - //************ - - Get('/api/desc200/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var wjson: tjsonobject; - begin - if Req.Params.Items['id'] <> '' then - begin - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ - timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','404')); - wjson.AddPair(tjsonpair.Create('Nome','404')); - wjson.AddPair(tjsonpair.Create('Ncm','404')); - wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); - wjson.AddPair(tjsonpair.Create('Embalagem','404')); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); - wjson.AddPair(tjsonpair.Create('Marca','404')); - wjson.AddPair(tjsonpair.Create('Categoria','404')); - wjson.AddPair(tjsonpair.Create('Peso','0')); - wjson.AddPair(tjsonpair.Create('id_categoria','0')); - wjson.AddPair(tjsonpair.Create('tributacao','404')); - Res.Send(wjson).Status(200);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - - finally - end; - end; - end); - //************ - - - Get('/api/desc_ini/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var oini: tstringlist; - var wjson: tjsonobject; - begin - if Req.Params.Items['id'] <> '' then - begin - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - oini:=TStringList.Create; - oini.Add('[GENERAL]'); - oini.Add('Nome='+removeacento(ds.FieldByName('nome').asstring)); - oini.Add('Ncm='+removeacento(ds.FieldByName('ncm').asstring)); - oini.Add('Cest_Codigo='+removeacento(ds.FieldByName('cest_codigo').asstring)); - oini.Add('Embalagem='+removeacento(ds.FieldByName('embalagem').asstring)); - oini.Add('QuantidadeEmbalagem='+removeacento(ds.FieldByName('quantidade_embalagem').asstring)); - oini.Add('Marca='+removeacento(ds.FieldByName('marca').asstring)); - oini.Add('Categoria='+removeacento(ds.FieldByName('categoria').asstring)); - oini.Add('Peso='+''); -// oini.Add('id_categoria='+removeacento(ds.FieldByName('id_categoria').asstring)); - oini.Add('id_categoria='+''); -// oini.Add('tributacao'+removeacento(ds.FieldByName('tributacao').asstring)); - oini.Add('tributacao='+''); - Res.Send(oini.TEXT).Status(200); - - freeandnil(oini); - - inc(cont200); - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ - timetostr(now)+'| Entregue INI: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); - Res.Send(wjson).Status(404);; - - inc(cont404); - mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - - finally - end; - end; - end); - - //************ end; end; From 8f1b8421c6bb80aa7fdb2c964d26b663e6b98a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 14:47:45 -0300 Subject: [PATCH 09/39] Convertendo MainControl em Sigleton --- src/main.control.pas | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main.control.pas b/src/main.control.pas index 0e5c63a..5c6a8e2 100644 --- a/src/main.control.pas +++ b/src/main.control.pas @@ -15,6 +15,8 @@ TMainControl = class procedure LoadConfig; function GetConfigParams(Key: String): String; property WS: TWsHorse read GetWs; + + class var MainControl: TMainControl; public constructor Create; destructor Destroy; @@ -22,6 +24,9 @@ TMainControl = class procedure SaveConfig(Values: TStrings); property Config: TStrings read FConfig; function Active: Boolean; + + class function GetInstance: TMainControl; + class destructor UnInitialize; end; implementation @@ -54,6 +59,14 @@ function TMainControl.GetConfigParams(Key: String): String; result := Config.Values[Key]; end; +class function TMainControl.GetInstance: TMainControl; +begin + if MainControl = nil + then MainControl := TMainControl.Create; + + Result := MainControl; +end; + function TMainControl.GetWs: TWsHorse; begin if not Assigned(FWS) then @@ -79,6 +92,12 @@ procedure TMainControl.SaveConfig(Values: TStrings); Config.SaveToFile( FFileConfig ); end; +class destructor TMainControl.UnInitialize; +begin + if MainControl <> nil + then FreeAndNil(MainControl); +end; + procedure TMainControl.Power; begin if not Active then From 634e6683bd6ea47fc842de2a01aee59d32cf80f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 14:50:51 -0300 Subject: [PATCH 10/39] Utilizando sigleton MainControl e expondo Path e Porta --- src/main.control.pas | 17 +++++++++++++++-- src/main.view.pas | 17 +++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/main.control.pas b/src/main.control.pas index 5c6a8e2..1fd37b8 100644 --- a/src/main.control.pas +++ b/src/main.control.pas @@ -25,6 +25,9 @@ TMainControl = class property Config: TStrings read FConfig; function Active: Boolean; + function GetPath: String; + function GetPort: Integer; + class function GetInstance: TMainControl; class destructor UnInitialize; end; @@ -67,6 +70,16 @@ class function TMainControl.GetInstance: TMainControl; Result := MainControl; end; +function TMainControl.GetPath: String; +begin + Result := GetConfigParams('Path'); +end; + +function TMainControl.GetPort: Integer; +begin + Result := StrToIntDef(GetConfigParams('Port'), 9000); +end; + function TMainControl.GetWs: TWsHorse; begin if not Assigned(FWS) then @@ -102,8 +115,8 @@ procedure TMainControl.Power; begin if not Active then begin - WS.Port( GetConfigParams('Port').ToInteger ) - .Path( GetConfigParams('Path') ) + WS.Port( Self.GetPort ) + .Path( Self.GetPath ) end; WS.Power; end; diff --git a/src/main.view.pas b/src/main.view.pas index cabb03a..15010f2 100644 --- a/src/main.view.pas +++ b/src/main.view.pas @@ -5,7 +5,7 @@ interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Buttons, - main.control, Vcl.Grids, Vcl.ValEdit; + Vcl.Grids, Vcl.ValEdit; type TMainView = class(TForm) @@ -28,7 +28,6 @@ TMainView = class(TForm) procedure MemoHistoricoChange(Sender: TObject); private { Private declarations } - Control: TMainControl; procedure LoadConfigFile; procedure SaveConfigFile; public @@ -43,11 +42,13 @@ TMainView = class(TForm) implementation +uses + main.control; + {$R *.dfm} procedure TMainView.FormCreate(Sender: TObject); begin - Control := TMainControl.Create; LoadConfigFile; end; @@ -58,9 +59,9 @@ procedure TMainView.btnSaveConfigClick(Sender: TObject); procedure TMainView.btnPowerClick(Sender: TObject); begin - Control.Config.Assign( ValueListEditor1.Strings ); - Control.Power; - case Control.Active of + TMainControl.GetInstance.Config.Assign( ValueListEditor1.Strings ); + TMainControl.GetInstance.Power; + case TMainControl.GetInstance.Active of false: btnPower.Caption := 'Start'; true : btnPower.Caption := 'Stop'; end; @@ -68,7 +69,7 @@ procedure TMainView.btnPowerClick(Sender: TObject); procedure TMainView.LoadConfigFile; begin - ValueListEditor1.Strings.Assign( Control.Config ); + ValueListEditor1.Strings.Assign( TMainControl.GetInstance.Config ); end; procedure TMainView.MemoHistoricoChange(Sender: TObject); @@ -79,7 +80,7 @@ procedure TMainView.MemoHistoricoChange(Sender: TObject); procedure TMainView.SaveConfigFile; begin - Control.SaveConfig(ValueListEditor1.Strings); + TMainControl.GetInstance.SaveConfig(ValueListEditor1.Strings); LoadConfigFile; end; From aa9c454ad9941a59a50bb48b3d501c85624a086e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 14:53:24 -0300 Subject: [PATCH 11/39] =?UTF-8?q?Migra=C3=A7=C3=A3o=20get=20GETIN=20para?= =?UTF-8?q?=20controllers/Ean.Controllers.Produto.pas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/Ean.Controllers.Produto.pas | 73 ++++++++++++++++++++- src/wsHorse.pas | 36 ---------- 2 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/Ean.Controllers.Produto.pas index b305952..a7dff37 100644 --- a/src/controllers/Ean.Controllers.Produto.pas +++ b/src/controllers/Ean.Controllers.Produto.pas @@ -5,16 +5,24 @@ interface uses Horse, Horse.Exception, + Horse.OctetStream, + System.SysUtils, System.JSON, System.Classes, - Database.Factory; + System.IOUtils, + + Database.Factory, + + main.control; procedure Registry; //procedure ConfigSwagger; implementation +var LPath: String = ''; + function RemoveAcento(const ptext: string):string; type usaascii20127 = type ansistring(20127); @@ -22,6 +30,19 @@ function RemoveAcento(const ptext: string):string; result := string(usaascii20127(ptext)); end; +function SomenteNumero(snum: string): string; +var s1, s2: string; + i: integer; +begin + s1 := snum; + s2 := ''; + for i := 1 to length(s1) do + if s1[i] in ['0' .. '9'] then + s2:=s2 + s1[i]; + result:=s2; +end; + + procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin @@ -320,6 +341,54 @@ procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); end; end; +procedure GetProdutoFotoExiste(Req: THorseRequest; Res: THorseResponse); +begin + +end; + +procedure GetProdutoFoto(Req: THorseRequest; Res: THorseResponse); +begin + +end; + +procedure GetProdutoGTIN(Req: THorseRequest; Res: THorseResponse); +var + LFile: String; + LFileSend: TFileReturn; + LStream: TFileStream; + LDisposition: String; + LPath: String; +begin + LPath := TMainControl.GetInstance.GetPath; + LFile := LPath + SomenteNumero(Req.Params.Items['id']) + '.png'; + +// if fileexists(lfile) = false then baixacosmos(somentenumero(Req.Params.Items['id'])); + +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + if FileExists(LFile) then + begin + try + LStream := TFileStream.Create(LFile, fmOpenRead); + LFileSend := TFileReturn.Create( TPath.GetFileName(LFile), LStream, False); + Res.Send(LFileSend).Status(200); + +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue arquivo: '+lfile); + finally + end; + end + else + begin + //quando pede foto eu nao envio json no retorno para evitar erro na conversao do lado do cliente +// inc(cont404); +// +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Arquivo nao encontrado: '+lfile); + Res.Send('').Status(404); + end; +end; + procedure Registry; begin THorse @@ -327,6 +396,8 @@ procedure Registry; .Get('/api/desc200/:id', GetDescricao200Produto) .Get('/api/desc/:id', GetProduto) .Get('/api/desc_ini/:id', GetProdutoINI) + .Get('/api/fotoexiste/:id', GetProdutoFotoExiste) + .Get('/api/gtin/:id', GetProdutoGTIN) ; end; diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 5c3bd26..09542b6 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -69,42 +69,6 @@ procedure TWsHorse.AddMethods; Res.Send(LVersao); end); - Get('/api/gtin/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var - LFile: String; - LFileSend: TFileReturn; - LStream: TFileStream; - LDisposition: String; - begin - LFile := FPath + somentenumero(Req.Params.Items['id']) + '.png'; - -// if fileexists(lfile) = false then baixacosmos(somentenumero(Req.Params.Items['id'])); - - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - if FileExists(LFile) then - begin - try - LStream := TFileStream.Create(LFile, fmOpenRead); - LFileSend := TFileReturn.Create( TPath.GetFileName(LFile), LStream, False); - Res.Send(LFileSend).Status(200); - inc(cont200); - - mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue arquivo: '+lfile); - finally - end; - end - else - begin - //quando pede foto eu nao envio json no retorno para evitar erro na conversao do lado do cliente - inc(cont404); - - mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Arquivo nao encontrado: '+lfile); - Res.Send('').Status(404); - end; - end); - Get('/api/fotoexiste/:id', procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) var From 2265f7cd3c120e3ae353a854d841435bed0f8939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 14:55:49 -0300 Subject: [PATCH 12/39] =?UTF-8?q?Migra=C3=A7=C3=A3o=20rotas=20para=20obter?= =?UTF-8?q?=20foto=20do=20produto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/Ean.Controllers.Produto.pas | 56 ++++++++++++++++- src/wsHorse.pas | 67 --------------------- 2 files changed, 55 insertions(+), 68 deletions(-) diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/Ean.Controllers.Produto.pas index a7dff37..ca9c19c 100644 --- a/src/controllers/Ean.Controllers.Produto.pas +++ b/src/controllers/Ean.Controllers.Produto.pas @@ -42,7 +42,6 @@ function SomenteNumero(snum: string): string; result:=s2; end; - procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin @@ -342,13 +341,68 @@ procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); end; procedure GetProdutoFotoExiste(Req: THorseRequest; Res: THorseResponse); +var + LFile: String; begin + LFile := TMainControl.GetInstance.GetPath + somentenumero(Req.Params.Items['id']) + '.png'; + +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + if FileExists(LFile) then + begin + try + Res.Send('Sim').Status(200); +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); + finally + end; + end + else + begin + Res.Send('Nao').Status(200); + +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); + end; end; procedure GetProdutoFoto(Req: THorseRequest; Res: THorseResponse); +var + LFile: String; + wjson: tjsonobject; begin + LFile := TMainControl.GetInstance.GetPath + somentenumero(Req.Params.Items['id']) + '.png'; + + +// if mainview.MemoHistorico.lines.count > 10000 then +// mainview.MemoHistorico.lines.clear; + + wjson:=tjsonobject.Create; + + + if FileExists(LFile) then + begin + try + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Foto encontrada: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(200);; +// Res.Send('Sim').Status(200); +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); + finally + end; + end + else + begin + wjson.AddPair(tjsonpair.Create('Status','404')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Foto nao encontrada: '+Req.Params.Items['id'])); + Res.Send(wjson).Status(200);; +// Res.Send('Nao').Status(200); +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); + end; end; procedure GetProdutoGTIN(Req: THorseRequest; Res: THorseResponse); diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 09542b6..918c71c 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -69,73 +69,6 @@ procedure TWsHorse.AddMethods; Res.Send(LVersao); end); - Get('/api/fotoexiste/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var - LFile: String; - begin - LFile := FPath + somentenumero(Req.Params.Items['id']) + '.png'; - - - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - if FileExists(LFile) then - begin - try - Res.Send('Sim').Status(200); - inc(cont200); - - mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); - finally - end; - end - else - begin - Res.Send('Nao').Status(200); - inc(cont200); - mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); - end; - end); - - Get('/api/fotoexistej/:id', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) - var - LFile: String; - wjson: tjsonobject; - begin - LFile := FPath + somentenumero(Req.Params.Items['id']) + '.png'; - - - if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear; - - wjson:=tjsonobject.Create; - - - if FileExists(LFile) then - begin - try - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Foto encontrada: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(200);; -// Res.Send('Sim').Status(200); - inc(cont200); - - mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); - finally - end; - end - else - begin - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Foto nao encontrada: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(200);; -// Res.Send('Nao').Status(200); - inc(cont200); - mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); - end; - end); - end; end; From 637a4adf295c2f6f7ead4429b0da31a62634c7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Sat, 12 Aug 2023 14:58:19 -0300 Subject: [PATCH 13/39] =?UTF-8?q?removido=20FHorse=20pois=20nova=20vers?= =?UTF-8?q?=C3=A3o=20n=C3=A3o=20exige=20esta=20abordagem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/wsHorse.pas | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 918c71c..5cac9b5 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -14,7 +14,6 @@ interface TWsHorse = class private - FHorse: THorse; FPath: String; FDBParams: TConnectionDefParams; @@ -51,38 +50,32 @@ implementation function TWsHorse.Active: Boolean; begin - Result := FHorse.IsRunning; + Result := THorse.IsRunning; end; procedure TWsHorse.AddMethods; begin Ean.Controllers.Registry.DoRegistry; - with FHorse do - begin - - Get('/api/version', + THorse + .Get('/api/version', procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) begin var LVersao := TJsonObject.Create; - LVersao.AddPair('horseVersion', FHorse.Version); + LVersao.AddPair('horseVersion', THorse.Version); Res.Send(LVersao); end); - - end; end; constructor TWsHorse.Create; begin LoadDatabaseConfig; - FHorse := THorse.Create; - with FHorse do - begin - Use(Jhonson); - Use(OctetStream); - Use(HandleException); - end; + THorse + .Use(Jhonson) + .Use(OctetStream) + .Use(HandleException); + AddMethods; end; @@ -117,7 +110,7 @@ procedure TWsHorse.LoadDatabaseConfig; function TWsHorse.Port(Value: Integer): TWsHorse; begin Result := Self; - FHorse.Port := Value; + THorse.Port := Value; end; function TWsHorse.Path(Value: String): TWsHorse; @@ -128,17 +121,16 @@ function TWsHorse.Path(Value: String): TWsHorse; procedure TWsHorse.Power; begin - if FHorse.IsRunning - then FHorse.StopListen - else FHorse.Listen; + if THorse.IsRunning + then THorse.StopListen + else THorse.Listen; end; - function twshorse.removeacento(const ptext: string):string; type usaascii20127 = type ansistring(20127); begin - result:=string(usaascii20127(ptext)); + result:=string(usaascii20127(ptext)); end; function twshorse.somentenumero(snum: string): string; From 1b27cd47c8d0ecfc6259285a5eebed4020e593f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Tue, 15 Aug 2023 15:02:56 -0300 Subject: [PATCH 14/39] =?UTF-8?q?Substitui=C3=A7=C3=A3o=20de=20Req.Params.?= =?UTF-8?q?Items['id']=20por=20Req.Params.Field('id').AsString=20com=20Req?= =?UTF-8?q?uired=20-=20se=20n=C3=A3o=20informado,=20vai=20estourar=20erro?= =?UTF-8?q?=20400=20Bad=20Request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/Ean.Controllers.Produto.pas | 437 +++++++++----------- src/wsHorse.pas | 1 - 2 files changed, 198 insertions(+), 240 deletions(-) diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/Ean.Controllers.Produto.pas index ca9c19c..d08f41d 100644 --- a/src/controllers/Ean.Controllers.Produto.pas +++ b/src/controllers/Ean.Controllers.Produto.pas @@ -45,74 +45,50 @@ function SomenteNumero(snum: string): string; procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin - if Req.Params.Items['id'] <> '' then - begin -// if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; + + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', LId) + .&End + .Open(); -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','404')); - wjson.AddPair(tjsonpair.Create('Nome','404')); - wjson.AddPair(tjsonpair.Create('Ncm','404')); - wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); - wjson.AddPair(tjsonpair.Create('Embalagem','404')); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); - wjson.AddPair(tjsonpair.Create('Marca','404')); - wjson.AddPair(tjsonpair.Create('Categoria','404')); - wjson.AddPair(tjsonpair.Create('Peso','0')); - wjson.AddPair(tjsonpair.Create('id_categoria','0')); - wjson.AddPair(tjsonpair.Create('tributacao','404')); - Res.Send(wjson).Status(200);; + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); + wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); + wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); + wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); + wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); +// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); + wjson.AddPair(tjsonpair.Create('Peso','')); +// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); + wjson.AddPair(tjsonpair.Create('id_categoria','')); +// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); + wjson.AddPair(tjsonpair.Create('tributacao','')); + Res.Send(wjson).Status(200);; -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue json: '+LId+ '|' +ds.FieldByName('nome').asstring); + finally end; end else @@ -120,12 +96,21 @@ procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); try wjson:=tjsonobject.Create; wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); - Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); + wjson.AddPair(tjsonpair.Create('Status_Desc','404')); + wjson.AddPair(tjsonpair.Create('Nome','404')); + wjson.AddPair(tjsonpair.Create('Ncm','404')); + wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); + wjson.AddPair(tjsonpair.Create('Embalagem','404')); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); + wjson.AddPair(tjsonpair.Create('Marca','404')); + wjson.AddPair(tjsonpair.Create('Categoria','404')); + wjson.AddPair(tjsonpair.Create('Peso','0')); + wjson.AddPair(tjsonpair.Create('id_categoria','0')); + wjson.AddPair(tjsonpair.Create('tributacao','404')); + Res.Send(wjson).Status(200);; +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); finally end; end; @@ -134,49 +119,38 @@ procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin - if Req.Params.Items['id'] <> '' then - begin -// if mainview.MemoHistorico.lines.count > 10000 then + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; + +//if mainview.MemoHistorico.lines.count > 10000 then // mainview.MemoHistorico.lines.clear; - var ds:= TDatabaseFactory.New.SQL - .SQL('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean') - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open; + var ds := TDatabaseFactory.New.SQL + .SQL('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean') + .ParamList + .AddString('ean', LId) + .&End + .Open; - if ds.IsEmpty = false then - begin - Res.Send(ds.FieldByName('nome').asstring).Status(200); -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+ -// Req.Params.Items['id']+ '|' +ds.FieldByName('nome').AsString); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; - end; + if ds.IsEmpty = false then + begin + Res.Send(ds.FieldByName('nome').asstring).Status(200); +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+ +// LId+ '|' +ds.FieldByName('nome').AsString); end else begin try wjson:=tjsonobject.Create; wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+LId)); Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); finally end; end; @@ -185,64 +159,53 @@ procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); procedure GetProduto(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin - if Req.Params.Items['id'] <> '' then - begin -// if mainview.MemoHistorico.lines.count > 10000 then + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; + + // if mainview.MemoHistorico.lines.count > 10000 then // mainview.MemoHistorico.lines.clear; - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', LId) + .&End + .Open(); + + if not ds.IsEmpty then + begin + try + wjson:=tjsonobject.Create; + wjson.AddPair(tjsonpair.Create('Status','200')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); + wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); + wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); + wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); + wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); + wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); + wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); // wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); + wjson.AddPair(tjsonpair.Create('Peso','')); // wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); + wjson.AddPair(tjsonpair.Create('id_categoria','')); // wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; + wjson.AddPair(tjsonpair.Create('tributacao','')); + Res.Send(wjson).Status(200);; // inc(cont200); // mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue json: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; +// timetostr(now)+'| Entregue json: '+LId+ '|' +ds.FieldByName('nome').asstring); + finally end; end else @@ -250,11 +213,11 @@ procedure GetProduto(Req: THorseRequest; Res: THorseResponse); try wjson:=tjsonobject.Create; wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+LId)); Res.Send(wjson).Status(404);; -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); finally end; end; @@ -264,64 +227,53 @@ procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); var oini: tstringlist; var wjson: tjsonobject; begin - if Req.Params.Items['id'] <> '' then - begin -// if mainview.MemoHistorico.lines.count > 10000 then + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; + +// if mainview.MemoHistorico.lines.count > 10000 then // mainview.MemoHistorico.lines.clear; - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', Req.Params.Items['id']) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - oini:=TStringList.Create; - oini.Add('[GENERAL]'); - oini.Add('Nome='+removeacento(ds.FieldByName('nome').asstring)); - oini.Add('Ncm='+removeacento(ds.FieldByName('ncm').asstring)); - oini.Add('Cest_Codigo='+removeacento(ds.FieldByName('cest_codigo').asstring)); - oini.Add('Embalagem='+removeacento(ds.FieldByName('embalagem').asstring)); - oini.Add('QuantidadeEmbalagem='+removeacento(ds.FieldByName('quantidade_embalagem').asstring)); - oini.Add('Marca='+removeacento(ds.FieldByName('marca').asstring)); - oini.Add('Categoria='+removeacento(ds.FieldByName('categoria').asstring)); - oini.Add('Peso='+''); -// oini.Add('id_categoria='+removeacento(ds.FieldByName('id_categoria').asstring)); - oini.Add('id_categoria='+''); -// oini.Add('tributacao'+removeacento(ds.FieldByName('tributacao').asstring)); - oini.Add('tributacao='+''); - Res.Send(oini.TEXT).Status(200); - - freeandnil(oini); + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue INI: '+Req.Params.Items['id']+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', LId) + .&End + .Open(); -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - finally - end; + if not ds.IsEmpty then + begin + try + oini:=TStringList.Create; + oini.Add('[GENERAL]'); + oini.Add('Nome='+removeacento(ds.FieldByName('nome').asstring)); + oini.Add('Ncm='+removeacento(ds.FieldByName('ncm').asstring)); + oini.Add('Cest_Codigo='+removeacento(ds.FieldByName('cest_codigo').asstring)); + oini.Add('Embalagem='+removeacento(ds.FieldByName('embalagem').asstring)); + oini.Add('QuantidadeEmbalagem='+removeacento(ds.FieldByName('quantidade_embalagem').asstring)); + oini.Add('Marca='+removeacento(ds.FieldByName('marca').asstring)); + oini.Add('Categoria='+removeacento(ds.FieldByName('categoria').asstring)); + oini.Add('Peso='+''); +// oini.Add('id_categoria='+removeacento(ds.FieldByName('id_categoria').asstring)); + oini.Add('id_categoria='+''); +// oini.Add('tributacao'+removeacento(ds.FieldByName('tributacao').asstring)); + oini.Add('tributacao='+''); + Res.Send(oini.TEXT).Status(200); + + freeandnil(oini); + +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue INI: '+LId+ '|' +ds.FieldByName('nome').asstring); + finally end; end else @@ -329,12 +281,11 @@ procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); try wjson:=tjsonobject.Create; wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+LId)); Res.Send(wjson).Status(404);; -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+Req.Params.Items['id']); - +// inc(cont404); +// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); finally end; end; @@ -344,26 +295,28 @@ procedure GetProdutoFotoExiste(Req: THorseRequest; Res: THorseResponse); var LFile: String; begin - LFile := TMainControl.GetInstance.GetPath + somentenumero(Req.Params.Items['id']) + '.png'; + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; + + LFile := TMainControl.GetInstance.GetPath + somentenumero(LId) + '.png'; // if mainview.MemoHistorico.lines.count > 10000 then // mainview.MemoHistorico.lines.clear; if FileExists(LFile) then begin - try - Res.Send('Sim').Status(200); + Res.Send('Sim').Status(200); -// inc(cont200); -// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); - finally - end; +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); end else begin Res.Send('Nao').Status(200); -// inc(cont200); -// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); end; end; @@ -372,36 +325,39 @@ procedure GetProdutoFoto(Req: THorseRequest; Res: THorseResponse); LFile: String; wjson: tjsonobject; begin - LFile := TMainControl.GetInstance.GetPath + somentenumero(Req.Params.Items['id']) + '.png'; + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; + LFile := TMainControl.GetInstance.GetPath + somentenumero(Lid) + '.png'; // if mainview.MemoHistorico.lines.count > 10000 then // mainview.MemoHistorico.lines.clear; wjson:=tjsonobject.Create; - if FileExists(LFile) then begin try wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Foto encontrada: '+Req.Params.Items['id'])); + wjson.AddPair(tjsonpair.Create('Status_Desc','Foto encontrada: '+LId)); Res.Send(wjson).Status(200);; -// Res.Send('Sim').Status(200); +// Res.Send('Sim').Status(200); -// inc(cont200); -// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Sim'); finally end; end else begin wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Foto nao encontrada: '+Req.Params.Items['id'])); + wjson.AddPair(tjsonpair.Create('Status_Desc','Foto nao encontrada: '+LId)); Res.Send(wjson).Status(200);; -// Res.Send('Nao').Status(200); -// inc(cont200); -// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); +// Res.Send('Nao').Status(200); +// inc(cont200); +// mainview.MemoHistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Consulta Arquivo : '+lfile+' Nao'); end; end; @@ -411,15 +367,18 @@ procedure GetProdutoGTIN(Req: THorseRequest; Res: THorseResponse); LFileSend: TFileReturn; LStream: TFileStream; LDisposition: String; - LPath: String; begin - LPath := TMainControl.GetInstance.GetPath; - LFile := LPath + SomenteNumero(Req.Params.Items['id']) + '.png'; + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .AsString; -// if fileexists(lfile) = false then baixacosmos(somentenumero(Req.Params.Items['id'])); + LFile := TMainControl.GetInstance.GetPath + SomenteNumero(LId) + '.png'; -// if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; +//if fileexists(lfile) = false then baixacosmos(somentenumero(LId)); + +//if mainview.MemoHistorico.lines.count > 10000 then +//mainview.MemoHistorico.lines.clear; if FileExists(LFile) then begin diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 5cac9b5..f80d0b7 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -158,7 +158,6 @@ procedure TWsHorse.baixacosmos(const ean: string); if directoryexists(FPath + 'Cosmos') = false then CreateDir(FPath + 'Cosmos'); - begin if EAN.Length > 0 then if not FileExists(lfile) then From 90a9a9b46889e834281927f6dc3d102a4fb3f9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Tue, 15 Aug 2023 15:06:13 -0300 Subject: [PATCH 15/39] =?UTF-8?q?Substitui=C3=A7=C3=A3o=20de=20Req.Params.?= =?UTF-8?q?Items['id']=20por=20Req.Params.Field('id').AsString=20com=20Req?= =?UTF-8?q?uired=20-=20se=20n=C3=A3o=20informado,=20vai=20estourar=20erro?= =?UTF-8?q?=20400=20Bad=20Request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Ean.Controllers.UnidadeMedida.pas | 89 ++++++------------- 1 file changed, 27 insertions(+), 62 deletions(-) diff --git a/src/controllers/Ean.Controllers.UnidadeMedida.pas b/src/controllers/Ean.Controllers.UnidadeMedida.pas index c8d448c..149513a 100644 --- a/src/controllers/Ean.Controllers.UnidadeMedida.pas +++ b/src/controllers/Ean.Controllers.UnidadeMedida.pas @@ -24,52 +24,39 @@ function RemoveAcento(const ptext: string):string; procedure GetDescricaoUnidadeMedida(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; begin - if Req.Params.Items['id'] <> '' then - begin + var LId := Req.Params.Field('id') + .Required + .RequiredMessage('Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3') + .AsString; - {if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear;} // Alterar para estratégia de Log no Console - - var ds := TDatabaseFactory.New.SQL - .SQL('select nome from unidade_medida where id = :id') - .ParamList - .AddString('id', Req.Params.Items['id']) - .&End - .Open; - - if not ds.IsEmpty then - begin - Res.Send(ds.FieldByName('nome').asstring).Status(200); -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue descricao unidade medida: '+Req.Params.Items['id']+ '|' + -// ds.FieldByName('nome').asstring); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); - Res.Send(wjson).Status(404);; + {if mainview.MemoHistorico.lines.count > 10000 then + mainview.MemoHistorico.lines.clear;} // Alterar para estratégia de Log no Console -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; - end; + var ds := TDatabaseFactory.New.SQL + .SQL('select nome from unidade_medida where id = :id') + .ParamList + .AddString('id', LId) + .&End + .Open; + + if not ds.IsEmpty then + begin + Res.Send(ds.FieldByName('nome').asstring).Status(200); +// inc(cont200); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ +// timetostr(now)+'| Entregue descricao unidade medida: '+LId+ '|' + +// ds.FieldByName('nome').asstring); end else begin try wjson:=tjsonobject.Create; wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3')); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+LId)); Res.Send(wjson).Status(404);; -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - +// inc(cont404); +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+LId); finally end; end; @@ -86,7 +73,7 @@ procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); var ds := TDatabaseFactory.New.SQL .SQL('select id, nome from unidade_medida where id = :id') .ParamList - .AddString('id', Req.Params.Items['id']) + .AddString('id', LId) .&End .Open(); @@ -102,7 +89,7 @@ procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); // inc(cont200); // mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+ -// Req.Params.Items['id']+ '|' +ds.fieldbyname('nome').asstring); +// LId+ '|' +ds.fieldbyname('nome').asstring); finally end; @@ -112,33 +99,11 @@ procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); try wjson:=tjsonobject.Create; wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+Req.Params.Items['id'])); + wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+LId)); Res.Send(wjson).Status(404);; // inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - finally - end; - end; - - if Req.Params.Items['id'] <> '' then - begin -// if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; - - - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3')); - Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+Req.Params.Items['id']); - +// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+LId); finally end; end; From 1829883175208ce2d5d6205f186a7822ff87887e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 08:00:41 -0300 Subject: [PATCH 16/39] =?UTF-8?q?Arquivos=20renomeados=20para=20padroniza?= =?UTF-8?q?=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGTin.Aplication.dpr | 6 ++--- WsGtin.Aplication.dproj | 6 ++--- src/controllers/Ean.Controllers.Registry.pas | 23 ------------------- ...uto.pas => WsGTin.Controllers.Produto.pas} | 2 +- .../WsGTin.Controllers.Registry.pas | 23 +++++++++++++++++++ ...s => WsGTin.Controllers.UnidadeMedida.pas} | 2 +- src/wsHorse.pas | 4 ++-- 7 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 src/controllers/Ean.Controllers.Registry.pas rename src/controllers/{Ean.Controllers.Produto.pas => WsGTin.Controllers.Produto.pas} (99%) create mode 100644 src/controllers/WsGTin.Controllers.Registry.pas rename src/controllers/{Ean.Controllers.UnidadeMedida.pas => WsGTin.Controllers.UnidadeMedida.pas} (98%) diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 4c97095..0721c2e 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -5,9 +5,9 @@ uses main.view in 'src\main.view.pas' {MainView}, wsHorse in 'src\wsHorse.pas', main.control in 'src\main.control.pas', - Ean.Controllers.Registry in 'src\controllers\Ean.Controllers.Registry.pas', - Ean.Controllers.Produto in 'src\controllers\Ean.Controllers.Produto.pas', - Ean.Controllers.UnidadeMedida in 'src\controllers\Ean.Controllers.UnidadeMedida.pas'; + WsGTin.Controllers.Registry in 'src\controllers\WsGTin.Controllers.Registry.pas', + WsGTin.Controllers.Produto in 'src\controllers\WsGTin.Controllers.Produto.pas', + WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 8ab3b66..31c95a8 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -114,9 +114,9 @@ - - - + + + Base diff --git a/src/controllers/Ean.Controllers.Registry.pas b/src/controllers/Ean.Controllers.Registry.pas deleted file mode 100644 index fba77f1..0000000 --- a/src/controllers/Ean.Controllers.Registry.pas +++ /dev/null @@ -1,23 +0,0 @@ -unit Ean.Controllers.Registry; - -interface - -uses - Horse, - Horse.Exception; - -procedure DoRegistry; - -implementation - -uses - Ean.Controllers.Produto, - Ean.Controllers.UnidadeMedida; - -procedure DoRegistry; -begin - Ean.Controllers.Produto.Registry; - Ean.Controllers.UnidadeMedida.Registry; -end; - -end. diff --git a/src/controllers/Ean.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas similarity index 99% rename from src/controllers/Ean.Controllers.Produto.pas rename to src/controllers/WsGTin.Controllers.Produto.pas index d08f41d..719463f 100644 --- a/src/controllers/Ean.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -1,4 +1,4 @@ -unit Ean.Controllers.Produto; +unit WsGTin.Controllers.Produto; interface diff --git a/src/controllers/WsGTin.Controllers.Registry.pas b/src/controllers/WsGTin.Controllers.Registry.pas new file mode 100644 index 0000000..f329d61 --- /dev/null +++ b/src/controllers/WsGTin.Controllers.Registry.pas @@ -0,0 +1,23 @@ +unit WsGTin.Controllers.Registry; + +interface + +uses + Horse, + Horse.Exception; + +procedure DoRegistry; + +implementation + +uses + WsGTin.Controllers.Produto, + WsGTin.Controllers.UnidadeMedida; + +procedure DoRegistry; +begin + WsGTin.Controllers.Produto.Registry; + WsGTin.Controllers.UnidadeMedida.Registry; +end; + +end. diff --git a/src/controllers/Ean.Controllers.UnidadeMedida.pas b/src/controllers/WsGTin.Controllers.UnidadeMedida.pas similarity index 98% rename from src/controllers/Ean.Controllers.UnidadeMedida.pas rename to src/controllers/WsGTin.Controllers.UnidadeMedida.pas index 149513a..9398be6 100644 --- a/src/controllers/Ean.Controllers.UnidadeMedida.pas +++ b/src/controllers/WsGTin.Controllers.UnidadeMedida.pas @@ -1,4 +1,4 @@ -unit Ean.Controllers.UnidadeMedida; +unit WsGTin.Controllers.UnidadeMedida; interface diff --git a/src/wsHorse.pas b/src/wsHorse.pas index f80d0b7..8c342f4 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -44,7 +44,7 @@ implementation system.JSON, Database.Factory, - Ean.Controllers.Registry; + WsGTin.Controllers.Registry; { TWsHorse } @@ -55,7 +55,7 @@ function TWsHorse.Active: Boolean; procedure TWsHorse.AddMethods; begin - Ean.Controllers.Registry.DoRegistry; + WsGTin.Controllers.Registry.DoRegistry; THorse .Get('/api/version', From 905513c0ef1da9c7b0295b778fd2d47b4a13a460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:15:55 -0300 Subject: [PATCH 17/39] =?UTF-8?q?Iniciando=20implementa=C3=A7=C3=A3o=20de?= =?UTF-8?q?=20Models?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGTin.Aplication.dpr | 3 ++- WsGtin.Aplication.dproj | 1 + src/model/WsGTin.Model.Interfaces.pas | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/model/WsGTin.Model.Interfaces.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 0721c2e..7d2d613 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -7,7 +7,8 @@ uses main.control in 'src\main.control.pas', WsGTin.Controllers.Registry in 'src\controllers\WsGTin.Controllers.Registry.pas', WsGTin.Controllers.Produto in 'src\controllers\WsGTin.Controllers.Produto.pas', - WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas'; + WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas', + WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 31c95a8..83d92ad 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -117,6 +117,7 @@ + Base diff --git a/src/model/WsGTin.Model.Interfaces.pas b/src/model/WsGTin.Model.Interfaces.pas new file mode 100644 index 0000000..b6ab183 --- /dev/null +++ b/src/model/WsGTin.Model.Interfaces.pas @@ -0,0 +1,17 @@ +unit WsGTin.Model.Interfaces; + +interface + +uses + System.Classes, + System.Generics.Collection; + +type + IWsGTinModelProduto = interface + ['{0F7834A7-CB9A-46AD-B65D-6805561868D7}'] + function ObterProdutoPorEan(AEanCode: string): string; + end; + +implementation + +end. From cc2d3dd3e82366ec6bae40fb08b3af6fcc8bcf49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:25:15 -0300 Subject: [PATCH 18/39] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20Entity=20para?= =?UTF-8?q?=20Produtos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGTin.Aplication.dpr | 3 +- WsGtin.Aplication.dproj | 1 + src/model/WsGTin.Model.Interfaces.pas | 6 +- .../entity/WsGTin.Model.Entity.Produto.pas | 57 +++++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/model/entity/WsGTin.Model.Entity.Produto.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 7d2d613..344c0ff 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -8,7 +8,8 @@ uses WsGTin.Controllers.Registry in 'src\controllers\WsGTin.Controllers.Registry.pas', WsGTin.Controllers.Produto in 'src\controllers\WsGTin.Controllers.Produto.pas', WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas', - WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas'; + WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas', + WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 83d92ad..c8eee5c 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -118,6 +118,7 @@ + Base diff --git a/src/model/WsGTin.Model.Interfaces.pas b/src/model/WsGTin.Model.Interfaces.pas index b6ab183..0809394 100644 --- a/src/model/WsGTin.Model.Interfaces.pas +++ b/src/model/WsGTin.Model.Interfaces.pas @@ -4,12 +4,14 @@ interface uses System.Classes, - System.Generics.Collection; + System.Generics.Collection, + + WsGTin.Model.Entity.Produto; type IWsGTinModelProduto = interface ['{0F7834A7-CB9A-46AD-B65D-6805561868D7}'] - function ObterProdutoPorEan(AEanCode: string): string; + function ObterProdutoPorEan(AEanCode: string): TWsGTinModelEntityProduto; end; implementation diff --git a/src/model/entity/WsGTin.Model.Entity.Produto.pas b/src/model/entity/WsGTin.Model.Entity.Produto.pas new file mode 100644 index 0000000..25d1203 --- /dev/null +++ b/src/model/entity/WsGTin.Model.Entity.Produto.pas @@ -0,0 +1,57 @@ +unit WsGTin.Model.Entity.Produto; + +interface + +uses + System.Classes; + System.Generics.Collections; + +type + TWsGTinModelEntityProduto = class + private + FEan: string; + FNome: string; + FNcm: Integer; + FValor: Double; + FAvg: Double; + FEx: Integer; + FMarca: string; + FPais: string; + FCategoria: string; + FValorMedio: Double; + FAtualizado: Integer; + FFoto: string; + FCestCodigo: string; + FDhUpdate: TDateTime; + FErro: Integer; + FEmbalagem: string; + FQuantidadeEmabalagem: string; + FTributacao: string; + FProdutoAcento: string; + public + property Ean: string read FEan write FEan; + property Nome: string read FNome write FNome; + property Ncm: Integer read FNcm write FNcm; + property Valor: Double read FValor write FValor; + property Avg: Double read FAvg write FAvg; + property Ex: Integer read FEx write FEx; + property Marca: string read FMarca write FMarca; + property Pais: string read FPais write FPais; + property Categoria: string read FCategoria write FCategoria; + property ValorMedio: Double read FValorMedio write FValorMedio; + property Atualizado: Integer read FAtualizado write FAtualizado; + property Foto: string read FFoto write FFoto; + property CestCodigo: string read FCestCodigo write FCestCodigo; + property DhUpdate: TDateTime read FDhUpdate write FDhUpdate; + property Erro: Integer read FErro write FErro; + property Embalagem: string read FEmbalagem write FEmbalagem; + property QuantidadeEmabalagem: string read FQuantidadeEmabalagem write FQuantidadeEmabalagem; + property Tributacao: string read FTributacao write FTributacao; + property ProdutoAcento: string read FProdutoAcento write FProdutoAcento; + end; + + TWsGTinModelEntityProdutoLista = TObjectList; + +implementation + +end. From c0bbab9aa01cb55623d97023de3c598e224c22bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:30:44 -0300 Subject: [PATCH 19/39] =?UTF-8?q?Iniciando=20implementa=C3=A7=C3=A3o=20do?= =?UTF-8?q?=20Model=20de=20Produto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGTin.Aplication.dpr | 3 +- WsGtin.Aplication.dproj | 1 + src/model/WsGTin.Model.Interfaces.pas | 2 +- src/model/WsGTin.Model.Produto.pas | 48 +++++++++++++++++++ .../entity/WsGTin.Model.Entity.Produto.pas | 2 +- 5 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/model/WsGTin.Model.Produto.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 344c0ff..7101567 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -9,7 +9,8 @@ uses WsGTin.Controllers.Produto in 'src\controllers\WsGTin.Controllers.Produto.pas', WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas', WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas', - WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas'; + WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas', + WsGTin.Model.Produto in 'src\model\WsGTin.Model.Produto.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index c8eee5c..cc3ba57 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -119,6 +119,7 @@ + Base diff --git a/src/model/WsGTin.Model.Interfaces.pas b/src/model/WsGTin.Model.Interfaces.pas index 0809394..62d4419 100644 --- a/src/model/WsGTin.Model.Interfaces.pas +++ b/src/model/WsGTin.Model.Interfaces.pas @@ -4,7 +4,7 @@ interface uses System.Classes, - System.Generics.Collection, + System.Generics.Collections, WsGTin.Model.Entity.Produto; diff --git a/src/model/WsGTin.Model.Produto.pas b/src/model/WsGTin.Model.Produto.pas new file mode 100644 index 0000000..834fb77 --- /dev/null +++ b/src/model/WsGTin.Model.Produto.pas @@ -0,0 +1,48 @@ +unit WsGTin.Model.Produto; + +interface + +uses + System.Classes, + + WsGTin.Model.Interfaces, + WsGTin.Model.Entity.Produto; + +type + TWsGTinModelProduto = class(TInterfacedObject, IWsGTinModelProduto) + public + constructor Create; + destructor Destroy; override; + class function New: TWsGTinModelProduto; + + { IWsGTinModelProduto } + function ObterProdutoPorEan(AEanCode: string): TWsGTinModelEntityProduto; + end; + +implementation + +{ TWsGTinModelProduto } + +constructor TWsGTinModelProduto.Create; +begin + +end; + +destructor TWsGTinModelProduto.Destroy; +begin + + inherited; +end; + +class function TWsGTinModelProduto.New: TWsGTinModelProduto; +begin + Result := Self.Create; +end; + +function TWsGTinModelProduto.ObterProdutoPorEan( + AEanCode: string): TWsGTinModelEntityProduto; +begin + +end; + +end. diff --git a/src/model/entity/WsGTin.Model.Entity.Produto.pas b/src/model/entity/WsGTin.Model.Entity.Produto.pas index 25d1203..273184d 100644 --- a/src/model/entity/WsGTin.Model.Entity.Produto.pas +++ b/src/model/entity/WsGTin.Model.Entity.Produto.pas @@ -3,7 +3,7 @@ interface uses - System.Classes; + System.Classes, System.Generics.Collections; type From 1b07f789f516afc5e7bfe29c9d634a55f9449b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:37:39 -0300 Subject: [PATCH 20/39] Obtendo dados do BD --- src/model/WsGTin.Model.Produto.pas | 35 +++++++++++++++++++ .../entity/WsGTin.Model.Entity.Produto.pas | 4 +-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/model/WsGTin.Model.Produto.pas b/src/model/WsGTin.Model.Produto.pas index 834fb77..bbef930 100644 --- a/src/model/WsGTin.Model.Produto.pas +++ b/src/model/WsGTin.Model.Produto.pas @@ -21,6 +21,12 @@ TWsGTinModelProduto = class(TInterfacedObject, IWsGTinModelProduto) implementation +uses + Horse, + Horse.Exception, + + Database.Factory; + { TWsGTinModelProduto } constructor TWsGTinModelProduto.Create; @@ -42,6 +48,35 @@ class function TWsGTinModelProduto.New: TWsGTinModelProduto; function TWsGTinModelProduto.ObterProdutoPorEan( AEanCode: string): TWsGTinModelEntityProduto; begin + var LSql := #13#10 + + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + 'FROM base_produtos.cad_produtos cp ' + + 'where ean = :ean ' + ; + + var ds := TDatabaseFactory.New.SQL + .SQL(Lsql) + .ParamList + .AddString('ean', AEanCode) + .&End + .Open(); + + if ds.IsEmpty + then raise EHorseException.New + .&Unit(Self.UnitName) + .Status(THTTPStatus.NotFound) + .Error('Não foi possível encontrar o produto pelo EAN informado'); + + Result := TWsGTinModelEntityProduto.Create; + + Result.Ean := ds.FieldByName('ean').AsString; + Result.Nome := ds.FieldByName('nome').AsString; + Result.CestCodigo := ds.FieldByName('cest_codigo').AsString; + Result.Embalagem := ds.FieldByName('embalagem').AsString; + Result.QuantidadeEmabalagem := ds.FieldByName('quantidade_embalagem').AsFloat; + Result.Marca := ds.FieldByName('marca').AsString; + Result.Categoria := ds.FieldByName('categoria').AsString; end; diff --git a/src/model/entity/WsGTin.Model.Entity.Produto.pas b/src/model/entity/WsGTin.Model.Entity.Produto.pas index 273184d..2baad08 100644 --- a/src/model/entity/WsGTin.Model.Entity.Produto.pas +++ b/src/model/entity/WsGTin.Model.Entity.Produto.pas @@ -25,7 +25,7 @@ TWsGTinModelEntityProduto = class FDhUpdate: TDateTime; FErro: Integer; FEmbalagem: string; - FQuantidadeEmabalagem: string; + FQuantidadeEmabalagem: Double; FTributacao: string; FProdutoAcento: string; public @@ -45,7 +45,7 @@ TWsGTinModelEntityProduto = class property DhUpdate: TDateTime read FDhUpdate write FDhUpdate; property Erro: Integer read FErro write FErro; property Embalagem: string read FEmbalagem write FEmbalagem; - property QuantidadeEmabalagem: string read FQuantidadeEmabalagem write FQuantidadeEmabalagem; + property QuantidadeEmabalagem: Double read FQuantidadeEmabalagem write FQuantidadeEmabalagem; property Tributacao: string read FTributacao write FTributacao; property ProdutoAcento: string read FProdutoAcento write FProdutoAcento; end; From 5a4e95772b3f8eb10e83a48ab70de005823a555d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:43:17 -0300 Subject: [PATCH 21/39] Implementando Factory de Models --- WsGTin.Aplication.dpr | 3 +- WsGtin.Aplication.dproj | 1 + .../WsGTin.Controllers.Produto.pas | 4 +- src/model/WsGTin.Model.Factory.pas | 49 +++++++++++++++++++ src/model/WsGTin.Model.Interfaces.pas | 5 ++ 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/model/WsGTin.Model.Factory.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 7101567..ba2c922 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -10,7 +10,8 @@ uses WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas', WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas', WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas', - WsGTin.Model.Produto in 'src\model\WsGTin.Model.Produto.pas'; + WsGTin.Model.Produto in 'src\model\WsGTin.Model.Produto.pas', + WsGTin.Model.Factory in 'src\model\WsGTin.Model.Factory.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index cc3ba57..249647c 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -120,6 +120,7 @@ + Base diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index 719463f..b05bf1d 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -14,7 +14,9 @@ interface Database.Factory, - main.control; + main.control, + + WsGTin.Model.Factory; procedure Registry; //procedure ConfigSwagger; diff --git a/src/model/WsGTin.Model.Factory.pas b/src/model/WsGTin.Model.Factory.pas new file mode 100644 index 0000000..77d36c6 --- /dev/null +++ b/src/model/WsGTin.Model.Factory.pas @@ -0,0 +1,49 @@ +unit WsGTin.Model.Factory; + +interface + +uses + System.Classes, + + WsGTin.Model.Interfaces; + +type + TWsGTinModelFactory = class(TInterfacedObject, IWsGTinModelFactory) + public + constructor Create; + destructor Destroy; override; + class function New: TWsGTinModelFactory; + + { IWsGTinModelProduto } + function Produto: IWsGTinModelProduto; + end; + +implementation + +uses + WsGTin.Model.Produto; + +{ TWsGTinModelFactory } + +constructor TWsGTinModelFactory.Create; +begin + +end; + +destructor TWsGTinModelFactory.Destroy; +begin + + inherited; +end; + +class function TWsGTinModelFactory.New: TWsGTinModelFactory; +begin + Result := Self.Create; +end; + +function TWsGTinModelFactory.Produto: IWsGTinModelProduto; +begin + Result := TWsGTinModelProduto.New; +end; + +end. diff --git a/src/model/WsGTin.Model.Interfaces.pas b/src/model/WsGTin.Model.Interfaces.pas index 62d4419..acb56f2 100644 --- a/src/model/WsGTin.Model.Interfaces.pas +++ b/src/model/WsGTin.Model.Interfaces.pas @@ -14,6 +14,11 @@ interface function ObterProdutoPorEan(AEanCode: string): TWsGTinModelEntityProduto; end; + IWsGTinModelFactory = interface + ['{B60DB98D-433B-4E91-91D2-7C831E599C2B}'] + function Produto: IWsGTinModelProduto; + end; + implementation end. From 7ecbb060f92d25896bb258e6514ba7c00035a936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:50:36 -0300 Subject: [PATCH 22/39] Adicionado horse-jsoninterceptor --- WsGtin.Aplication.dproj | 2 +- WsGtin.Service.dproj | 2 +- boss-lock.json | 8 ++++++++ boss.json | 1 + src/controllers/WsGTin.Controllers.Produto.pas | 4 ++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 249647c..79ea33c 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -58,7 +58,7 @@ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png WsGTin_Aplication - ..\pascal-database-engine\src;modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src;$(DCC_UnitSearchPath) + ..\pascal-database-engine\src;$(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src 1046 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= diff --git a/WsGtin.Service.dproj b/WsGtin.Service.dproj index 11151eb..0e2a7ac 100644 --- a/WsGtin.Service.dproj +++ b/WsGtin.Service.dproj @@ -67,7 +67,7 @@ $(BDS)\bin\delphi_PROJECTICON.ico $(BDS)\bin\delphi_PROJECTICNS.icns WsGTin_Service - $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src + $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;fmx;FireDACIBDriver;xmlrtl;soapmidas;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage) diff --git a/boss-lock.json b/boss-lock.json index 2f1fe4c..553623f 100644 --- a/boss-lock.json +++ b/boss-lock.json @@ -42,6 +42,14 @@ "failed": false, "changed": false }, + "https://github.com/iagoocesaar/horse-jsoninterceptor": { + "name": "horse-jsoninterceptor", + "version": "0.0.7", + "hash": "1c6ce2d3a7c72ab965a01fc44b0df78b", + "artifacts": {}, + "failed": false, + "changed": false + }, "https://github.com/iagoocesaar/pascal-database-engine": { "name": "pascal-database-engine", "version": "0.0.4", diff --git a/boss.json b/boss.json index 9de7bd8..fdbbc44 100644 --- a/boss.json +++ b/boss.json @@ -10,6 +10,7 @@ "https://github.com/hashload/handle-exception": "^0.1.4", "https://github.com/hashload/horse-octet-stream": "^1.9.2", "https://github.com/hashload/jhonson": "^1.0.7", + "https://github.com/iagoocesaar/horse-jsoninterceptor": "^0.0.7", "https://github.com/iagoocesaar/pascal-database-engine": "^0.0.4" } } \ No newline at end of file diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index b05bf1d..01ebe14 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -166,6 +166,10 @@ procedure GetProduto(Req: THorseRequest; Res: THorseResponse); .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') .AsString; + var LProduto := TWsGTinModelFactory.New + .Produto + .ObterProdutoPorEan(LId); + // if mainview.MemoHistorico.lines.count > 10000 then // mainview.MemoHistorico.lines.clear; From 599db746349c933a57c787bb7ab8870fac295440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 13:58:05 -0300 Subject: [PATCH 23/39] Utilizado Model de Produto --- .../WsGTin.Controllers.Produto.pas | 62 ++----------------- 1 file changed, 4 insertions(+), 58 deletions(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index 01ebe14..87c49cf 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -16,7 +16,9 @@ interface main.control, - WsGTin.Model.Factory; + WsGTin.Model.Factory, + + Horse.JsonInterceptor.Helpers; procedure Registry; //procedure ConfigSwagger; @@ -170,63 +172,7 @@ procedure GetProduto(Req: THorseRequest; Res: THorseResponse); .Produto .ObterProdutoPorEan(LId); - // if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; - - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', LId) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; - -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue json: '+LId+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+LId)); - Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); - finally - end; - end; + Res.Send(TJson.ObjectToJsonObject(LProduto)); end; procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); From bf677799b64066519abdf0b8c454d2b3c45d5904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Wed, 16 Aug 2023 14:07:08 -0300 Subject: [PATCH 24/39] =?UTF-8?q?removida=20vari=C3=A1vel=20n=C3=A3o=20uti?= =?UTF-8?q?lizada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/WsGTin.Controllers.Produto.pas | 1 - 1 file changed, 1 deletion(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index 87c49cf..bd74497 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -161,7 +161,6 @@ procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); end; procedure GetProduto(Req: THorseRequest; Res: THorseResponse); -var wjson: tjsonobject; begin var LId := Req.Params.Field('id') .Required From c7fa2edbd4c40bfa6fc5bf5bb1ec8bbf64867b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 06:38:22 -0300 Subject: [PATCH 25/39] =?UTF-8?q?Retornando=20tamb=C3=A9m=20o=20campo=20de?= =?UTF-8?q?=20link=20da=20foto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/WsGTin.Model.Produto.pas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/model/WsGTin.Model.Produto.pas b/src/model/WsGTin.Model.Produto.pas index bbef930..5cc5251 100644 --- a/src/model/WsGTin.Model.Produto.pas +++ b/src/model/WsGTin.Model.Produto.pas @@ -50,7 +50,7 @@ function TWsGTinModelProduto.ObterProdutoPorEan( begin var LSql := #13#10 + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' + + ' cp.quantidade_embalagem, cp.marca, cp.categoria, cp.link_foto ' + 'FROM base_produtos.cad_produtos cp ' + 'where ean = :ean ' ; @@ -77,6 +77,7 @@ function TWsGTinModelProduto.ObterProdutoPorEan( Result.QuantidadeEmabalagem := ds.FieldByName('quantidade_embalagem').AsFloat; Result.Marca := ds.FieldByName('marca').AsString; Result.Categoria := ds.FieldByName('categoria').AsString; + Result.Foto := ds.FieldByName('link_foto').AsString; end; From d162f44cec4cdb56b38660f6f217daa482bf9c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 07:57:13 -0300 Subject: [PATCH 26/39] =?UTF-8?q?Manter=20um=20padr=C3=A3o=20na=20resposta?= =?UTF-8?q?=20dos=20dados,=20uma=20hora=20retorna=20JSON,=20outra=20um=20t?= =?UTF-8?q?exto=20(etapa=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WsGTin.Controllers.Produto.pas | 126 +----------------- 1 file changed, 6 insertions(+), 120 deletions(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index bd74497..7df6e70 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -46,130 +46,16 @@ function SomenteNumero(snum: string): string; result:=s2; end; -procedure GetDescricao200Produto(Req: THorseRequest; Res: THorseResponse); -var wjson: tjsonobject; -begin - var LId := Req.Params.Field('id') - .Required - .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') - .AsString; - - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', LId) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('Nome',removeacento(ds.FieldByName('nome').asstring))); - wjson.AddPair(tjsonpair.Create('Ncm',removeacento(ds.FieldByName('ncm').asstring))); - wjson.AddPair(tjsonpair.Create('Cest_Codigo',removeacento(ds.FieldByName('cest_codigo').asstring))); - wjson.AddPair(tjsonpair.Create('Embalagem',removeacento(ds.FieldByName('embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem',removeacento(ds.FieldByName('quantidade_embalagem').asstring))); - wjson.AddPair(tjsonpair.Create('Marca',removeacento(ds.FieldByName('marca').asstring))); - wjson.AddPair(tjsonpair.Create('Categoria',removeacento(ds.FieldByName('categoria').asstring))); -// wjson.AddPair(tjsonpair.Create('Peso',removeacento(ds.FieldByName('peso').asstring))); - wjson.AddPair(tjsonpair.Create('Peso','')); -// wjson.AddPair(tjsonpair.Create('id_categoria',removeacento(ds.FieldByName('id_categoria').asstring))); - wjson.AddPair(tjsonpair.Create('id_categoria','')); -// wjson.AddPair(tjsonpair.Create('tributacao',removeacento(ds.FieldByName('tributacao').asstring))); - wjson.AddPair(tjsonpair.Create('tributacao','')); - Res.Send(wjson).Status(200);; - -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue json: '+LId+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','404')); - wjson.AddPair(tjsonpair.Create('Nome','404')); - wjson.AddPair(tjsonpair.Create('Ncm','404')); - wjson.AddPair(tjsonpair.Create('Cest_Codigo','404')); - wjson.AddPair(tjsonpair.Create('Embalagem','404')); - wjson.AddPair(tjsonpair.Create('QuantidadeEmbalagem','0')); - wjson.AddPair(tjsonpair.Create('Marca','404')); - wjson.AddPair(tjsonpair.Create('Categoria','404')); - wjson.AddPair(tjsonpair.Create('Peso','0')); - wjson.AddPair(tjsonpair.Create('id_categoria','0')); - wjson.AddPair(tjsonpair.Create('tributacao','404')); - Res.Send(wjson).Status(200);; - -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); - finally - end; - end; -end; - -procedure GetDescricaoProduto(Req: THorseRequest; Res: THorseResponse); -var wjson: tjsonobject; -begin - var LId := Req.Params.Field('id') - .Required - .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') - .AsString; - -//if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; - - var ds := TDatabaseFactory.New.SQL - .SQL('select nome, ncm, cest_codigo, embalagem, quantidade_embalagem, marca, categoria from cad_produtos where ean = :ean') - .ParamList - .AddString('ean', LId) - .&End - .Open; - - if ds.IsEmpty = false then - begin - Res.Send(ds.FieldByName('nome').asstring).Status(200); -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao: '+ -// LId+ '|' +ds.FieldByName('nome').AsString); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+LId)); - Res.Send(wjson).Status(404);; -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); - finally - end; - end; -end; - procedure GetProduto(Req: THorseRequest; Res: THorseResponse); begin - var LId := Req.Params.Field('id') + var LEanCode := Req.Params.Field('ean') .Required - .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') + .RequiredMessage('Necessario enviar o codigo ean da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') .AsString; var LProduto := TWsGTinModelFactory.New .Produto - .ObterProdutoPorEan(LId); + .ObterProdutoPorEan(LEanCode); Res.Send(TJson.ObjectToJsonObject(LProduto)); end; @@ -356,12 +242,12 @@ procedure GetProdutoGTIN(Req: THorseRequest; Res: THorseResponse); procedure Registry; begin THorse - .Get('/api/descricao/:id', GetDescricaoProduto) - .Get('/api/desc200/:id', GetDescricao200Produto) - .Get('/api/desc/:id', GetProduto) + .Get('/api/desc/:ean', GetProduto) .Get('/api/desc_ini/:id', GetProdutoINI) .Get('/api/fotoexiste/:id', GetProdutoFotoExiste) .Get('/api/gtin/:id', GetProdutoGTIN) + + .Get('/api/produto/:ean', GetProduto) ; end; From 2a6467402fc5dce40d5a47641246939d6b9a887c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 07:58:03 -0300 Subject: [PATCH 27/39] =?UTF-8?q?Manter=20um=20padr=C3=A3o=20na=20resposta?= =?UTF-8?q?=20dos=20dados,=20uma=20hora=20retorna=20JSON,=20outra=20um=20t?= =?UTF-8?q?exto=20(etapa=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WsGTin.Controllers.Produto.pas | 69 ------------------- 1 file changed, 69 deletions(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index 7df6e70..84e99c9 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -60,74 +60,6 @@ procedure GetProduto(Req: THorseRequest; Res: THorseResponse); Res.Send(TJson.ObjectToJsonObject(LProduto)); end; -procedure GetProdutoINI(Req: THorseRequest; Res: THorseResponse); -var oini: tstringlist; -var wjson: tjsonobject; -begin - var LId := Req.Params.Field('id') - .Required - .RequiredMessage('Necessario enviar o codigo da mercadoria. Ex: www.eanpictures.com.br:9000/api/descricao/789789789789') - .AsString; - -// if mainview.MemoHistorico.lines.count > 10000 then -// mainview.MemoHistorico.lines.clear; - - var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria ' - + 'FROM base_produtos.cad_produtos cp ' - + 'where ean = :ean ' - ; - - var ds := TDatabaseFactory.New.SQL - .SQL(Lsql) - .ParamList - .AddString('ean', LId) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - oini:=TStringList.Create; - oini.Add('[GENERAL]'); - oini.Add('Nome='+removeacento(ds.FieldByName('nome').asstring)); - oini.Add('Ncm='+removeacento(ds.FieldByName('ncm').asstring)); - oini.Add('Cest_Codigo='+removeacento(ds.FieldByName('cest_codigo').asstring)); - oini.Add('Embalagem='+removeacento(ds.FieldByName('embalagem').asstring)); - oini.Add('QuantidadeEmbalagem='+removeacento(ds.FieldByName('quantidade_embalagem').asstring)); - oini.Add('Marca='+removeacento(ds.FieldByName('marca').asstring)); - oini.Add('Categoria='+removeacento(ds.FieldByName('categoria').asstring)); - oini.Add('Peso='+''); -// oini.Add('id_categoria='+removeacento(ds.FieldByName('id_categoria').asstring)); - oini.Add('id_categoria='+''); -// oini.Add('tributacao'+removeacento(ds.FieldByName('tributacao').asstring)); - oini.Add('tributacao='+''); - Res.Send(oini.TEXT).Status(200); - - freeandnil(oini); - -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue INI: '+LId+ '|' +ds.FieldByName('nome').asstring); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para o ean: '+LId)); - Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada para o ean: '+LId); - finally - end; - end; -end; - procedure GetProdutoFotoExiste(Req: THorseRequest; Res: THorseResponse); var LFile: String; @@ -243,7 +175,6 @@ procedure Registry; begin THorse .Get('/api/desc/:ean', GetProduto) - .Get('/api/desc_ini/:id', GetProdutoINI) .Get('/api/fotoexiste/:id', GetProdutoFotoExiste) .Get('/api/gtin/:id', GetProdutoGTIN) From a598b9a3d2d3bb932e41e7a966790f8fa604a388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:01:01 -0300 Subject: [PATCH 28/39] =?UTF-8?q?Manter=20um=20padr=C3=A3o=20na=20resposta?= =?UTF-8?q?=20dos=20dados,=20uma=20hora=20retorna=20JSON,=20outra=20um=20t?= =?UTF-8?q?exto=20(etapa=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/WsGTin.Controllers.Produto.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index 84e99c9..915f5a5 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -174,11 +174,11 @@ procedure GetProdutoGTIN(Req: THorseRequest; Res: THorseResponse); procedure Registry; begin THorse - .Get('/api/desc/:ean', GetProduto) + .Get('/api/produto/:ean', GetProduto) + + // TODO: Essas rotas deverão ser removidas e adotar estratégia de static files .Get('/api/fotoexiste/:id', GetProdutoFotoExiste) .Get('/api/gtin/:id', GetProdutoGTIN) - - .Get('/api/produto/:ean', GetProduto) ; end; From 348e23b6494e5a3a7473217e27c4864590cc7a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:03:24 -0300 Subject: [PATCH 29/39] Iniciando model de unidade de medida --- WsGTin.Aplication.dpr | 3 ++- WsGtin.Aplication.dproj | 3 ++- .../WsGTin.Model.Entity.UnidadeMedida.pas | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index ba2c922..5ec6d63 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -11,7 +11,8 @@ uses WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas', WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas', WsGTin.Model.Produto in 'src\model\WsGTin.Model.Produto.pas', - WsGTin.Model.Factory in 'src\model\WsGTin.Model.Factory.pas'; + WsGTin.Model.Factory in 'src\model\WsGTin.Model.Factory.pas', + WsGTin.Model.Entity.UnidadeMedida in 'src\model\entity\WsGTin.Model.Entity.UnidadeMedida.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 79ea33c..6d0d670 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -58,7 +58,7 @@ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png WsGTin_Aplication - ..\pascal-database-engine\src;$(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src + ..\pascal-database-engine\src;modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src;$(DCC_UnitSearchPath) 1046 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= @@ -121,6 +121,7 @@ + Base diff --git a/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas b/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas new file mode 100644 index 0000000..8f25117 --- /dev/null +++ b/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas @@ -0,0 +1,21 @@ +unit WsGTin.Model.Entity.UnidadeMedida; + +interface + +uses + System.Classes, + System.Generics.Collections; + +type + TWsGTinModelEntityUnidadeMedida = class + private + FId: string; + FNome: string; + public + property Id: string read FId write FId; + property Nome: string read FNome write FNome; + end; + +implementation + +end. From 9eed656bb5cf18d845723c032936dd773ff9ee04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:14:50 -0300 Subject: [PATCH 30/39] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20do=20Model=20de?= =?UTF-8?q?=20Unidade=20de=20Medida?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGTin.Aplication.dpr | 3 +- WsGtin.Aplication.dproj | 1 + src/model/WsGTin.Model.Interfaces.pas | 8 ++- src/model/WsGTin.Model.UnidadeMedida.pas | 71 +++++++++++++++++++ .../WsGTin.Model.Entity.UnidadeMedida.pas | 2 + 5 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/model/WsGTin.Model.UnidadeMedida.pas diff --git a/WsGTin.Aplication.dpr b/WsGTin.Aplication.dpr index 5ec6d63..0b35bf9 100644 --- a/WsGTin.Aplication.dpr +++ b/WsGTin.Aplication.dpr @@ -12,7 +12,8 @@ uses WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas', WsGTin.Model.Produto in 'src\model\WsGTin.Model.Produto.pas', WsGTin.Model.Factory in 'src\model\WsGTin.Model.Factory.pas', - WsGTin.Model.Entity.UnidadeMedida in 'src\model\entity\WsGTin.Model.Entity.UnidadeMedida.pas'; + WsGTin.Model.Entity.UnidadeMedida in 'src\model\entity\WsGTin.Model.Entity.UnidadeMedida.pas', + WsGTin.Model.UnidadeMedida in 'src\model\WsGTin.Model.UnidadeMedida.pas'; {$R *.res} diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 6d0d670..8a5c16a 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -122,6 +122,7 @@ + Base diff --git a/src/model/WsGTin.Model.Interfaces.pas b/src/model/WsGTin.Model.Interfaces.pas index acb56f2..0a4a30f 100644 --- a/src/model/WsGTin.Model.Interfaces.pas +++ b/src/model/WsGTin.Model.Interfaces.pas @@ -6,7 +6,8 @@ interface System.Classes, System.Generics.Collections, - WsGTin.Model.Entity.Produto; + WsGTin.Model.Entity.Produto, + WsGTin.Model.Entity.UnidadeMedida; type IWsGTinModelProduto = interface @@ -14,6 +15,11 @@ interface function ObterProdutoPorEan(AEanCode: string): TWsGTinModelEntityProduto; end; + IWsGTinModelUnidadeMedida = interface + ['{16980E32-B528-4C35-86FB-70F34744829A}'] + function ObterUnidadeMedida(AId: string): TWsGTinModelEntityUnidadeMedida; + end; + IWsGTinModelFactory = interface ['{B60DB98D-433B-4E91-91D2-7C831E599C2B}'] function Produto: IWsGTinModelProduto; diff --git a/src/model/WsGTin.Model.UnidadeMedida.pas b/src/model/WsGTin.Model.UnidadeMedida.pas new file mode 100644 index 0000000..89e38fc --- /dev/null +++ b/src/model/WsGTin.Model.UnidadeMedida.pas @@ -0,0 +1,71 @@ +unit WsGTin.Model.UnidadeMedida; + +interface + +uses + System.Classes, + System.Generics.Collections, + + WsGTin.Model.Interfaces, + WsGTin.Model.Entity.UnidadeMedida; + +type + TWsGTinModelUnidadeMedida = class(TInterfacedObject, IWsGTinModelUnidadeMedida) + public + constructor Create; + destructor Destroy; override; + class function New: IWsGTinModelUnidadeMedida; + + { IWsGTinModelUnidadeMedida } + function ObterUnidadeMedida(AId: string): TWsGTinModelEntityUnidadeMedida; + end; + + +implementation + +uses + Horse, + Horse.Exception, + + Database.Factory; + +{ TWsGTinModelUnidadeMedida } + +constructor TWsGTinModelUnidadeMedida.Create; +begin + +end; + +destructor TWsGTinModelUnidadeMedida.Destroy; +begin + + inherited; +end; + +class function TWsGTinModelUnidadeMedida.New: IWsGTinModelUnidadeMedida; +begin + Result := Self.Create; +end; + +function TWsGTinModelUnidadeMedida.ObterUnidadeMedida( + AId: string): TWsGTinModelEntityUnidadeMedida; +begin + var ds := TDatabaseFactory.New.SQL + .SQL('select * from unidade_medida where id = :id') + .ParamList + .AddString('id', AId) + .&End + .Open; + + if ds.IsEmpty + then raise EHorseException.New + .&Unit(Self.UnitName) + .Status(THTTPStatus.NotFound) + .Error('Não foi possível encontrar a unidade de medida pelo ID informado'); + + Result := TWsGTinModelEntityUnidadeMedida.Create; + Result.Id := ds.FieldByName('id').AsString; + Result.Nome := ds.FieldByName('nome').AsString; +end; + +end. diff --git a/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas b/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas index 8f25117..0de7a32 100644 --- a/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas +++ b/src/model/entity/WsGTin.Model.Entity.UnidadeMedida.pas @@ -16,6 +16,8 @@ TWsGTinModelEntityUnidadeMedida = class property Nome: string read FNome write FNome; end; + TWsGTinModelEntityUnidadeMedidaLista = TObjectList; + implementation end. From 2f3f8c862218e8e95304807b889eb645b121d078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:21:47 -0300 Subject: [PATCH 31/39] Utilizando Model de Unidade de Medida --- .../WsGTin.Controllers.Produto.pas | 2 + .../WsGTin.Controllers.UnidadeMedida.pas | 94 ++----------------- src/model/WsGTin.Model.Factory.pas | 9 +- src/model/WsGTin.Model.Interfaces.pas | 1 + 4 files changed, 20 insertions(+), 86 deletions(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index 915f5a5..cc47ad9 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -58,6 +58,8 @@ procedure GetProduto(Req: THorseRequest; Res: THorseResponse); .ObterProdutoPorEan(LEanCode); Res.Send(TJson.ObjectToJsonObject(LProduto)); + + LProduto.Free; end; procedure GetProdutoFotoExiste(Req: THorseRequest; Res: THorseResponse); diff --git a/src/controllers/WsGTin.Controllers.UnidadeMedida.pas b/src/controllers/WsGTin.Controllers.UnidadeMedida.pas index 9398be6..fcc127b 100644 --- a/src/controllers/WsGTin.Controllers.UnidadeMedida.pas +++ b/src/controllers/WsGTin.Controllers.UnidadeMedida.pas @@ -12,55 +12,10 @@ implementation uses System.JSON, - Database.Factory; + Database.Factory, -function RemoveAcento(const ptext: string):string; -type - usaascii20127 = type ansistring(20127); -begin - result := string(usaascii20127(ptext)); -end; - -procedure GetDescricaoUnidadeMedida(Req: THorseRequest; Res: THorseResponse); -var wjson: tjsonobject; -begin - var LId := Req.Params.Field('id') - .Required - .RequiredMessage('Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3') - .AsString; - - {if mainview.MemoHistorico.lines.count > 10000 then - mainview.MemoHistorico.lines.clear;} // Alterar para estratégia de Log no Console - - var ds := TDatabaseFactory.New.SQL - .SQL('select nome from unidade_medida where id = :id') - .ParamList - .AddString('id', LId) - .&End - .Open; - - if not ds.IsEmpty then - begin - Res.Send(ds.FieldByName('nome').asstring).Status(200); -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+ -// timetostr(now)+'| Entregue descricao unidade medida: '+LId+ '|' + -// ds.FieldByName('nome').asstring); - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+LId)); - Res.Send(wjson).Status(404);; - -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+LId); - finally - end; - end; -end; + WsGtin.Model.Factory, + Horse.JsonInterceptor.Helpers; procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); var wjson: tjsonobject; @@ -70,50 +25,19 @@ procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); .RequiredMessage('Necessario enviar o codigo da unidade de medida. Ex: www.eanpictures.com.br:9000/api/um/M3') .AsString; - var ds := TDatabaseFactory.New.SQL - .SQL('select id, nome from unidade_medida where id = :id') - .ParamList - .AddString('id', LId) - .&End - .Open(); - - if not ds.IsEmpty then - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','200')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Ok')); - wjson.AddPair(tjsonpair.Create('id',removeacento(ds.FieldByName('id').AsString))); - wjson.AddPair(tjsonpair.Create('nome',removeacento(ds.FieldByName('nome').AsString))); - Res.Send(wjson).Status(200);; - -// inc(cont200); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont200)+'|'+datetostr(date)+'|'+timetostr(now)+'| Entregue descricao unidade medida: '+ -// LId+ '|' +ds.fieldbyname('nome').asstring); + var LUnidadeMedida := TWsGTinModelFactory.New + .UnidadeMedida + .ObterUnidadeMedida(LId); - finally - end; - end - else - begin - try - wjson:=tjsonobject.Create; - wjson.AddPair(tjsonpair.Create('Status','404')); - wjson.AddPair(tjsonpair.Create('Status_Desc','Descricao nao encontrada para a unidade de medida: '+LId)); - Res.Send(wjson).Status(404);; + Res.Send(TJson.ObjectToJsonObject(LUnidadeMedida)); -// inc(cont404); -// mainview.memohistorico.lines.add(Req.RawWebRequest.RemoteAddr+' | '+inttostr(cont404)+'|'+datetostr(date)+'|'+timetostr(now)+'| Descricao nao encontrada a unidade de meida: '+LId); - finally - end; - end; + LUnidadeMedida.Free; end; procedure Registry; begin THorse - .Get('/api/um2/:id', GetDescricaoUnidadeMedida) - .Get('/api/um/:id', GetUnidadeMedida) + .Get('/api/unidade-medida/:id', GetUnidadeMedida) ; end; diff --git a/src/model/WsGTin.Model.Factory.pas b/src/model/WsGTin.Model.Factory.pas index 77d36c6..2f06016 100644 --- a/src/model/WsGTin.Model.Factory.pas +++ b/src/model/WsGTin.Model.Factory.pas @@ -16,12 +16,14 @@ TWsGTinModelFactory = class(TInterfacedObject, IWsGTinModelFactory) { IWsGTinModelProduto } function Produto: IWsGTinModelProduto; + function UnidadeMedida: IWsGTinModelUnidadeMedida; end; implementation uses - WsGTin.Model.Produto; + WsGTin.Model.Produto, + WsGTin.Model.UnidadeMedida; { TWsGTinModelFactory } @@ -46,4 +48,9 @@ function TWsGTinModelFactory.Produto: IWsGTinModelProduto; Result := TWsGTinModelProduto.New; end; +function TWsGTinModelFactory.UnidadeMedida: IWsGTinModelUnidadeMedida; +begin + Result := TWsGTinModelUnidadeMedida.New; +end; + end. diff --git a/src/model/WsGTin.Model.Interfaces.pas b/src/model/WsGTin.Model.Interfaces.pas index 0a4a30f..b79b7f0 100644 --- a/src/model/WsGTin.Model.Interfaces.pas +++ b/src/model/WsGTin.Model.Interfaces.pas @@ -23,6 +23,7 @@ interface IWsGTinModelFactory = interface ['{B60DB98D-433B-4E91-91D2-7C831E599C2B}'] function Produto: IWsGTinModelProduto; + function UnidadeMedida: IWsGTinModelUnidadeMedida; end; implementation From 2f771eb542c725734ac854648805b915e2f3e84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:24:26 -0300 Subject: [PATCH 32/39] =?UTF-8?q?Removidas=20fun=C3=A7=C3=B5es=20e=20vari?= =?UTF-8?q?=C3=A1veis=20n=C3=A3o=20utilizadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WsGTin.Controllers.Produto.pas | 19 +++++-------------- .../WsGTin.Controllers.UnidadeMedida.pas | 4 ---- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/controllers/WsGTin.Controllers.Produto.pas b/src/controllers/WsGTin.Controllers.Produto.pas index cc47ad9..23c46d7 100644 --- a/src/controllers/WsGTin.Controllers.Produto.pas +++ b/src/controllers/WsGTin.Controllers.Produto.pas @@ -12,27 +12,18 @@ interface System.Classes, System.IOUtils, - Database.Factory, - - main.control, - - WsGTin.Model.Factory, - - Horse.JsonInterceptor.Helpers; + main.control; procedure Registry; //procedure ConfigSwagger; implementation -var LPath: String = ''; +uses + WsGTin.Model.Factory, + Horse.JsonInterceptor.Helpers; -function RemoveAcento(const ptext: string):string; -type - usaascii20127 = type ansistring(20127); -begin - result := string(usaascii20127(ptext)); -end; +var LPath: String = ''; function SomenteNumero(snum: string): string; var s1, s2: string; diff --git a/src/controllers/WsGTin.Controllers.UnidadeMedida.pas b/src/controllers/WsGTin.Controllers.UnidadeMedida.pas index fcc127b..e520fce 100644 --- a/src/controllers/WsGTin.Controllers.UnidadeMedida.pas +++ b/src/controllers/WsGTin.Controllers.UnidadeMedida.pas @@ -11,14 +11,10 @@ procedure Registry; implementation uses - System.JSON, - Database.Factory, - WsGtin.Model.Factory, Horse.JsonInterceptor.Helpers; procedure GetUnidadeMedida(Req: THorseRequest; Res: THorseResponse); -var wjson: tjsonobject; begin var LId := Req.Params.Field('id') .Required From 0f490de0f65bb53084915b7619b07f64a2e51899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:29:37 -0300 Subject: [PATCH 33/39] Retornando demais campos do cadastro de produto --- src/model/WsGTin.Model.Produto.pas | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/model/WsGTin.Model.Produto.pas b/src/model/WsGTin.Model.Produto.pas index 5cc5251..d796d17 100644 --- a/src/model/WsGTin.Model.Produto.pas +++ b/src/model/WsGTin.Model.Produto.pas @@ -49,8 +49,7 @@ function TWsGTinModelProduto.ObterProdutoPorEan( AEanCode: string): TWsGTinModelEntityProduto; begin var LSql := #13#10 - + 'SELECT cp.ean, cp.nome, cp.ncm, cp.cest_codigo, cp.embalagem, ' - + ' cp.quantidade_embalagem, cp.marca, cp.categoria, cp.link_foto ' + + 'SELECT * ' + 'FROM base_produtos.cad_produtos cp ' + 'where ean = :ean ' ; @@ -72,13 +71,23 @@ function TWsGTinModelProduto.ObterProdutoPorEan( Result.Ean := ds.FieldByName('ean').AsString; Result.Nome := ds.FieldByName('nome').AsString; - Result.CestCodigo := ds.FieldByName('cest_codigo').AsString; - Result.Embalagem := ds.FieldByName('embalagem').AsString; - Result.QuantidadeEmabalagem := ds.FieldByName('quantidade_embalagem').AsFloat; + Result.Ncm := ds.FieldByName('ncm').AsInteger; + Result.Valor := ds.FieldByName('valor').AsFloat; + Result.Avg := ds.FieldByName('avg').AsFloat; + Result.Ex := ds.FieldByName('ex').AsInteger; Result.Marca := ds.FieldByName('marca').AsString; + Result.Pais := ds.FieldByName('pais').AsString; Result.Categoria := ds.FieldByName('categoria').AsString; + Result.ValorMedio := ds.FieldByName('valor_medio').AsFloat; + Result.Atualizado := ds.FieldByName('atualizado').AsInteger; Result.Foto := ds.FieldByName('link_foto').AsString; - + Result.CestCodigo := ds.FieldByName('cest_codigo').AsString; + Result.DhUpdate := ds.FieldByName('dh_update').AsDateTime; + Result.Erro := ds.FieldByName('erro').AsInteger; + Result.Embalagem := ds.FieldByName('embalagem').AsString; + Result.QuantidadeEmabalagem := ds.FieldByName('quantidade_embalagem').AsFloat; + Result.Tributacao := ds.FieldByName('tributacao').AsString; + Result.ProdutoAcento := ds.FieldByName('produto_acento').AsString; end; end. From 02616e2c25529706c93f5ae47292cca93d35ae4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:38:51 -0300 Subject: [PATCH 34/39] Iniciando projeto Console --- WsGtin.Aplication.dproj | 2 +- WsGtin.Console.dpr | 17 ++++ WsGtin.Console.dproj | 192 +++++++++++++++++++++++++++++++++++ WsGtinProjectGroup.groupproj | 46 +++++---- 4 files changed, 239 insertions(+), 18 deletions(-) create mode 100644 WsGtin.Console.dpr create mode 100644 WsGtin.Console.dproj diff --git a/WsGtin.Aplication.dproj b/WsGtin.Aplication.dproj index 8a5c16a..121e53d 100644 --- a/WsGtin.Aplication.dproj +++ b/WsGtin.Aplication.dproj @@ -58,7 +58,7 @@ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png WsGTin_Aplication - ..\pascal-database-engine\src;modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src;$(DCC_UnitSearchPath) + ..\pascal-database-engine\src;$(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src 1046 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= diff --git a/WsGtin.Console.dpr b/WsGtin.Console.dpr new file mode 100644 index 0000000..1d61607 --- /dev/null +++ b/WsGtin.Console.dpr @@ -0,0 +1,17 @@ +program WsGtin.Console; + +{$APPTYPE CONSOLE} + +{$R *.res} + +uses + System.SysUtils; + +begin + try + { TODO -oUser -cConsole Main : Insert code here } + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; +end. diff --git a/WsGtin.Console.dproj b/WsGtin.Console.dproj new file mode 100644 index 0000000..316f862 --- /dev/null +++ b/WsGtin.Console.dproj @@ -0,0 +1,192 @@ + + + {19E3F538-6EA6-44BB-9F1D-E408CD0FDB34} + 19.5 + None + True + Debug + Win32 + 1 + Console + WsGtin.Console.dpr + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + WsGtin_Console + modules\.dcp;modules\.dcu;$(DCC_UnitSearchPath);modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src + + soapserver;IndySystem;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;rtl;FireDACSqliteDriver;DbxClientDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;soapmidas;inet;FireDAC;fmxase;xmlrtl;tethering;dbrtl;dsnap;CloudService;CustomIPTransport;FMXTee;soaprtl;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png + activity-1.1.0.dex.jar;annotation-1.2.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;biometric-1.1.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.1.0.dex.jar;core-runtime-2.1.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.2.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.2.0.dex.jar;lifecycle-runtime-2.2.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.2.0.dex.jar;lifecycle-viewmodel-savedstate-2.2.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;savedstate-1.0.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar + + + soapserver;IndySystem;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;rtl;FireDACSqliteDriver;DbxClientDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;soapmidas;inet;FireDAC;xmlrtl;tethering;dbrtl;dsnap;CloudService;CustomIPTransport;FMXTee;soaprtl;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png + $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png + activity-1.1.0.dex.jar;annotation-1.2.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;biometric-1.1.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.1.0.dex.jar;core-runtime-2.1.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.2.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.2.0.dex.jar;lifecycle-runtime-2.2.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.2.0.dex.jar;lifecycle-viewmodel-savedstate-2.2.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;savedstate-1.0.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar + + + soapserver;IndySystem;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;rtl;FireDACSqliteDriver;DbxClientDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;soapmidas;inet;FireDAC;fmxase;xmlrtl;tethering;dbrtl;dsnap;CloudService;CustomIPTransport;FMXTee;soaprtl;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) + + + soapserver;IndySystem;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;rtl;FireDACSqliteDriver;DbxClientDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;soapmidas;inet;FireDAC;fmxase;xmlrtl;tethering;dbrtl;dsnap;CloudService;CustomIPTransport;FMXTee;soaprtl;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) + + + soapserver;IndySystem;vclwinx;fmx;vclie;DbxCommonDriver;bindengine;vcldb;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;vclFireDAC;bindcompvclwinx;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;inetdb;rtl;FireDACMySQLDriver;FireDACSqliteDriver;DbxClientDriver;FireDACADSDriver;Tee;RESTComponents;DBXSqliteDriver;vcl;vclactnband;TeeUI;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;dsnapcon;soapmidas;adortl;DBXMySQLDriver;VclSmp;inet;vclimg;vcltouch;FireDACPgDriver;FireDAC;fmxase;inetdbxpress;xmlrtl;tethering;dbrtl;bindcompvcl;dsnap;fmxdae;TeeDB;CloudService;FireDACMSAccDriver;CustomIPTransport;fmxobj;bindcompvclsmp;FMXTee;soaprtl;vcldsnap;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + true + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + soapserver;IndySystem;vclwinx;fmx;vclie;DbxCommonDriver;bindengine;vcldb;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;vclFireDAC;bindcompvclwinx;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;inetdb;rtl;FireDACMySQLDriver;FireDACSqliteDriver;DbxClientDriver;FireDACADSDriver;Tee;RESTComponents;DBXSqliteDriver;vcl;vclactnband;TeeUI;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;dsnapcon;soapmidas;adortl;DBXMySQLDriver;VclSmp;inet;vclimg;vcltouch;FireDACPgDriver;FireDAC;fmxase;inetdbxpress;xmlrtl;tethering;dbrtl;bindcompvcl;dsnap;fmxdae;TeeDB;CloudService;FireDACMSAccDriver;CustomIPTransport;fmxobj;bindcompvclsmp;FMXTee;soaprtl;vcldsnap;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) + true + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DEBUG;$(DCC_Define) + true + false + true + true + true + true + true + + + false + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + + MainSource + + + Base + + + Cfg_1 + Base + + + Cfg_2 + Base + + + + Delphi.Personality.12 + Application + + + + WsGtin.Console.dpr + + + + + False + False + False + False + True + False + + + 12 + + + + + diff --git a/WsGtinProjectGroup.groupproj b/WsGtinProjectGroup.groupproj index cf04da0..3821638 100644 --- a/WsGtinProjectGroup.groupproj +++ b/WsGtinProjectGroup.groupproj @@ -3,10 +3,13 @@ {7C7B119B-AE55-4280-BAB0-D5FDC4EFB70A} - + - + + + + @@ -17,32 +20,41 @@ - - + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - + - + - +
From d09a4440e8aa60f4133c0cca2db57a166d8fa67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:51:15 -0300 Subject: [PATCH 35/39] =?UTF-8?q?Cria=C3=A7=C3=A3o=20de=20projeto=20Consol?= =?UTF-8?q?e=20com=20report=20de=20Memory=20Leak?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WsGtin.Console.dpr | 15 +- WsGtin.Console.dproj | 860 ++++++++++++++++++++++++++++++++++++++++++- src/wsHorse.pas | 17 +- 3 files changed, 887 insertions(+), 5 deletions(-) diff --git a/WsGtin.Console.dpr b/WsGtin.Console.dpr index 1d61607..578b262 100644 --- a/WsGtin.Console.dpr +++ b/WsGtin.Console.dpr @@ -5,11 +5,22 @@ program WsGtin.Console; {$R *.res} uses - System.SysUtils; + System.SysUtils, + main.control in 'src\main.control.pas', + WsGTin.Controllers.Produto in 'src\controllers\WsGTin.Controllers.Produto.pas', + WsGTin.Controllers.Registry in 'src\controllers\WsGTin.Controllers.Registry.pas', + WsGTin.Controllers.UnidadeMedida in 'src\controllers\WsGTin.Controllers.UnidadeMedida.pas', + wsHorse in 'src\wsHorse.pas', + WsGTin.Model.Factory in 'src\model\WsGTin.Model.Factory.pas', + WsGTin.Model.Interfaces in 'src\model\WsGTin.Model.Interfaces.pas', + WsGTin.Model.Produto in 'src\model\WsGTin.Model.Produto.pas', + WsGTin.Model.UnidadeMedida in 'src\model\WsGTin.Model.UnidadeMedida.pas', + WsGTin.Model.Entity.Produto in 'src\model\entity\WsGTin.Model.Entity.Produto.pas', + WsGTin.Model.Entity.UnidadeMedida in 'src\model\entity\WsGTin.Model.Entity.UnidadeMedida.pas'; begin try - { TODO -oUser -cConsole Main : Insert code here } + TMainControl.GetInstance.Power; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); diff --git a/WsGtin.Console.dproj b/WsGtin.Console.dproj index 316f862..88b315a 100644 --- a/WsGtin.Console.dproj +++ b/WsGtin.Console.dproj @@ -69,7 +69,8 @@ false System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) WsGtin_Console - modules\.dcp;modules\.dcu;$(DCC_UnitSearchPath);modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src + modules\.dcp;modules\.dcu;modules;modules\handle-exception\src;modules\horse\src;modules\horse-jsoninterceptor\src;modules\horse-octet-stream\src;modules\jhonson\src;modules\pascal-database-engine\src;$(DCC_UnitSearchPath) + soapserver;IndySystem;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcomp;FmxTeeUI;FireDACCommon;IndyCore;RESTBackendComponents;bindcompfmx;bindcompdbx;rtl;FireDACSqliteDriver;DbxClientDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;fmxFireDAC;dbexpress;dsnapxml;soapmidas;inet;FireDAC;fmxase;xmlrtl;tethering;dbrtl;dsnap;CloudService;CustomIPTransport;FMXTee;soaprtl;DBXInterBaseDriver;FireDACIBDriver;$(DCC_UsePackage) $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png @@ -153,6 +154,17 @@ MainSource + + + + + + + + + + + Base @@ -174,7 +186,851 @@ WsGtin.Console.dpr - + + + + true + + + + + true + + + + + true + + + + + WsGtin_Console.exe + true + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + classes + 64 + + + classes + 64 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + ..\ + 1 + + + + + Contents + 1 + + + Contents + 1 + + + Contents + 1 + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + ..\ + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen + 64 + + + ..\$(PROJECTNAME).launchscreen + 64 + + + + + 1 + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + + + + + + + + + + False False diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 8c342f4..02cf8f1 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -40,7 +40,9 @@ implementation uses System.Classes, System.IOUtils, + {$IF (not defined(CONSOLE))} main.view, + {$ENDIF} system.JSON, Database.Factory, @@ -69,6 +71,11 @@ procedure TWsHorse.AddMethods; constructor TWsHorse.Create; begin + {$IFDEF MSWINDOWS} + IsConsole := False; + ReportMemoryLeaksOnShutdown := True; + {$ENDIF} + LoadDatabaseConfig; THorse @@ -123,7 +130,13 @@ procedure TWsHorse.Power; begin if THorse.IsRunning then THorse.StopListen - else THorse.Listen; + else THorse.Listen( + procedure begin + {$IF defined(CONSOLE) and (not defined(TEST))} + Writeln(Format('Server is runing on %s:%d', [THorse.Host, THorse.Port])); + Readln; + {$ENDIF} + end); end; function twshorse.removeacento(const ptext: string):string; @@ -172,7 +185,9 @@ procedure TWsHorse.baixacosmos(const ean: string); // Client_.Free; + {$IF (not defined(CONSOLE))} mainview.MemoHistorico.lines.ADD('******Baixado arquivo direto da cosmos: '+lfile+' | '+'https://cdn-cosmos.bluesoft.com.br/products/' + EAN); + {$ENDIF} end; From 220aec940225ba2feb0d36b20d25bf0fae914dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:51:31 -0300 Subject: [PATCH 36/39] adicionando arquivo refatoracao.md --- refatoracao.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 refatoracao.md diff --git a/refatoracao.md b/refatoracao.md new file mode 100644 index 0000000..374f5c3 --- /dev/null +++ b/refatoracao.md @@ -0,0 +1,26 @@ +# Refatoração EAN Pictures - 1a etapa + +- [ ] Mudar o tipo de aplicação para console +- [ ] Remoção do Main.View.pas +- [ ] Migrar para a nova versão do Horse +- [ ] Remover acesso de recursos visuais da API +- [ ] Criar uma unit específica para conexão com banco de dados +- [ ] Remover Uses do Zeos na classe de conexão com banco de dados +- [ ] Remover Utilização de variáveis globais +- [ ] No endpoint /api/desc_ini/:id garantir que a variável seja destruída + +# Refatoração EAN Pictures - 2a etapa (melhoria na estrutura do projeto) + +- [ ] Organização do projeto em pastas (controllers, providers, services) +- [ ] organização e nomeação dos endpoints +- [ ] Passagem de filtros +- [ ] Separar em responsabilidades o conteúdo que está na wsHorse +- [ ] Padronizar Nome de variáveis e parâmetros de funções +- [ ] Blocos try-finally sem necessidade +- [ ] Rever Uso do with +- [ ] Manter um padrão na resposta dos dados, uma hora retorna JSON, outra um texto +- [ ] Parâmetro Next não é mais necessário na nova versão do Horse +- [ ] Não precisa ficar criando TJSONPair para cada pair adicionado +- [ ] Uso do FreeAndNil sem necessidade no endpoint /api/desc_ini/:id +- [ ] Identação de código +- [ ] Excluir Componente para fazer requisição \ No newline at end of file From 19627fb8e1c7794591362d60618e26e7653b262c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:53:20 -0300 Subject: [PATCH 37/39] =?UTF-8?q?Identificando=20pontos=20j=C3=A1=20supera?= =?UTF-8?q?dos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refatoracao.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/refatoracao.md b/refatoracao.md index 374f5c3..808c8bb 100644 --- a/refatoracao.md +++ b/refatoracao.md @@ -1,24 +1,24 @@ # Refatoração EAN Pictures - 1a etapa -- [ ] Mudar o tipo de aplicação para console +- [X] Mudar o tipo de aplicação para console - [ ] Remoção do Main.View.pas -- [ ] Migrar para a nova versão do Horse +- [X] Migrar para a nova versão do Horse - [ ] Remover acesso de recursos visuais da API -- [ ] Criar uma unit específica para conexão com banco de dados -- [ ] Remover Uses do Zeos na classe de conexão com banco de dados +- [X] Criar uma unit específica para conexão com banco de dados +- [X] Remover Uses do Zeos na classe de conexão com banco de dados - [ ] Remover Utilização de variáveis globais -- [ ] No endpoint /api/desc_ini/:id garantir que a variável seja destruída +- [X] No endpoint /api/desc_ini/:id garantir que a variável seja destruída # Refatoração EAN Pictures - 2a etapa (melhoria na estrutura do projeto) - [ ] Organização do projeto em pastas (controllers, providers, services) -- [ ] organização e nomeação dos endpoints +- [X] organização e nomeação dos endpoints - [ ] Passagem de filtros - [ ] Separar em responsabilidades o conteúdo que está na wsHorse - [ ] Padronizar Nome de variáveis e parâmetros de funções - [ ] Blocos try-finally sem necessidade - [ ] Rever Uso do with -- [ ] Manter um padrão na resposta dos dados, uma hora retorna JSON, outra um texto +- [X] Manter um padrão na resposta dos dados, uma hora retorna JSON, outra um texto - [ ] Parâmetro Next não é mais necessário na nova versão do Horse - [ ] Não precisa ficar criando TJSONPair para cada pair adicionado - [ ] Uso do FreeAndNil sem necessidade no endpoint /api/desc_ini/:id From 28da7700ad1c6c9eca1b4483c7c29506b5a3e1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:56:17 -0300 Subject: [PATCH 38/39] =?UTF-8?q?Atualizando=20pontos=20j=C3=A1=20superado?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refatoracao.md | 10 +++++----- src/wsHorse.pas | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/refatoracao.md b/refatoracao.md index 808c8bb..11e0801 100644 --- a/refatoracao.md +++ b/refatoracao.md @@ -14,13 +14,13 @@ - [ ] Organização do projeto em pastas (controllers, providers, services) - [X] organização e nomeação dos endpoints - [ ] Passagem de filtros -- [ ] Separar em responsabilidades o conteúdo que está na wsHorse +- [X] Separar em responsabilidades o conteúdo que está na wsHorse - [ ] Padronizar Nome de variáveis e parâmetros de funções -- [ ] Blocos try-finally sem necessidade -- [ ] Rever Uso do with +- [X] Blocos try-finally sem necessidade +- [X] Rever Uso do with - [X] Manter um padrão na resposta dos dados, uma hora retorna JSON, outra um texto -- [ ] Parâmetro Next não é mais necessário na nova versão do Horse +- [X] Parâmetro Next não é mais necessário na nova versão do Horse - [ ] Não precisa ficar criando TJSONPair para cada pair adicionado -- [ ] Uso do FreeAndNil sem necessidade no endpoint /api/desc_ini/:id +- [X] Uso do FreeAndNil sem necessidade no endpoint /api/desc_ini/:id - [ ] Identação de código - [ ] Excluir Componente para fazer requisição \ No newline at end of file diff --git a/src/wsHorse.pas b/src/wsHorse.pas index 02cf8f1..84c5f29 100644 --- a/src/wsHorse.pas +++ b/src/wsHorse.pas @@ -61,7 +61,7 @@ procedure TWsHorse.AddMethods; THorse .Get('/api/version', - procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc) + procedure(Req: THorseRequest; Res: THorseResponse) begin var LVersao := TJsonObject.Create; LVersao.AddPair('horseVersion', THorse.Version); From eddc73b23e431a8691f632b6f12b67368cb20b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20C=C3=A9sar=20Fernandes=20Nogueira?= Date: Thu, 17 Aug 2023 08:57:00 -0300 Subject: [PATCH 39/39] Removido antigo refatoracao.txt --- refatoracao.txt | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 refatoracao.txt diff --git a/refatoracao.txt b/refatoracao.txt deleted file mode 100644 index a65162e..0000000 --- a/refatoracao.txt +++ /dev/null @@ -1,10 +0,0 @@ -Refatoração EAN Pictures - 1a etapa - -- Mudar o tipo de aplicação para console -- Remoção do Main.View.pas -- Migrar para a nova versão do Horse -- Remover acesso de recursos visuais da API -- Criar uma unit específica para conexão com banco de dados -- Remover Uses do Zeos na classe de conexão com banco de dados -- Remover Utilização de variáveis globais -- No endpoint /api/desc_ini/:id garantir que a variável seja destruída \ No newline at end of file