diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..7f9929bc6 Binary files /dev/null and b/.DS_Store differ diff --git a/azure-pipelines/fiskaltrust.Middleware.Queue-Release.yml b/azure-pipelines/fiskaltrust.Middleware.Queue-Release.yml index e0f8d0baf..2ccba5316 100644 --- a/azure-pipelines/fiskaltrust.Middleware.Queue-Release.yml +++ b/azure-pipelines/fiskaltrust.Middleware.Queue-Release.yml @@ -35,3 +35,53 @@ stages: environment: production storage: stprodwesteuropepackages serviceConnection: rg-prod-westeurope-packages + + - template: templates/release-legacy.yml + parameters: + type: fiskaltrust.Middleware.Queue + artifact: build + projects: + - InMemory + - SQLite + - EF + - MySQL + - PostgreSQL + stages: + - stage: Release_Sandbox_Legacy + dependsOn: [] + templateContext: + environment: sandbox-legacy + storage: fiskaltrustsandbox + serviceConnection: sandbox-legacy-packages + + - stage: Release_Production_Legacy + templateContext: + dependsOnPrefix: Release_Sandbox_Legacy + environment: production-legacy + storage: fiskaltrustcommonwe1 + serviceConnection: production-legacy-packages + + - template: templates/release-legacy-nuget.yml + parameters: + type: fiskaltrust.Middleware.Queue + artifact: build + projects: + - InMemory + - SQLite + - EF + - MySQL + - PostgreSQL + stages: + - stage: Release_Sandbox_Legacy_Nuget + dependsOn: [] + templateContext: + environment: sandbox-legacy-nuget + feed: dev + serviceConnection: sandbox-legacy-packages + + - stage: Release_Production_Legacy_Nuget + templateContext: + dependsOnPrefix: Release_Sandbox_Legacy_Nuget + environment: production-legacy-nuget + feed: middleware + serviceConnection: production-legacy-packages \ No newline at end of file diff --git a/azure-pipelines/fiskaltrust.Middleware.SCU.DE-Release.yml b/azure-pipelines/fiskaltrust.Middleware.SCU.DE-Release.yml index 6b27516f0..0f23774c9 100644 --- a/azure-pipelines/fiskaltrust.Middleware.SCU.DE-Release.yml +++ b/azure-pipelines/fiskaltrust.Middleware.SCU.DE-Release.yml @@ -38,3 +38,59 @@ stages: environment: production storage: stprodwesteuropepackages serviceConnection: rg-prod-westeurope-packages + + - template: templates/release-legacy.yml + parameters: + type: fiskaltrust.Middleware.SCU.DE + artifact: build + projects: + - CryptoVision + - DieboldNixdorf + - Epson + - FiskalyCertified + - Swissbit + - DeutscheFiskal + - SwissbitCloud + - InMemory + stages: + - stage: Release_Sandbox_Legacy + dependsOn: [] + templateContext: + environment: sandbox-legacy + storage: fiskaltrustsandbox + serviceConnection: sandbox-legacy-packages + + - stage: Release_Production_Legacy + templateContext: + dependsOnPrefix: Release_Sandbox_Legacy + environment: production-legacy + storage: fiskaltrustcommonwe1 + serviceConnection: production-legacy-packages + + - template: templates/release-legacy-nuget.yml + parameters: + type: fiskaltrust.Middleware.SCU.DE + artifact: build + projects: + - CryptoVision + - DieboldNixdorf + - Epson + - FiskalyCertified + - Swissbit + - DeutscheFiskal + - SwissbitCloud + - InMemory + stages: + - stage: Release_Sandbox_Legacy_Nuget + dependsOn: [] + templateContext: + environment: sandbox-legacy-nuget + feed: dev + serviceConnection: sandbox-legacy-packages + + - stage: Release_Production_Legacy_Nuget + templateContext: + dependsOnPrefix: Release_Sandbox_Legacy_Nuget + environment: production-legacy-nuget + feed: middleware + serviceConnection: production-legacy-packages \ No newline at end of file diff --git a/azure-pipelines/fiskaltrust.Middleware.SCU.IT-Release.yml b/azure-pipelines/fiskaltrust.Middleware.SCU.IT-Release.yml index d6b3dcf92..be8c33167 100644 --- a/azure-pipelines/fiskaltrust.Middleware.SCU.IT-Release.yml +++ b/azure-pipelines/fiskaltrust.Middleware.SCU.IT-Release.yml @@ -16,7 +16,9 @@ stages: type: fiskaltrust.Middleware.SCU.IT artifact: build projects: - - Epson + - EpsonRTPrinter + - CustomRTPrinter + - CustomRTServer stages: - stage: Release_Sandbox dependsOn: [] @@ -25,9 +27,32 @@ stages: storage: stdevwesteuropepackages serviceConnection: rg-dev-westeurope-packages - # - stage: Release_Production - # templateContext: - # environment: production - # storage: stprodwesteuropepackages - # serviceConnection: rg-prod-westeurope-packages - # dependsOnPrefix: Release_Sandbox + - stage: Release_Production + templateContext: + environment: production + storage: stprodwesteuropepackages + serviceConnection: rg-prod-westeurope-packages + dependsOnPrefix: Release_Sandbox + + - template: templates/release-legacy.yml + parameters: + type: fiskaltrust.Middleware.SCU.IT + artifact: build + projects: + - EpsonRTPrinter + - CustomRTPrinter + - CustomRTServer + stages: + - stage: Release_Sandbox_Legacy + dependsOn: [] + templateContext: + environment: sandbox-legacy + storage: fiskaltrustsandbox + serviceConnection: sandbox-legacy-packages + + - stage: Release_Production_Legacy + templateContext: + dependsOnPrefix: Release_Sandbox_Legacy + environment: production-legacy + storage: fiskaltrustcommonwe1 + serviceConnection: production-legacy-packages \ No newline at end of file diff --git a/azure-pipelines/fiskaltrust.Middleware.SCU.IT.yml b/azure-pipelines/fiskaltrust.Middleware.SCU.IT.yml index 061d1f3ab..7d365e282 100644 --- a/azure-pipelines/fiskaltrust.Middleware.SCU.IT.yml +++ b/azure-pipelines/fiskaltrust.Middleware.SCU.IT.yml @@ -62,4 +62,6 @@ stages: parameters: workingDirectory: scu-it projects: - - fiskaltrust.Middleware.SCU.IT.Epson + - fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter + - fiskaltrust.Middleware.SCU.IT.CustomRTServer + - fiskaltrust.Middleware.SCU.IT.CustomRTPrinter diff --git a/azure-pipelines/templates/release-legacy-nuget.yml b/azure-pipelines/templates/release-legacy-nuget.yml new file mode 100644 index 000000000..dc576bc64 --- /dev/null +++ b/azure-pipelines/templates/release-legacy-nuget.yml @@ -0,0 +1,55 @@ +parameters: +- name: stages + type: stageList + +- name: type + type: string + +- name: artifact + type: string + default: current + +- name: projects + type: object + +stages: +- ${{ each project in parameters.projects }}: + - ${{ each stage in parameters.stages }}: + - ${{ each pair in stage }}: + ${{ if eq(pair.key, 'stage') }}: + stage: ${{ pair.value }}_${{ project }} + ${{ else }}: + ${{ pair.key }}: ${{ pair.value }} + + displayName: ${{ stage.templateContext.environment }} ${{ project }} + + ${{ if ne(stage.templateContext.dependsOnPrefix, '') }}: + dependsOn: ${{ stage.templateContext.dependsOnPrefix }}_${{ replace(project, '.', '_') }} + + ${{ if eq(stage.templateContext.environment, 'production-legacy-nuget') }}: + condition: and(startsWith(variables['Build.SourceBranch'], 'refs/tags/'), contains(variables['Build.SourceBranch'], lower('/${{ project }}/v'))) + ${{ else }}: + condition: or(not(startsWith(variables['Build.SourceBranch'], 'refs/tags/')), and(startsWith(variables['Build.SourceBranch'], 'refs/tags/'), contains(variables['Build.SourceBranch'], lower('/${{ project }}/v')))) + + jobs: + - deployment: Release + + pool: + vmImage: windows-latest + + environment: ${{ stage.templateContext.serviceConnection }} + + strategy: + runOnce: + deploy: + steps: + - download: ${{ parameters.artifact }} + artifact: packages-v1 + displayName: "Download artifact" + + - task: NuGetCommand@2 + displayName: 'NuGet push' + inputs: + command: push + packagesToPush: '${{ parameters.type }}.${{ project }}.*.nupkg' + publishVstsFeed: '${{ stage.templateContext.feed }}' \ No newline at end of file diff --git a/azure-pipelines/templates/release-legacy.yml b/azure-pipelines/templates/release-legacy.yml new file mode 100644 index 000000000..3cb5e1a0d --- /dev/null +++ b/azure-pipelines/templates/release-legacy.yml @@ -0,0 +1,57 @@ +parameters: +- name: stages + type: stageList + +- name: type + type: string + +- name: artifact + type: string + default: current + +- name: projects + type: object + +stages: +- ${{ each project in parameters.projects }}: + - ${{ each stage in parameters.stages }}: + - ${{ each pair in stage }}: + ${{ if eq(pair.key, 'stage') }}: + stage: ${{ pair.value }}_${{ project }} + ${{ else }}: + ${{ pair.key }}: ${{ pair.value }} + + displayName: ${{ stage.templateContext.environment }} ${{ project }} + + ${{ if ne(stage.templateContext.dependsOnPrefix, '') }}: + dependsOn: ${{ stage.templateContext.dependsOnPrefix }}_${{ replace(project, '.', '_') }} + + ${{ if eq(stage.templateContext.environment, 'production-legacy') }}: + condition: and(startsWith(variables['Build.SourceBranch'], 'refs/tags/'), contains(variables['Build.SourceBranch'], lower('/${{ project }}/v'))) + ${{ else }}: + condition: or(not(startsWith(variables['Build.SourceBranch'], 'refs/tags/')), and(startsWith(variables['Build.SourceBranch'], 'refs/tags/'), contains(variables['Build.SourceBranch'], lower('/${{ project }}/v')))) + + jobs: + - deployment: Release + + pool: + vmImage: windows-latest + + environment: ${{ stage.templateContext.serviceConnection }} + + strategy: + runOnce: + deploy: + steps: + - download: ${{ parameters.artifact }} + artifact: packages-v1 + displayName: "Download artifact" + + - task: AzureCLI@2 + displayName: "Publish to blob storage" + inputs: + azureSubscription: ${{ stage.templateContext.serviceConnection }} + scriptType: ps + scriptLocation: inlineScript + inlineScript: | + az storage blob upload-batch --account-name ${{ stage.templateContext.storage }} -d "packages" -s "$(Pipeline.Workspace)/${{ parameters.artifact }}/packages-v1/" --pattern "${{ parameters.type }}.${{ project }}.*.nupkg" \ No newline at end of file diff --git a/azure-pipelines/templates/scu-it/build-nuget.template.yml b/azure-pipelines/templates/scu-it/build-nuget.template.yml index b1277e634..b51843755 100644 --- a/azure-pipelines/templates/scu-it/build-nuget.template.yml +++ b/azure-pipelines/templates/scu-it/build-nuget.template.yml @@ -43,8 +43,16 @@ steps: $(WorkingDirectory)/src/**/*fiskaltrust*.exe - script: dotnet pack --output $(Build.ArtifactStagingDirectory) --no-restore --configuration $(buildConfiguration) - displayName: 'dotnet pack fiskaltrust.Middleware.SCU.IT.Epson' - workingDirectory: '$(WorkingDirectory)/src/fiskaltrust.Middleware.SCU.IT.Epson' + displayName: 'dotnet pack fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter' + workingDirectory: '$(WorkingDirectory)/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter' + +- script: dotnet pack --output $(Build.ArtifactStagingDirectory) --no-restore --configuration $(buildConfiguration) + displayName: 'dotnet pack fiskaltrust.Middleware.SCU.IT.CustomRTServer' + workingDirectory: '$(WorkingDirectory)/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer' + +- script: dotnet pack --output $(Build.ArtifactStagingDirectory) --no-restore --configuration $(buildConfiguration) + displayName: 'dotnet pack fiskaltrust.Middleware.SCU.IT.CustomRTPrinter' + workingDirectory: '$(WorkingDirectory)/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter' - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' diff --git a/nuget.config b/nuget.config index 0892f6b55..9abfa3796 100644 --- a/nuget.config +++ b/nuget.config @@ -6,6 +6,8 @@ - + + \ No newline at end of file diff --git a/queue/fiskaltrust.Middleware.sln b/queue/fiskaltrust.Middleware.sln index 49a6d21aa..b686d7b64 100644 --- a/queue/fiskaltrust.Middleware.sln +++ b/queue/fiskaltrust.Middleware.sln @@ -127,13 +127,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.Loca EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.Localization.QueueIT", "src\fiskaltrust.Middleware.Localization.QueueIT\fiskaltrust.Middleware.Localization.QueueIT.csproj", "{65633C3A-65AA-4E05-8E56-7A348872CCC3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fiskaltrust.Middleware.Localization.QueueIT.UnitTest", "test\fiskaltrust.Middleware.Localization.QueueIT.UnitTest\fiskaltrust.Middleware.Localization.QueueIT.UnitTest.csproj", "{5FAB9D88-4B90-4DF0-B1B7-1F50DF7CFCA4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.Localization.QueueIT.UnitTest", "test\fiskaltrust.Middleware.Localization.QueueIT.UnitTest\fiskaltrust.Middleware.Localization.QueueIT.UnitTest.csproj", "{5FAB9D88-4B90-4DF0-B1B7-1F50DF7CFCA4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fiskaltrust.Middleware.Localization.QueueDEFAULT", "src\fiskaltrust.Middleware.Localization.QueueDEFAULT\fiskaltrust.Middleware.Localization.QueueDEFAULT.csproj", "{3C0310D9-EC55-4115-A2D5-0DC8C1246645}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.Localization.QueueDEFAULT", "src\fiskaltrust.Middleware.Localization.QueueDEFAULT\fiskaltrust.Middleware.Localization.QueueDEFAULT.csproj", "{3C0310D9-EC55-4115-A2D5-0DC8C1246645}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fiskaltrust.Middleware.Localization.QueueDEFAULT.UnitTest", "test\fiskaltrust.Middleware.Localization.QueueDEFAULT.UnitTest\fiskaltrust.Middleware.Localization.QueueDEFAULT.UnitTest.csproj", "{04B32BB6-2E1D-400F-B7B2-2638483B0825}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.Localization.QueueDEFAULT.UnitTest", "test\fiskaltrust.Middleware.Localization.QueueDEFAULT.UnitTest\fiskaltrust.Middleware.Localization.QueueDEFAULT.UnitTest.csproj", "{04B32BB6-2E1D-400F-B7B2-2638483B0825}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fiskaltrust.Middleware.Localization.QueueFR.IntegrationTest", "test\fiskaltrust.Middleware.Localization.QueueFR.IntegrationTest\fiskaltrust.Middleware.Localization.QueueFR.IntegrationTest.csproj", "{7F52D143-9179-4FCF-9DC7-B5F1681BD22A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.Localization.QueueFR.IntegrationTest", "test\fiskaltrust.Middleware.Localization.QueueFR.IntegrationTest\fiskaltrust.Middleware.Localization.QueueFR.IntegrationTest.csproj", "{7F52D143-9179-4FCF-9DC7-B5F1681BD22A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/queue/src/Directory.Build.props b/queue/src/Directory.Build.props index 396315fff..f6b2fd8d0 100644 --- a/queue/src/Directory.Build.props +++ b/queue/src/Directory.Build.props @@ -3,10 +3,11 @@ netstandard2.0;netstandard2.1;net461;net6 + NU1901;NU1902;NU1903;NU1904 - + NU1605 diff --git a/queue/src/fiskaltrust.Middleware.Contracts/Extensions/ReceiptRequestExtensions.cs b/queue/src/fiskaltrust.Middleware.Contracts/Extensions/ReceiptRequestExtensions.cs deleted file mode 100644 index 233ce6d12..000000000 --- a/queue/src/fiskaltrust.Middleware.Contracts/Extensions/ReceiptRequestExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using fiskaltrust.ifPOS.v1; - -namespace fiskaltrust.Middleware.Contracts.Extensions -{ - public static class ReceiptRequestExtensions - { - public static bool IsVoid(this ReceiptRequest receiptRequest) - { - return (receiptRequest.ftReceiptCase & 0x0000_0000_0004_0000) > 0x0000; - } - - public static bool IsFailedReceipt(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0001_0000) != 0; - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueDE/Extensions/ReceiptRequestExtensions.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueDE/Extensions/ReceiptRequestExtensions.cs index 228971e1c..523e39c38 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueDE/Extensions/ReceiptRequestExtensions.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueDE/Extensions/ReceiptRequestExtensions.cs @@ -109,6 +109,11 @@ public static bool IsFailTransactionReceipt(this ReceiptRequest receiptRequest) { return ((receiptRequest.ftReceiptCase & 0x0000_0000_0000_FFFF) == 0x0000_0000_0000_000B); } + + public static bool IsVoid(this ReceiptRequest receiptRequest) + { + return (receiptRequest.ftReceiptCase & 0x0000_0000_0004_0000) > 0x0000; + } public static string GetReceiptIdentification(this ReceiptRequest receiptRequest, long receiptNumerator, ulong? transactionNumber) { @@ -368,7 +373,7 @@ public static string GetReceiptTaxes(this ReceiptRequest request) special_2 += item.Amount * GetSignForAmount(item.Quantity, item.Amount); break; default: - zero += item.Amount * GetSignForAmount(item.Quantity, item.Amount); + zero += item.Amount * GetSignForAmount(item.Quantity, item.Amount); break; } @@ -393,7 +398,7 @@ public static string GetReceiptTaxes(this ReceiptRequest request) case 0x0015: case 0x0016: case 0x0017: - item.Amount = item.Amount*GetSignForAmount(item.Quantity, item.Amount); + item.Amount = item.Amount * GetSignForAmount(item.Quantity, item.Amount); zero += item.Amount * -1; break; default: @@ -402,8 +407,8 @@ public static string GetReceiptTaxes(this ReceiptRequest request) } //TODO check rounding problesm: round sum(results) towards receipt.totalamount if given - return FormatAmount(normal) + "_" + FormatAmount(discounted_1) + "_" + FormatAmount( special_1) + - "_" + FormatAmount(special_2) + "_" + FormatAmount( zero); + return FormatAmount(normal) + "_" + FormatAmount(discounted_1) + "_" + FormatAmount(special_1) + + "_" + FormatAmount(special_2) + "_" + FormatAmount(zero); } private static string FormatAmount(decimal value) { @@ -424,10 +429,10 @@ DateTime GetMinDateTime(IEnumerable dts) request.cbReceiptMoment }).Min(); } - private static decimal GetSignForAmount(decimal quantity, decimal amount) => quantity < 0 && amount >= 0 ? -1 : 1; + private static decimal GetSignForAmount(decimal quantity, decimal amount) => quantity < 0 && amount >= 0 ? -1 : 1; public static void CheckForEqualSumChargePayItems(this ReceiptRequest request, ILogger logger) { - var chargeAmount = request.cbChargeItems != null ? request.cbChargeItems.Sum( x => x.Amount != null ? x.Amount * GetSignForAmount(x.Quantity, x.Amount) : 0) : 0; + var chargeAmount = request.cbChargeItems != null ? request.cbChargeItems.Sum(x => x.Amount != null ? x.Amount * GetSignForAmount(x.Quantity, x.Amount) : 0) : 0; var payAmount = request.cbPayItems != null ? request.cbPayItems.Sum(x => x.Amount != null ? x.Amount * GetSignForAmount(x.Quantity, x.Amount) : 0) : 0; if (chargeAmount != payAmount) { diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueDE/MasterData/MasterDataService.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueDE/MasterData/MasterDataService.cs index 71592b657..59e3ae5d3 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueDE/MasterData/MasterDataService.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueDE/MasterData/MasterDataService.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; using fiskaltrust.Middleware.Contracts.Models; using fiskaltrust.Middleware.Contracts.Repositories; using fiskaltrust.storage.V0.MasterData; @@ -93,4 +94,4 @@ public async Task PersistConfigurationAsync() } } } -} +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/Cases.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/Cases.cs index de9582897..dc8e13df7 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/Cases.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/Cases.cs @@ -1,7 +1,16 @@ +using System.Globalization; + namespace fiskaltrust.Middleware.Localization.QueueIT.Constants { public class Cases { - public const long BASE_STATE = 0x4954000000000000; + public const long BASE_STATE = 0x4954_2000_0000_0000; + + public static NumberFormatInfo CurrencyFormatter = new() + { + NumberDecimalSeparator = ",", + NumberGroupSeparator = "", + CurrencyDecimalDigits = 2 + }; } } \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/CountrySpecificSettings.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/CountrySpecificSettings.cs deleted file mode 100644 index 8dba553c3..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/CountrySpecificSettings.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Repositories; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Constants -{ - public class CountrySpecificSettings : ICountrySpecificSettings - { - public long CountryBaseState => Cases.BASE_STATE; - - public bool ResendFailedReceipts => true; - - public ICountrySpecificQueueRepository CountrySpecificQueueRepository { get; private set; } - - public CountrySpecificSettings(ICountrySpecificQueueRepository countrySpecificQueueRepository) - { - CountrySpecificQueueRepository = countrySpecificQueueRepository; - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/SignatureTypesIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/SignatureTypesIT.cs new file mode 100644 index 000000000..f7fabee48 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/SignatureTypesIT.cs @@ -0,0 +1,21 @@ +namespace fiskaltrust.Middleware.Localization.QueueIT.Constants +{ + public enum SignatureTypesIT + { + PosReceiptPrimarySignature = 0x01, + PosReceiptSecondarySignature = 0x02, + RTSerialNumber = 0x010, + RTZNumber = 0x11, + RTDocumentNumber = 0x12, + RTDocumentMoment = 0x13, + RTDocumentType = 0x14, + RTLotteryID = 0x15, + RTCustomerID = 0x16, + RTServerShaMetadata = 0x17, + RTAmount = 0x18, + + RTReferenceZNumber = 0x20, + RTReferenceDocumentNumber = 0x21, + RTReferenceDocumentMoment = 0x22 + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/States.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/States.cs deleted file mode 100644 index df0636bc3..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Constants/States.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace fiskaltrust.Middleware.Localization.QueueIT.Constants -{ - public class States - { - public const long ToOldForLateSigning = Cases.BASE_STATE + 0x03; - } - - public class StateFlags - { - public const long ReceiptsNeedManualUpload = 0x0000_0000_0001_0000; - } -} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/CbReferenceExistsException.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/CbReferenceExistsException.cs deleted file mode 100644 index 320a87feb..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/CbReferenceExistsException.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Exceptions -{ - [Serializable] - public class CbReferenceExistsException : ArgumentException - { - public static readonly string _message = "CbReference {0} from Request already exists in the database, use an unique cbReference for each transaction."; - public CbReferenceExistsException() { } - - public CbReferenceExistsException(string reference) : base(string.Format(_message, reference)) { } - public CbReferenceExistsException(string reference, Exception inner) : base(string.Format(_message, reference), inner) { } - protected CbReferenceExistsException(SerializationInfo info, StreamingContext context) : base(info, context) { } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/ItemPaymentInequalityException.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/ItemPaymentInequalityException.cs deleted file mode 100644 index 07e0e1bf9..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/ItemPaymentInequalityException.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Exceptions -{ - [Serializable] - public class ItemPaymentInequalityException : Exception - { - public static readonly string _message = "Pament sum of {0} is inequal to chargeitem sum {1}."; - public ItemPaymentInequalityException() { } - - public ItemPaymentInequalityException(decimal paymentSum, decimal chargeItemSum) : base(string.Format(_message, paymentSum, chargeItemSum)) { } - public ItemPaymentInequalityException(decimal paymentSum, decimal chargeItemSum, Exception inner) : base(string.Format(_message, paymentSum, chargeItemSum), inner) { } - protected ItemPaymentInequalityException(SerializationInfo info, StreamingContext context) : base(info, context) { } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/MultiUseVoucherNoSaleException.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/MultiUseVoucherNoSaleException.cs deleted file mode 100644 index 4cefd41a0..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/MultiUseVoucherNoSaleException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Exceptions -{ - [Serializable] - public class MultiUseVoucherNoSaleException : ArgumentException - { - public static readonly string _message = "In a multi use Voucher sale no other chargeitems can be sold!"; - - public MultiUseVoucherNoSaleException() : base(_message) { } - public MultiUseVoucherNoSaleException(Exception inner) : base(_message, inner) { } - protected MultiUseVoucherNoSaleException(SerializationInfo info, StreamingContext context) : base(info, context) { } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/RefundException.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/RefundException.cs deleted file mode 100644 index 342de521b..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Exceptions/RefundException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Exceptions -{ - [Serializable] - public class RefundException : ArgumentException - { - public RefundException() { } - public RefundException(string message) : base(message) { } - public RefundException(string message, Exception inner) : base(message, inner) { } - protected RefundException(SerializationInfo info, StreamingContext context) : base(info, context) { } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ChargeItemExtensions.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ChargeItemExtensions.cs deleted file mode 100644 index 3e528e29a..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ChargeItemExtensions.cs +++ /dev/null @@ -1,117 +0,0 @@ -using fiskaltrust.ifPOS.v1; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Contracts.Exceptions; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Extensions -{ - public static class ChargeItemExtensions - { - - // TODO: check VAT rate table on printer at the moment according to xml example - private static readonly int _vatRateBasic = 1; - private static readonly int _vatRateDeduction1 = 2; - private static readonly int _vatRateDeduction2 = 3; - private static readonly int _vatRateDeduction3 = 4; - private static readonly int _vatRateZero = 0; - - public static PaymentAdjustmentType? GetPaymentAdjustmentType(this ChargeItem chargeItem) - { - return (chargeItem.ftChargeItemCase & 0xFFFF) switch - { - long i when i >= 0x0023 && i <= 0x0027 => PaymentAdjustmentType.Adjustment, - long i when i >= 0x0028 && i <= 0x002C => PaymentAdjustmentType.SingleUseVoucher, - _ => null, - }; - } - - public static bool IsPaymentAdjustment(this ChargeItem chargeItem) - { - return (chargeItem.ftChargeItemCase & 0xFFFF) switch - { - long i when i >= 0x0023 && i <= 0x0027 => true, - long i when i >= 0x0028 && i <= 0x002D && chargeItem.GetAmount() < 0 => true, - _ => false, - }; - } - - public static bool IsMultiUseVoucherRedeem(this ChargeItem chargeItem) - { - return (chargeItem.ftChargeItemCase & 0xFFFF) switch - { - 0x002D => true && chargeItem.GetAmount() < 0, - _ => false, - }; - } - - public static bool IsMultiUseVoucherSale(this ChargeItem chargeItem) - { - return (chargeItem.ftChargeItemCase & 0xFFFF) switch - { - 0x002D => true && chargeItem.GetAmount() > 0, - _ => false, - }; - } - - public static int GetVatGroup(this ChargeItem chargeItem) - { - // TODO: check VAT rate table on printer at the moment according to xml example - switch (chargeItem.ftChargeItemCase & 0xFFFF) - { - //0 - case 0x0005: - case 0x000C: - case 0x0011: - case 0x0016: - case 0x001B: - case 0x0020: - case 0x0027: - case 0x002C: - case 0x002D: - return _vatRateZero; - //22 - case 0x0001: - case 0x0008: - case 0x000D: - case 0x0012: - case 0x0017: - case 0x001C: - case 0x0023: - case 0x0028: - return _vatRateBasic; - //10 - case 0x0002: - case 0x0009: - case 0x000E: - case 0x0013: - case 0x0018: - case 0x001D: - case 0x0024: - case 0x0029: - return _vatRateDeduction1; - //5 - case 0x0003: - case 0x000A: - case 0x000F: - case 0x0014: - case 0x0019: - case 0x001E: - case 0x0025: - case 0x002A: - return _vatRateDeduction2; - //4 - case 0x0004: - case 0x000B: - case 0x0010: - case 0x0015: - case 0x001A: - case 0x001F: - case 0x0026: - case 0x002B: - return _vatRateDeduction3; - default: - throw new UnknownChargeItemException(chargeItem.ftChargeItemCase); - } - } - public static decimal GetAmount(this ChargeItem chargeItem) => chargeItem.Quantity < 0 && chargeItem.Amount >= 0 ? chargeItem.Amount*(-1) : chargeItem.Amount; - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/PayItemExtensions.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/PayItemExtensions.cs deleted file mode 100644 index 65f6bd2f9..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/PayItemExtensions.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Contracts.Exceptions; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Extensions -{ - public static class PayItemExtensions - { - public static PaymentType GetPaymentType(this PayItem payItem) - { - switch (payItem.ftPayItemCase & 0xFFFF) - { - case 0x0000: - case 0x0001: - return PaymentType.Cash; - case 0x0003: - return PaymentType.Cheque; - case 0x0004: - case 0x0005: - case 0x0009: - case 0x000A: - return PaymentType.CreditCard; - case 0x0006: - return PaymentType.Voucher; - case 0x0002: //TODO foreign currencies - case 0x0007: //TODO Online payment - case 0x0008: //TODO Customer card payment - case 0x000C: //TODO SEPA transfer - case 0x000D: //TODO Other transfer - case 0x000E: //TODO Cash book expense - case 0x000F: //TODO Cash book contribution - case 0x0010: //TODO Levy - case 0x0011: //TODO Internal/ material consumption Can be used for bill - case 0x0012: //TODO 0x4954000000000012 Change tip cash - throw new NotImplementedException(); - case 0x000B: - return PaymentType.NotPaid; - default: - throw new UnknownPayItemException(payItem.ftPayItemCase); - } - } - - public static bool IsVoucherRedeem(this PayItem payItem) - { - return payItem.GetPaymentType() == PaymentType.Voucher && payItem.GetAmount() > 0; - } - - public static bool IsVoucherSale(this PayItem payItem) - { - return payItem.GetPaymentType() == PaymentType.Voucher && payItem.GetAmount() < 0; - } - - public static decimal GetAmount(this PayItem payItem) => payItem.Quantity < 0 && payItem.Amount >= 0 ? payItem.Amount * (-1) : payItem.Amount; - - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ReceiptRequestExtensions.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ReceiptRequestExtensions.cs index 6c5f693a0..d825fd0b6 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ReceiptRequestExtensions.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ReceiptRequestExtensions.cs @@ -1,123 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Net.Http.Headers; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Localization.QueueIT.Exceptions; +using fiskaltrust.ifPOS.v1; namespace fiskaltrust.Middleware.Localization.QueueIT.Extensions { public static class ReceiptRequestExtensions { - public static bool IsMultiUseVoucherSale(this ReceiptRequest receiptRequest) - { - var hasChargeItemVoucher = receiptRequest?.cbChargeItems?.Any(x => x.IsMultiUseVoucherSale()) ?? false; - var hasPayItemVoucher = receiptRequest?.cbPayItems?.Any(x => x.IsVoucherSale()) ?? false; + public static bool IsVoid(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_000F_0000) == 0x0000_0000_0004_0000; - if(hasChargeItemVoucher || hasPayItemVoucher) - { - if(receiptRequest?.cbChargeItems?.Any(x => !x.IsPaymentAdjustment() && !x.IsMultiUseVoucherSale()) ?? false) - { - throw new MultiUseVoucherNoSaleException(); - } - return true; - } - return false; - } + public static bool IsRefund(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0F00_0000) == 0x0000_0000_0100_0000; - public static List GetPaymentAdjustments(this ReceiptRequest receiptRequest) - { - var paymentAdjustments = new List(); + public static bool IsInitialOperation(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0000_FFFF) == 0x4001; - if (receiptRequest.cbChargeItems != null) - { - foreach (var item in receiptRequest.cbChargeItems) - { - if (item.IsPaymentAdjustment() && !item.IsMultiUseVoucherRedeem()) - { - paymentAdjustments.Add(new PaymentAdjustment - { - Amount = item.GetAmount(), - Description = item.Description, - VatGroup = item.GetVatGroup(), - PaymentAdjustmentType = (PaymentAdjustmentType) item.GetPaymentAdjustmentType(), - AdditionalInformation = item.ftChargeItemCaseData - }); - } - } - } - return paymentAdjustments; - } + public static bool IsReceiptOperation(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0000_F000) == 0x0000; - public static List GetPayments(this ReceiptRequest receiptRequest) - { - var sumChargeItems = receiptRequest.cbChargeItems?.Sum(x => x.GetAmount()) ?? 0; - var sumPayItems = receiptRequest.cbPayItems?.Sum(x => x.GetAmount()) ?? 0; + public static bool IsInvoiceOperation(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0000_F000) == 0x1000; - if ((sumPayItems - sumChargeItems) != 0) - { - throw new ItemPaymentInequalityException(sumPayItems, sumChargeItems); - } - var payment = receiptRequest.GetPaymentFullyRedeemedByVouchers(); + public static bool IsDailyOperation(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0000_F000) == 0x2000; - if (payment.Any()) - { - return payment; - } - var payments = receiptRequest.cbPayItems?.Select(p => new Payment - { - Amount = p.Amount, - Description = p.Description, - PaymentType = p.GetPaymentType(), - AdditionalInformation = p.ftPayItemCaseData - }).ToList() ?? new List(); - var vouchersFromChargeItms = receiptRequest.cbChargeItems.Where(x => x.IsMultiUseVoucherRedeem()).Select(ch => - new Payment - { - Amount = Math.Abs(ch.Amount), - Description = ch.Description, - PaymentType = PaymentType.Voucher, - AdditionalInformation = ch.ftChargeItemCaseData - }).ToList(); - payments.AddRange(vouchersFromChargeItms); - return payments; - } + public static bool IsProtocolOperation(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0000_F000) == 0x3000; - private static List GetPaymentFullyRedeemedByVouchers(this ReceiptRequest receiptRequest) - { - var sumChargeItemsNoVoucher = receiptRequest.cbChargeItems?.Where(x => !x.IsPaymentAdjustment()).Sum(x => x.GetAmount()) ?? 0; - - var payments = new List(); - if ((receiptRequest.cbPayItems != null && receiptRequest.cbPayItems.Any(x => x.IsVoucherRedeem())) || - (receiptRequest.cbChargeItems != null && receiptRequest.cbChargeItems.Any(x => x.IsMultiUseVoucherRedeem()))) - { - var sumVoucher = receiptRequest.cbPayItems.Where(x => x.IsVoucherRedeem()).Sum(x => x.GetAmount()) + - receiptRequest.cbChargeItems.Where(x => x.IsMultiUseVoucherRedeem()).Sum(x => Math.Abs(x.Amount)); - if (sumVoucher > sumChargeItemsNoVoucher) - { - var dscrPay = receiptRequest.cbPayItems.Where(x => x.IsVoucherRedeem()).Select(x => x.Description).ToList(); - var dscrCharge = receiptRequest.cbChargeItems.Where(x => x.IsMultiUseVoucherRedeem()).Select(x => x.Description).ToList(); - dscrPay.AddRange(dscrCharge); - - var addiPay = receiptRequest.cbPayItems.Where(x => x.IsVoucherRedeem()).Select(x => x.ftPayItemCaseData).ToList(); - var addiCharge = receiptRequest.cbChargeItems.Where(x => x.IsMultiUseVoucherRedeem()).Select(x => x.ftChargeItemCaseData).ToList(); - addiPay.AddRange(addiCharge); - - payments.Add( - new Payment - { - Amount = sumChargeItemsNoVoucher, - Description = string.Join(" ", dscrPay), - PaymentType = PaymentType.Voucher, - AdditionalInformation = string.Join(" ", addiPay), - }); - }; - } - return payments; - } - + public static bool IsLifeCycleOperation(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0000_F000) == 0x4000; } } - diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ServiceCollectionExtensions.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ServiceCollectionExtensions.cs deleted file mode 100644 index 879e2df78..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using fiskaltrust.Middleware.Localization.QueueIT.RequestCommands; -using Microsoft.Extensions.DependencyInjection; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Extensions -{ - public static class ServiceCollectionExtensions - { - public static IServiceCollection ConfigureReceiptCommands(this IServiceCollection services) - { - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - return services; - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ftJournalITExtensions.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ftJournalITExtensions.cs deleted file mode 100644 index 38e3b2fc7..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Extensions/ftJournalITExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using fiskaltrust.storage.V0; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Extensions -{ - public struct ScuResponse - { - public long ftReceiptCase { get; set; } - public DateTime ReceiptDateTime { get; set; } - public long ReceiptNumber { get; set; } - public long ZRepNumber { get; set; } - public string DataJson { get; set; } - } - public static class ftJournalITExtensions - { - public static ftJournalIT FromResponse(this ftJournalIT ftJournalIT, ICountrySpecificQueue queueIt, ftQueueItem queueItem, ScuResponse scuResponse) - { - ftJournalIT.ftJournalITId = Guid.NewGuid(); - ftJournalIT.ftQueueId = queueIt.ftQueueId; - ftJournalIT.ftQueueItemId = queueItem.ftQueueItemId; - ftJournalIT.cbReceiptReference = queueItem.cbReceiptReference; - ftJournalIT.ftSignaturCreationUnitITId = queueIt.ftSignaturCreationUnitId.Value; - ftJournalIT.JournalType = scuResponse.ftReceiptCase & 0xFFFF; - ftJournalIT.ReceiptDateTime = scuResponse.ReceiptDateTime; - ftJournalIT.ReceiptNumber = scuResponse.ReceiptNumber; - ftJournalIT.ZRepNumber = scuResponse.ZRepNumber; - ftJournalIT.DataJson = scuResponse.DataJson; - ftJournalIT.TimeStamp = DateTime.UtcNow.Ticks; - return ftJournalIT; - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/SignaturItemFactory.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/SignaturItemFactory.cs new file mode 100644 index 000000000..a6b35c9c3 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/SignaturItemFactory.cs @@ -0,0 +1,147 @@ +using System.Collections.Generic; +using System.Text; +using System; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.storage.V0; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; +namespace fiskaltrust.Middleware.Localization.QueueIT.Factories +{ + public static class SignaturItemFactory + { + public static SignaturItem CreateInitialOperationSignature(ftQueueIT queueIT, RTInfo rtInfo) + { + return new SignaturItem() + { + ftSignatureType = Cases.BASE_STATE | 0x1_1001, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + Caption = $"Initial-operation receipt", + Data = $"Queue-ID: {queueIT.ftQueueITId} Serial-Nr: {rtInfo.SerialNumber}" + }; + } + + public static SignaturItem CreateOutOfOperationSignature(ftQueueIT queueIT) + { + return new SignaturItem() + { + ftSignatureType = Cases.BASE_STATE | 0x1_1002, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + Caption = $"Out-of-operation receipt", + Data = $"Queue-ID: {queueIT.ftQueueITId}" + }; + } + + public static List CreatePOSReceiptFormatSignatures(ReceiptResponse response) + { + return new List + { + new SignaturItem + { + Caption = "[www.fiskaltrust.it]", + Data = CreateFooter(response).ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.PosReceiptPrimarySignature + }, + new SignaturItem + { + Caption = "DOCUMENTO COMMERCIALE", + Data = CreateHeader(response).ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.PosReceiptSecondarySignature + } + }; + } + + private static StringBuilder CreateFooter(ReceiptResponse receiptResponse) + { + var receiptNumber = long.Parse(receiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber)?.Data); + var zRepNumber = long.Parse(receiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber)?.Data); + var rtDocumentMoment = DateTime.Parse(receiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentMoment)?.Data); + var codiceLotteria = receiptResponse.GetSignaturItem(SignatureTypesIT.RTLotteryID)?.Data; + var customerIdentification = receiptResponse.GetSignaturItem(SignatureTypesIT.RTCustomerID)?.Data; + var shaMetadata = receiptResponse.GetSignaturItem(SignatureTypesIT.RTServerShaMetadata)?.Data; + var rtServerSerialNumber = receiptResponse.GetSignaturItem(SignatureTypesIT.RTSerialNumber)?.Data; + + var stringBuilder = new StringBuilder(); + stringBuilder.AppendLine($"{rtDocumentMoment.ToString("dd-MM-yyyy HH:mm")}"); + stringBuilder.AppendLine($"DOCUMENTO N. {zRepNumber.ToString().PadLeft(4, '0')}-{receiptNumber.ToString().PadLeft(4, '0')}"); + if (!string.IsNullOrEmpty(codiceLotteria)) + { + stringBuilder.AppendLine($"Codice Lotteria: {codiceLotteria}"); + stringBuilder.AppendLine(); + } + if (!string.IsNullOrEmpty(customerIdentification)) + { + stringBuilder.AppendLine($"Codice Fiscale: {customerIdentification}"); + } + if (!string.IsNullOrEmpty(shaMetadata)) + { + stringBuilder.AppendLine($"Server RT {rtServerSerialNumber}"); + } + stringBuilder.AppendLine($"Cassa {receiptResponse.ftCashBoxIdentification}"); + if (!string.IsNullOrEmpty(shaMetadata)) + { + stringBuilder.AppendLine($"-----FIRMA ELETTRONICA-----"); + stringBuilder.AppendLine(shaMetadata); + stringBuilder.AppendLine("---------------------------"); + } + return stringBuilder; + } + + private static StringBuilder CreateHeader(ReceiptResponse receiptResponse, string referencedRT = null, string referencedPrinterRT = null) + { + var docType = receiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentType)?.Data; + if (docType.ToUpper() == "POSRECEIPT") + { + return new StringBuilder("di vendita o prestazione"); + } + + var referenceZNumberString = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceZNumber)?.Data; + var referenceDocNumberString = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentNumber)?.Data; + var referenceDateTimeString = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentMoment)?.Data; + var stringBuilder = new StringBuilder(); + if (docType.ToUpper() == "REFUND") + { + stringBuilder.AppendLine("emesso per RESO MERCE"); + if (string.IsNullOrEmpty(referenceZNumberString) || string.IsNullOrEmpty(referenceDocNumberString)) + { + stringBuilder.AppendLine($"ND del {DateTime.Parse(referenceDateTimeString).ToString("dd-MM-yyyy")}"); + } + else + { + stringBuilder.AppendLine($"N. {long.Parse(referenceZNumberString).ToString().PadLeft(4, '0')}-{long.Parse(referenceDocNumberString).ToString().PadLeft(4, '0')} del {DateTime.Parse(referenceDateTimeString).ToString("dd-MM-yyyy")}"); + } + if (!string.IsNullOrEmpty(referencedRT)) + { + stringBuilder.AppendLine($"Server RT {referencedRT}"); + } + if (!string.IsNullOrEmpty(referencedPrinterRT)) + { + stringBuilder.AppendLine($"RT {referencedRT}"); + } + } + else if (docType.ToUpper() == "VOID") + { + stringBuilder.AppendLine("emesso per ANNULLAMENTO"); + if (string.IsNullOrEmpty(referenceZNumberString) || string.IsNullOrEmpty(referenceDocNumberString)) + { + stringBuilder.AppendLine($"ND del {DateTime.Parse(referenceDateTimeString).ToString("dd-MM-yyyy")}"); + } + else + { + stringBuilder.AppendLine($"N. {long.Parse(referenceZNumberString).ToString().PadLeft(4, '0')}-{long.Parse(referenceDocNumberString).ToString().PadLeft(4, '0')} del {DateTime.Parse(referenceDateTimeString).ToString("dd-MM-yyyy")}"); + } + if (!string.IsNullOrEmpty(referencedRT)) + { + stringBuilder.AppendLine($"Server RT {referencedRT}"); + } + if (!string.IsNullOrEmpty(referencedPrinterRT)) + { + stringBuilder.AppendLine($"RT {referencedRT}"); + } + } + return stringBuilder; + } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/SignatureItemFactoryIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/SignatureItemFactoryIT.cs deleted file mode 100644 index 53f725f5c..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/SignatureItemFactoryIT.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Contracts.Factories; - - -namespace fiskaltrust.Middleware.Localization.QueueIT.Factories -{ - public class SignatureItemFactoryIT : SignatureItemFactory - { - public override long CountryBaseState => 0x4954000000000000; - - public SignatureItemFactoryIT() { - } - - protected static NumberFormatInfo CurrencyFormatter = new () - { - NumberDecimalSeparator = ",", - NumberGroupSeparator = "", - CurrencyDecimalDigits = 2 - }; - - public SignaturItem[] CreatePosReceiptSignatures(DailyClosingResponse dailyClosingResponse) - { - return new SignaturItem[] - { - new SignaturItem - { - Caption = "", - Data = dailyClosingResponse.ZRepNumber.ToString(), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ZNumber - }, - new SignaturItem - { - Caption = "", - Data = dailyClosingResponse.DailyAmount.ToString(CurrencyFormatter), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ReceiptAmount - } - }; - } - - public SignaturItem[] CreateVoucherSignatures(NonFiscalRequest nonFiscalRequest) - { - - var signs = new List(); - var cnt = nonFiscalRequest.NonFiscalPrints.Count; - for (var i = 0; i < cnt; i ++ ) - { - var dat = nonFiscalRequest.NonFiscalPrints[i].Data; - if ( dat == "***Voucher***") - { - var dat2 = i + 1 < cnt ? nonFiscalRequest.NonFiscalPrints[i + 1].Data : null; - var isAmount = decimal.TryParse(dat2, NumberStyles.Number, new CultureInfo("it-It", false), out var amnt); - if (!isAmount) - { - dat2 = i + 2 < cnt ? nonFiscalRequest.NonFiscalPrints[i + 2].Data : null; - isAmount = decimal.TryParse(dat2, NumberStyles.Number, new CultureInfo("it-It", false), out amnt); - } - if (isAmount) - { - signs.Add(new SignaturItem - { - Caption = "", - Data = Math.Abs(amnt).ToString(new NumberFormatInfo - { - NumberDecimalSeparator = ",", - NumberGroupSeparator = "", - CurrencyDecimalDigits = 2 - }), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ReceiptAmount - }); - } - } - } - return signs.ToArray(); - } - - public SignaturItem [] CreatePosReceiptSignatures(FiscalReceiptResponse fiscalReceiptResponse) - { - return new SignaturItem[] - { - new SignaturItem - { - Caption = "", - Data = fiscalReceiptResponse.ReceiptNumber.ToString(), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ReceiptNumber - }, - new SignaturItem - { - Caption = "", - Data = fiscalReceiptResponse.ZRepNumber.ToString(), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ZNumber - }, - new SignaturItem - { - Caption = "", - Data = fiscalReceiptResponse.Amount.ToString(CurrencyFormatter), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ReceiptAmount - }, - new SignaturItem - { - Caption = "", - Data = fiscalReceiptResponse.ReceiptDateTime.ToString("yyyy-MM-dd HH:mm:ss"), - ftSignatureFormat = (long) SignaturItem.Formats.Text, - ftSignatureType = CountryBaseState & (long) SignatureTypesIT.ReceiptTimestamp - } - }; - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/ftActionJournalFactory.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/ftActionJournalFactory.cs new file mode 100644 index 000000000..7b1115752 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/ftActionJournalFactory.cs @@ -0,0 +1,88 @@ +using System; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.Contracts.Extensions; +using fiskaltrust.storage.serialization.DE.V0; +using fiskaltrust.storage.V0; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.Localization.QueueIT.Factories +{ + public static class ftActionJournalFactory + + { + public static ftActionJournal CreateDailyClosingActionJournal(ftQueue queue, ftQueueItem queueItem, ReceiptRequest request) + { + var ftReceiptCaseHex = request.ftReceiptCase.ToString("X"); + return CreateActionJournal(queue.ftQueueId, ftReceiptCaseHex, queueItem.ftQueueItemId, $"Daily-Closing receipt was processed.", JsonConvert.SerializeObject(new { ftReceiptNumerator = queue.ftReceiptNumerator + 1 })); + } + + public static ftActionJournal CreateMonthlyClosingActionJournal(ftQueue queue, ftQueueItem queueItem, ReceiptRequest request) + { + var ftReceiptCaseHex = request.ftReceiptCase.ToString("X"); + return CreateActionJournal(queue.ftQueueId, ftReceiptCaseHex, queueItem.ftQueueItemId, $"Monthly-Closing receipt was processed.", JsonConvert.SerializeObject(new { ftReceiptNumerator = queue.ftReceiptNumerator + 1 })); + } + + public static ftActionJournal CreateInitialOperationActionJournal(ftQueue queue, ftQueueItem queueItem, ftQueueIT queueIT, ReceiptRequest request) + { + var notification = new ActivateQueueSCU + { + CashBoxId = Guid.Parse(request.ftCashBoxID), + QueueId = queueItem.ftQueueId, + Moment = DateTime.UtcNow, + SCUId = queueIT.ftSignaturCreationUnitITId.GetValueOrDefault(), + IsStartReceipt = true, + Version = "V0", + }; + return CreateActionJournal(queue.ftQueueId, $"{request.ftReceiptCase:X}-{nameof(ActivateQueueSCU)}", queueItem.ftQueueItemId, $"Initial-Operation receipt. Queue-ID: {queue.ftQueueId}", JsonConvert.SerializeObject(notification)); + } + + public static ftActionJournal CreateWrongStateForInitialOperationActionJournal(ftQueue queue, ftQueueItem queueItem, ReceiptRequest request) + { + return CreateActionJournal(queue.ftQueueId, $"{request.ftReceiptCase:X}", + queueItem.ftQueueItemId, queue.IsDeactivated() + ? $"Queue {queue.ftQueueId} is de-activated, initial-operations-receipt can not be executed." + : $"Queue {queue.ftQueueId} is already activated, initial-operations-receipt can not be executed.", ""); + } + + public static ftActionJournal CreateOutOfOperationActionJournal(ftQueue queue, ftQueueItem queueItem, ftQueueIT queueIT, ReceiptRequest request) + { + var notification = new DeactivateQueueSCU + { + CashBoxId = Guid.Parse(request.ftCashBoxID), + QueueId = queueItem.ftQueueId, + Moment = DateTime.UtcNow, + SCUId = queueIT.ftSignaturCreationUnitITId.GetValueOrDefault(), + IsStopReceipt = true, + Version = "V0" + }; + return CreateActionJournal(queue.ftQueueId, $"{request.ftReceiptCase:X}-{nameof(DeactivateQueueSCU)}", queueItem.ftQueueItemId, $"Out-of-Operation receipt. Queue-ID: {queue.ftQueueId}", JsonConvert.SerializeObject(notification)); + } + + public static ftActionJournal CreateAlreadyOutOfOperationActionJournal(ftQueue queue, ftQueueItem queueItem, ReceiptRequest request) + { + return CreateActionJournal(queue.ftQueueId, $"{request.ftReceiptCase:X}-Queue-already-deactivated", + queueItem.ftQueueItemId, $"Out-of-Operation receipt. Queue-ID: {queue.ftQueueId}", $"Queue was already deactivated on the {queue.StopMoment.Value.ToString("yyyy-MM-dd hh:mm:ss")}"); + } + + public static ftActionJournal CreateYearlyClosingClosingActionJournal(ftQueue queue, ftQueueItem queueItem, ReceiptRequest request) + { + var ftReceiptCaseHex = request.ftReceiptCase.ToString("X"); + return CreateActionJournal(queue.ftQueueId, ftReceiptCaseHex, queueItem.ftQueueItemId, $"Yearly-Closing receipt was processed.", JsonConvert.SerializeObject(new { ftReceiptNumerator = queue.ftReceiptNumerator + 1 })); + } + + private static ftActionJournal CreateActionJournal(Guid queueId, string type, Guid queueItemId, string message, string data, int priority = -1) + { + return new ftActionJournal + { + ftActionJournalId = Guid.NewGuid(), + ftQueueId = queueId, + ftQueueItemId = queueItemId, + Type = type, + Moment = DateTime.UtcNow, + Message = message, + Priority = priority, + DataJson = data + }; + } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/ftJournalITFactory.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/ftJournalITFactory.cs new file mode 100644 index 000000000..2c3c61d9a --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Factories/ftJournalITFactory.cs @@ -0,0 +1,28 @@ +using System; +using fiskaltrust.Middleware.Localization.QueueIT.Models; +using fiskaltrust.storage.V0; + +namespace fiskaltrust.Middleware.Localization.QueueIT.Factories +{ + public static class ftJournalITFactory + { + public static ftJournalIT CreateFrom(ftQueueItem queueItem, ftQueueIT queueIT, ScuResponse scuResponse) + { + var ftJournalIT = new ftJournalIT + { + ftJournalITId = Guid.NewGuid(), + ftQueueId = queueIT.ftQueueId, + ftQueueItemId = queueItem.ftQueueItemId, + cbReceiptReference = queueItem.cbReceiptReference, + ftSignaturCreationUnitITId = queueIT.ftSignaturCreationUnitId.Value, + JournalType = scuResponse.ftReceiptCase & 0xFFFF, + ReceiptDateTime = scuResponse.ReceiptDateTime, + ReceiptNumber = scuResponse.ReceiptNumber, + ZRepNumber = scuResponse.ZRepNumber, + DataJson = scuResponse.DataJson, + TimeStamp = DateTime.UtcNow.Ticks + }; + return ftJournalIT; + } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Helpers/IsExternalInit.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Helpers/IsExternalInit.cs new file mode 100644 index 000000000..be6567575 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Helpers/IsExternalInit.cs @@ -0,0 +1,15 @@ +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// This dummy class is required to compile records when targeting .NET Standard + /// https://developercommunity.visualstudio.com/t/error-cs0518-predefined-type-systemruntimecompiler/1244809 + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static class IsExternalInit + { + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Helpers/ReceiptResponseHelper.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Helpers/ReceiptResponseHelper.cs new file mode 100644 index 000000000..d4f6bc7ca --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Helpers/ReceiptResponseHelper.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Linq; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; + +namespace fiskaltrust.Middleware.Localization.QueueIT.Helpers +{ + public static class ReceiptResponseHelper + { + public static void SetReceiptResponseError(this ReceiptResponse receiptResponse, string errorMessage) + { + receiptResponse.ftState |= 0xEEEE_EEEE; + receiptResponse.ftSignatures = new List().ToArray(); + receiptResponse.AddSignatureItem(new SignaturItem + { + Caption = "FAILURE", + Data = errorMessage, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + }); + } + + public static void InsertSignatureItems(this ReceiptResponse receiptResponse, List signaturItems) + { + var data = receiptResponse.ftSignatures.ToList(); + data.InsertRange(0, signaturItems); + receiptResponse.ftSignatures = data.ToArray(); + } + + public static void AddSignatureItem(this ReceiptResponse receiptResponse, SignaturItem signaturItem) + { + var data = receiptResponse.ftSignatures.ToList(); + data.Add(signaturItem); + receiptResponse.ftSignatures = data.ToArray(); + } + + public static bool HasFailed(this ReceiptResponse receiptRespons) => (receiptRespons.ftState & 0xFFFF_FFFF) == 0xEEEE_EEEE; + + public static SignaturItem GetSignaturItem(this ReceiptResponse receiptResponse, SignatureTypesIT signatureTypesIT) => receiptResponse.ftSignatures.FirstOrDefault(x => (x.ftSignatureType & 0xFF) == (long) signatureTypesIT); + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/IITSSCDProvider.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/IITSSCDProvider.cs new file mode 100644 index 000000000..39b287494 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/IITSSCDProvider.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; + +namespace fiskaltrust.Middleware.Localization.QueueIT +{ + public interface IITSSCDProvider + { + Task ProcessReceiptAsync(ProcessRequest request); + + Task GetRTInfoAsync(); + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/IReceiptTypeProcessor.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/IReceiptTypeProcessor.cs new file mode 100644 index 000000000..d8c2c31d5 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/IReceiptTypeProcessor.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.Localization.QueueIT.v2; +using fiskaltrust.storage.V0; + +namespace fiskaltrust.Middleware.Localization.QueueIT +{ + public interface IReceiptTypeProcessor + { + public ReceiptCases ReceiptCase { get; } + + Task<(ReceiptResponse receiptResponse, List actionJournals)> ExecuteAsync(ftQueue queue, ftQueueIT queueIt, ReceiptRequest request, ReceiptResponse receiptResponse, ftQueueItem queueItem); + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/ITSSCDProvider.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/ITSSCDProvider.cs new file mode 100644 index 000000000..c9aa9388b --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/ITSSCDProvider.cs @@ -0,0 +1,128 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.Middleware.Contracts.Models; +using fiskaltrust.storage.V0; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.Localization.QueueIT +{ + public class ITSSCDProvider : IITSSCDProvider + { + private readonly ILogger _logger; + private readonly IClientFactory _clientFactory; + private readonly IConfigurationRepository _configurationRepository; + private readonly MiddlewareConfiguration _middlewareConfiguration; + private readonly QueueITConfiguration _queueConfiguration; + + private readonly SemaphoreSlim _semaphoreInstance = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim _semaphoreRegister = new SemaphoreSlim(1, 1); + + private IITSSCD _instance; + + public IITSSCD Instance + { + get + { + try + { + _semaphoreInstance.Wait(); + if (_instance == null) + { + RegisterCurrentScuAsync().Wait(); + } + return _instance; + } + finally + { + _semaphoreInstance.Release(); + } + } + } + + public ITSSCDProvider(ILogger logger, IClientFactory clientFactory, IConfigurationRepository configurationRepository, MiddlewareConfiguration middlewareConfiguration, QueueITConfiguration queueConfiguration) + { + _logger = logger; + _clientFactory = clientFactory; + _configurationRepository = configurationRepository; + _middlewareConfiguration = middlewareConfiguration; + _queueConfiguration = queueConfiguration; + } + + public async Task RegisterCurrentScuAsync() + { + try + { + await _semaphoreRegister.WaitAsync().ConfigureAwait(false); + var queueIT = await _configurationRepository.GetQueueITAsync(_middlewareConfiguration.QueueId).ConfigureAwait(false); + + if (!queueIT.ftSignaturCreationUnitITId.HasValue) + { + _instance = null; + return; + } + + var signaturCreationUnitIT = await _configurationRepository.GetSignaturCreationUnitITAsync(queueIT.ftSignaturCreationUnitITId.Value).ConfigureAwait(false); + var uri = GetUriForSignaturCreationUnit(signaturCreationUnitIT); + var config = new ClientConfiguration + { + Url = uri.ToString(), + UrlType = uri.Scheme + }; + + if (_queueConfiguration.ScuTimeoutMs.HasValue) + { + config.Timeout = TimeSpan.FromMilliseconds(_queueConfiguration.ScuTimeoutMs.Value); + } + if (_queueConfiguration.ScuMaxRetries.HasValue) + { + config.RetryCount = _queueConfiguration.ScuMaxRetries.Value; + } + + _instance = _clientFactory.CreateClient(config); + try + { + var tseInfo = await _instance.GetRTInfoAsync().ConfigureAwait(false); + signaturCreationUnitIT.InfoJson = JsonConvert.SerializeObject(tseInfo); + await _configurationRepository.InsertOrUpdateSignaturCreationUnitITAsync(signaturCreationUnitIT).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to updated status of SCU (Url: {ScuUrl}, Id: {ScuId}). Will try again later...", config.Url, queueIT.ftSignaturCreationUnitITId.Value); + } + } + finally + { + _semaphoreRegister.Release(); + } + } + + public async Task ProcessReceiptAsync(ProcessRequest request) + { + return await Instance.ProcessReceiptAsync(request); + } + + + public async Task GetRTInfoAsync() + { + return await Instance.GetRTInfoAsync(); + } + + private static Uri GetUriForSignaturCreationUnit(ftSignaturCreationUnitIT signaturCreationUnit) + { + var url = signaturCreationUnit.Url; + try + { + var urls = JsonConvert.DeserializeObject(url); + var grpcUrl = urls.FirstOrDefault(x => x.StartsWith("grpc://")); + url = grpcUrl ?? urls.First(); + } + catch { } + return new Uri(url); + } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/JournalProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/JournalProcessorIT.cs index 8ceb0ee1f..073a6d908 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/JournalProcessorIT.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/JournalProcessorIT.cs @@ -8,14 +8,6 @@ namespace fiskaltrust.Middleware.Localization.QueueIT { public class JournalProcessorIT : IMarketSpecificJournalProcessor { - private readonly ILogger _logger; - - public JournalProcessorIT( - ILogger logger) - { - _logger = logger; - } - public IAsyncEnumerable ProcessAsync(JournalRequest request) { throw new NotImplementedException(); diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Models/ScuResponse.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Models/ScuResponse.cs new file mode 100644 index 000000000..c59d4cefc --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Models/ScuResponse.cs @@ -0,0 +1,13 @@ +using System; + +namespace fiskaltrust.Middleware.Localization.QueueIT.Models +{ + public struct ScuResponse + { + public long ftReceiptCase { get; set; } + public DateTime ReceiptDateTime { get; set; } + public long ReceiptNumber { get; set; } + public long ZRepNumber { get; set; } + public string DataJson { get; set; } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITBootstrapper.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITBootstrapper.cs index a93ed4bbb..b858bcae7 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITBootstrapper.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITBootstrapper.cs @@ -1,16 +1,7 @@ -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Abstractions; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Interfaces; +using fiskaltrust.Middleware.Contracts.Interfaces; using fiskaltrust.Middleware.Contracts.Models; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.RequestCommands.Factories; -using fiskaltrust.Middleware.Localization.QueueIT.Constants; -using fiskaltrust.Middleware.Localization.QueueIT.Extensions; -using fiskaltrust.Middleware.Localization.QueueIT.Factories; -using fiskaltrust.Middleware.Localization.QueueIT.Repositories; -using fiskaltrust.Middleware.Localization.QueueIT.RequestCommands.Factories; -using fiskaltrust.Middleware.Localization.QueueIT.Services; +using fiskaltrust.Middleware.Localization.QueueIT.v2; +using fiskaltrust.storage.V0; using Microsoft.Extensions.DependencyInjection; namespace fiskaltrust.Middleware.Localization.QueueIT @@ -20,23 +11,16 @@ public class QueueITBootstrapper : ILocalizedQueueBootstrapper public void ConfigureServices(IServiceCollection services) { var _ = services - .AddScoped() - .AddScoped() + .AddScoped() + .AddScoped(x => new SignProcessor(x.GetRequiredService(), x.GetRequiredService())) .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() .AddSingleton(sp => QueueITConfiguration.FromMiddlewareConfiguration(sp.GetRequiredService())) - .AddSingleton(sp => - { - var sscdProvider = new ITSSCDProvider( - sp.GetRequiredService>(), - sp.GetRequiredService()); - sscdProvider.RegisterCurrentScuAsync().Wait(); - return sscdProvider; - }) - .AddSingleton() - .ConfigureReceiptCommands(); + .AddSingleton(); } } } diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITConfiguration.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITConfiguration.cs index ad0c8fa31..2797ecc29 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITConfiguration.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/QueueITConfiguration.cs @@ -6,6 +6,16 @@ namespace fiskaltrust.Middleware.Localization.QueueIT public class QueueITConfiguration { public bool Sandbox { get; set; } = false; + + + [JsonProperty("scu-timeout-ms")] + public long? ScuTimeoutMs { get; set; } + + [JsonProperty("scu-max-retries")] + public int? ScuMaxRetries { get; set; } = 1; + // SKE => currently we don't perform any retries, we'll have to think about how we can handle this differently in the future, probably letting one of either component decide + // also this thing has to be 1 since we are considering the first try also as retry. + public static QueueITConfiguration FromMiddlewareConfiguration(MiddlewareConfiguration middlewareConfiguration) => JsonConvert.DeserializeObject(JsonConvert.SerializeObject(middlewareConfiguration.Configuration)); } } \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Repositories/CountrySpecificQueueRepository.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Repositories/CountrySpecificQueueRepository.cs deleted file mode 100644 index 441b9ad67..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Repositories/CountrySpecificQueueRepository.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.storage.V0; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Repositories -{ - public class CountrySpecificQueueRepository : ICountrySpecificQueueRepository - { - private readonly IConfigurationRepository _configurationRepository; - - public CountrySpecificQueueRepository(IConfigurationRepository configurationRepository) - { - _configurationRepository = configurationRepository; - } - - public async Task GetQueueAsync(Guid queueId) => await _configurationRepository.GetQueueITAsync(queueId).ConfigureAwait(false); - public async Task InsertOrUpdateQueueAsync(ICountrySpecificQueue queue) => await _configurationRepository.InsertOrUpdateQueueITAsync((ftQueueIT) queue).ConfigureAwait(false); - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/DailyClosingReceiptCommand.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/DailyClosingReceiptCommand.cs deleted file mode 100644 index 20f041fa8..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/DailyClosingReceiptCommand.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.ifPOS.v1.errors; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Interfaces; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.RequestCommands; -using fiskaltrust.Middleware.Localization.QueueIT.Extensions; -using fiskaltrust.Middleware.Localization.QueueIT.Factories; -using fiskaltrust.Middleware.Localization.QueueIT.Services; -using fiskaltrust.storage.V0; -using Microsoft.Extensions.Logging; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public class DailyClosingReceiptCommand : Contracts.RequestCommands.DailyClosingReceiptCommand - { - private readonly long _countryBaseState; - protected override long CountryBaseState => _countryBaseState; - private readonly ICountrySpecificSettings _countryspecificSettings; - private readonly ICountrySpecificQueueRepository _countrySpecificQueueRepository; - private readonly SignatureItemFactoryIT _signatureItemFactoryIT; - private readonly IMiddlewareJournalITRepository _journalITRepository; - private readonly IITSSCD _client; - private readonly ISSCD _signingDevice; - private readonly ILogger _logger; - - public DailyClosingReceiptCommand(ISSCD signingDevice, ILogger logger, SignatureItemFactoryIT signatureItemFactoryIT, ICountrySpecificSettings countrySpecificSettings, IITSSCDProvider itIsscdProvider, IMiddlewareJournalITRepository journalITRepository) - { - _countrySpecificQueueRepository = countrySpecificSettings.CountrySpecificQueueRepository; - _client = itIsscdProvider.Instance; - _journalITRepository = journalITRepository; - _signatureItemFactoryIT = signatureItemFactoryIT; - _countryspecificSettings = countrySpecificSettings; - _countryBaseState = countrySpecificSettings.CountryBaseState; - _signingDevice = signingDevice; - _logger = logger; - } - - protected override async Task GetCashboxIdentificationAsync(Guid ftQueueId) - { - var queueIt = await _countrySpecificQueueRepository.GetQueueAsync(ftQueueId).ConfigureAwait(false); - return queueIt.CashBoxIdentification; - } - - public override Task ReceiptNeedsReprocessing(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) => Task.FromResult(false); - - protected override async Task SpecializeAsync(RequestCommandResponse requestCommandResponse, ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) - { - var response = await _client.ExecuteDailyClosingAsync(new DailyClosingRequest() ).ConfigureAwait(false); - - if (!response.Success) - { - if (response.SSCDErrorInfo.Type == SSCDErrorType.Connection) - { - return await ProcessFailedReceiptRequest(_signingDevice, _logger, _countryspecificSettings, queue, queueItem, request).ConfigureAwait(false); - } - else - { - throw new SSCDErrorException(response.SSCDErrorInfo.Type, response.SSCDErrorInfo.Info); - } - } - else - { - requestCommandResponse.ReceiptResponse.ftReceiptIdentification += $"Z{response.ZRepNumber}"; - requestCommandResponse.ReceiptResponse.ftSignatures = _signatureItemFactoryIT.CreatePosReceiptSignatures(response); - var queueIt = await _countrySpecificQueueRepository.GetQueueAsync(queue.ftQueueId).ConfigureAwait(false); - var journalIT = new ftJournalIT().FromResponse(queueIt, queueItem, new ScuResponse() - { - DataJson = response.ReportDataJson, - ftReceiptCase = request.ftReceiptCase, - ZRepNumber = response.ZRepNumber - }); - await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); - return requestCommandResponse; - } - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/Factories/RequestCommandFactory.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/Factories/RequestCommandFactory.cs deleted file mode 100644 index 1d7b82c6b..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/Factories/RequestCommandFactory.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.Middleware.Contracts.Exceptions; -using fiskaltrust.Middleware.Contracts.RequestCommands; -using fiskaltrust.Middleware.Contracts.RequestCommands.Factories; -using Microsoft.Extensions.DependencyInjection; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands.Factories -{ - public class RequestCommandFactory : IRequestCommandFactory - { - private readonly IServiceProvider _serviceProvider; - - public RequestCommandFactory(IServiceProvider serviceCollection) => _serviceProvider = serviceCollection; - - public RequestCommand Create(ReceiptRequest request) - { - RequestCommand command = (request.ftReceiptCase & 0xFFFF) switch - { - 0x0000 => _serviceProvider.GetService(), - 0x0001 => _serviceProvider.GetService(), - 0x0003 => _serviceProvider.GetService(), - 0x0004 => _serviceProvider.GetService(), - 0x0007 => _serviceProvider.GetService(), - 0x0005 => _serviceProvider.GetService(), - 0x0006 => _serviceProvider.GetService(), - 0x0002 => _serviceProvider.GetService(), - _ => throw new UnknownReceiptCaseException(request.ftReceiptCase) - }; - - return command; - } - } -} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/InitialOperationReceiptCommand.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/InitialOperationReceiptCommand.cs deleted file mode 100644 index 00077bf0a..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/InitialOperationReceiptCommand.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.storage.V0; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.storage.serialization.DE.V0; -using fiskaltrust.Middleware.Localization.QueueIT.Factories; -using fiskaltrust.Middleware.Localization.QueueIT.Services; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.Constants; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public class InitialOperationReceiptCommand : Contracts.RequestCommands.InitialOperationReceiptCommand - { - private readonly ICountrySpecificQueueRepository _countrySpecificQueueRepository; - - private readonly IConfigurationRepository _configurationRepository; - private readonly SignatureItemFactoryIT _signatureItemFactoryIT; - private readonly IITSSCD _client; - - public InitialOperationReceiptCommand(ICountrySpecificSettings countrySpecificQueueSettings, IITSSCDProvider itIsscdProvider, ILogger logger, IConfigurationRepository configurationRepository, SignatureItemFactoryIT signatureItemFactoryIT) : base(countrySpecificQueueSettings, logger, configurationRepository) - { - _client = itIsscdProvider.Instance; - _configurationRepository = configurationRepository; - _signatureItemFactoryIT = signatureItemFactoryIT; - _countrySpecificQueueRepository = countrySpecificQueueSettings.CountrySpecificQueueRepository; - - } - - protected override async Task<(ftActionJournal, SignaturItem)> InitializeSCUAsync(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) - { - var queueIt = await _configurationRepository.GetQueueITAsync(queue.ftQueueId); - var scu = await _configurationRepository.GetSignaturCreationUnitITAsync(queueIt.ftSignaturCreationUnitITId.Value).ConfigureAwait(false); - var deviceInfo = await _client.GetDeviceInfoAsync().ConfigureAwait(false); - if (string.IsNullOrEmpty(scu.InfoJson )) - { - scu.InfoJson = JsonConvert.SerializeObject(deviceInfo); - await _configurationRepository.InsertOrUpdateSignaturCreationUnitITAsync(scu).ConfigureAwait(false); - } - var signatureItem = _signatureItemFactoryIT.CreateInitialOperationSignature($"Queue-ID: {queue.ftQueueId} Serial-Nr: {deviceInfo.SerialNumber}"); - var notification = new ActivateQueueSCU - { - CashBoxId = Guid.Parse(request.ftCashBoxID), - QueueId = queueItem.ftQueueId, - Moment = DateTime.UtcNow, - SCUId = queueIt.ftSignaturCreationUnitITId.GetValueOrDefault(), - IsStartReceipt = true, - Version = "V0", - }; - var actionJournal = CreateActionJournal(queue.ftQueueId, $"{request.ftReceiptCase:X}-{nameof(ActivateQueueSCU)}", - queueItem.ftQueueItemId, $"Initial-Operation receipt. Queue-ID: {queue.ftQueueId}", JsonConvert.SerializeObject(notification)); - - return (actionJournal, signatureItem); - } - - public override Task ReceiptNeedsReprocessing(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) => Task.FromResult(false); - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/MonthlyClosingReceiptCommand.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/MonthlyClosingReceiptCommand.cs deleted file mode 100644 index e991df28f..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/MonthlyClosingReceiptCommand.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading.Tasks; -using System; -using fiskaltrust.storage.V0; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.Constants; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public class MonthlyClosingReceiptCommand : Contracts.RequestCommands.MonthlyClosingReceiptCommand - { - private readonly ICountrySpecificQueueRepository _countrySpecificQueueRepository; - - private readonly long _countryBaseState; - protected override long CountryBaseState => _countryBaseState; - - public MonthlyClosingReceiptCommand(ICountrySpecificSettings countrySpecificSettings) - { - _countrySpecificQueueRepository = countrySpecificSettings.CountrySpecificQueueRepository; - _countryBaseState = countrySpecificSettings.CountryBaseState; - } - - protected override async Task GetCashboxIdentificationAsync(Guid ftQueueId) - { - var queueIt = await _countrySpecificQueueRepository.GetQueueAsync(ftQueueId).ConfigureAwait(false); - return queueIt.CashBoxIdentification; - } - - public override Task ReceiptNeedsReprocessing(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) => Task.FromResult(false); - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/OutOfOperationReceiptCommand.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/OutOfOperationReceiptCommand.cs deleted file mode 100644 index ae0df2fa4..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/OutOfOperationReceiptCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.storage.V0; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.storage.serialization.DE.V0; -using Newtonsoft.Json; -using fiskaltrust.Middleware.Localization.QueueIT.Factories; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.Constants; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public class OutOfOperationReceiptCommand : Contracts.RequestCommands.OutOfOperationReceiptCommand - { - protected override long CountryBaseState => _countryBaseState; - private readonly long _countryBaseState; - private readonly SignatureItemFactoryIT _signatureItemFactoryIT; - private readonly ftQueueIT _queueIt; - private readonly ICountrySpecificQueueRepository _countrySpecificQueueRepository; - - public OutOfOperationReceiptCommand(SignatureItemFactoryIT signatureItemFactoryIT, ftQueueIT queueIt, ICountrySpecificSettings countrySpecificSettings) - { - _signatureItemFactoryIT = signatureItemFactoryIT; - _queueIt = queueIt; - _countrySpecificQueueRepository = countrySpecificSettings.CountrySpecificQueueRepository; - _countryBaseState = countrySpecificSettings.CountryBaseState; - } - - public override Task ReceiptNeedsReprocessing(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) => Task.FromResult(false); - - protected override Task<(ftActionJournal, SignaturItem)> DeactivateSCUAsync(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) - { - var signatureItem = _signatureItemFactoryIT.CreateOutOfOperationSignature($"Queue-ID: {queue.ftQueueId}"); - var notification = new DeactivateQueueSCU - { - CashBoxId = Guid.Parse(request.ftCashBoxID), - QueueId = queueItem.ftQueueId, - Moment = DateTime.UtcNow, - SCUId = _queueIt.ftSignaturCreationUnitITId.GetValueOrDefault(), - IsStopReceipt = true, - Version = "V0" - }; - - var actionJournal = CreateActionJournal(queue.ftQueueId, $"{request.ftReceiptCase:X}-{nameof(DeactivateQueueSCU)}", - queueItem.ftQueueItemId, $"Out-of-Operation receipt. Queue-ID: {queue.ftQueueId}", JsonConvert.SerializeObject(notification)); - - return Task.FromResult((actionJournal, signatureItem)); - } - - protected override async Task GetCashboxIdentificationAsync(Guid ftQueueId) - { - var queueIt = await _countrySpecificQueueRepository.GetQueueAsync(ftQueueId).ConfigureAwait(false); - return queueIt.CashBoxIdentification; - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/PosReceiptCommand.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/PosReceiptCommand.cs deleted file mode 100644 index 3f364267e..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/PosReceiptCommand.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.storage.V0; -using fiskaltrust.Middleware.Contracts.RequestCommands; -using fiskaltrust.ifPOS.v1.it; -using System.Linq; -using fiskaltrust.Middleware.Localization.QueueIT.Extensions; -using fiskaltrust.Middleware.Localization.QueueIT.Factories; -using fiskaltrust.Middleware.Localization.QueueIT.Services; -using fiskaltrust.Middleware.Contracts.Extensions; -using fiskaltrust.Middleware.Localization.QueueIT.Exceptions; -using Newtonsoft.Json; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.ifPOS.v1.errors; -using fiskaltrust.Middleware.Contracts.Constants; -using System.Globalization; -using Microsoft.Extensions.Logging; -using fiskaltrust.Middleware.Contracts.Interfaces; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public struct RefundDetails - { - public string Serialnumber { get; set; } - public long ZRepNumber { get; set; } - public long ReceiptNumber { get; set; } - public DateTime ReceiptDateTime { get; set; } - } - - public class PosReceiptCommand : RequestCommand - { - private readonly long _countryBaseState; - private readonly ICountrySpecificQueueRepository _countrySpecificQueueRepository; - private readonly ICountrySpecificSettings _countryspecificSettings; - private readonly IConfigurationRepository _configurationRepository; - private readonly SignatureItemFactoryIT _signatureItemFactoryIT; - private readonly IMiddlewareJournalITRepository _journalITRepository; - private readonly IITSSCD _client; - private readonly ISSCD _signingDevice; - private readonly ILogger _logger; - - public PosReceiptCommand(ISSCD signingDevice, ILogger logger, IITSSCDProvider itIsscdProvider, SignatureItemFactoryIT signatureItemFactoryIT, IMiddlewareJournalITRepository journalITRepository, IConfigurationRepository configurationRepository, ICountrySpecificSettings countrySpecificSettings) - { - _client = itIsscdProvider.Instance; - _signatureItemFactoryIT = signatureItemFactoryIT; - _journalITRepository = journalITRepository; - _countryspecificSettings = countrySpecificSettings; - _countrySpecificQueueRepository = countrySpecificSettings.CountrySpecificQueueRepository; - _countryBaseState = countrySpecificSettings.CountryBaseState; - _configurationRepository = configurationRepository; - _signingDevice = signingDevice; - _logger = logger; - } - - public override async Task ExecuteAsync(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem, bool isBeingResent = false) - { - var journals = await _journalITRepository.GetAsync().ConfigureAwait(false); - if (journals.Where(x => x.cbReceiptReference.Equals(request.cbReceiptReference)).Any()) - { - throw new CbReferenceExistsException(request.cbReceiptReference); - } - - var queueIt = await _countrySpecificQueueRepository.GetQueueAsync(queue.ftQueueId).ConfigureAwait(false); - - var receiptResponse = CreateReceiptResponse(queue, request, queueItem, queueIt.CashBoxIdentification, _countryBaseState); - - if (request.IsMultiUseVoucherSale()) - { - return await CreateNonFiscalRequestAsync(queueIt, queueItem, receiptResponse, request).ConfigureAwait(false); - } - - FiscalReceiptResponse response; - if (request.IsVoid()) - { - var fiscalReceiptRefund = await CreateRefundAsync(request).ConfigureAwait(false); - response = await _client.FiscalReceiptRefundAsync(fiscalReceiptRefund).ConfigureAwait(false); - } - else - { - var fiscalReceiptinvoice = CreateInvoice(request); - response = await _client.FiscalReceiptInvoiceAsync(fiscalReceiptinvoice).ConfigureAwait(false); - } - if (!response.Success) - { - if (response.SSCDErrorInfo.Type == SSCDErrorType.Connection && !isBeingResent) - { - return await ProcessFailedReceiptRequest(_signingDevice, _logger, _countryspecificSettings, queue, queueItem, request).ConfigureAwait(false); - } - else - { - throw new SSCDErrorException(response.SSCDErrorInfo.Type, response.SSCDErrorInfo.Info); - } - } - else - { - receiptResponse.ftReceiptIdentification += $"{response.ReceiptNumber}"; - receiptResponse.ftSignatures = _signatureItemFactoryIT.CreatePosReceiptSignatures(response); - var journalIT = new ftJournalIT().FromResponse(queueIt, queueItem, new ScuResponse() - { - DataJson = response.ReceiptDataJson, - ftReceiptCase = request.ftReceiptCase, - ReceiptDateTime = response.ReceiptDateTime, - ReceiptNumber = response.ReceiptNumber, - ZRepNumber = response.ZRepNumber - }); - await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); - } - - return new RequestCommandResponse - { - ReceiptResponse = receiptResponse, - ActionJournals = new List() - }; - } - - private async Task CreateNonFiscalRequestAsync(ICountrySpecificQueue queue, ftQueueItem queueItem, ReceiptResponse receiptResponse, ReceiptRequest request) - { - var nonFiscalRequest = new NonFiscalRequest - { - NonFiscalPrints = new List() - }; - if (request.cbChargeItems != null) - { - foreach (var chargeItem in request.cbChargeItems.Where(x => x.IsMultiUseVoucherSale())) - { - AddVoucherNonFiscalPrints(nonFiscalRequest.NonFiscalPrints, chargeItem.Amount, chargeItem.ftChargeItemCaseData); - } - } - if (request.cbPayItems != null) - { - foreach (var payItem in request.cbPayItems.Where(x => x.IsVoucherSale())) - { - AddVoucherNonFiscalPrints(nonFiscalRequest.NonFiscalPrints, payItem.Amount, payItem.ftPayItemCaseData); - } - } - var response = await _client.NonFiscalReceiptAsync(nonFiscalRequest); - - if (response.Success) - { - receiptResponse.ftSignatures = _signatureItemFactoryIT.CreateVoucherSignatures(nonFiscalRequest); - } - var journalIT = new ftJournalIT - { - ftJournalITId = Guid.NewGuid(), - ftQueueId = queue.ftQueueId, - ftQueueItemId = queueItem.ftQueueItemId, - cbReceiptReference = queueItem.cbReceiptReference, - ftSignaturCreationUnitITId = queue.ftSignaturCreationUnitId.Value, - JournalType = request.ftReceiptCase & 0xFFFF, - ReceiptDateTime = queueItem.cbReceiptMoment, - ReceiptNumber = -1, - ZRepNumber = -1, - DataJson = JsonConvert.SerializeObject(nonFiscalRequest), - TimeStamp = DateTime.UtcNow.Ticks - }; - await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); - - return new RequestCommandResponse - { - ReceiptResponse = receiptResponse, - ActionJournals = new List() - }; - } - - private static void AddVoucherNonFiscalPrints(List nonFiscalPrints, decimal amount, string info) - { - nonFiscalPrints.Add(new NonFiscalPrint() { Data = "***Voucher***", Font = 2 }); - if (!string.IsNullOrEmpty(info)) - { - nonFiscalPrints.Add(new NonFiscalPrint() { Data = info, Font = 2 }); - } - nonFiscalPrints.Add(new NonFiscalPrint() - { - Data = Math.Abs(amount).ToString(new NumberFormatInfo - { - NumberDecimalSeparator = ",", - NumberGroupSeparator = "", - CurrencyDecimalDigits = 2 - }), - Font = 2 - }); - } - - private static FiscalReceiptInvoice CreateInvoice(ReceiptRequest request) - { - var fiscalReceiptRequest = new FiscalReceiptInvoice() - { - //Barcode = ChargeItem.ProductBarcode, - //TODO DisplayText = "Message on customer display", - Operator = request.cbUser, - Items = request.cbChargeItems.Where(x => !x.IsPaymentAdjustment()).Select(p => new Item - { - Description = p.Description, - Quantity = p.Quantity, - UnitPrice = p.UnitPrice ?? p.Amount / p.Quantity, - Amount = p.Amount, - VatGroup = p.GetVatGroup(), - AdditionalInformation = p.ftChargeItemCaseData - }).ToList(), - PaymentAdjustments = request.GetPaymentAdjustments(), - Payments = request.GetPayments() - }; - return fiscalReceiptRequest; - } - - private async Task CreateRefundAsync(ReceiptRequest request) - { - var refundDetails = await GetRefundDetailsAsync(request).ConfigureAwait(false); - var fiscalReceiptRequest = new FiscalReceiptRefund() - { - //TODO Barcode = "0123456789" - Operator = request.cbUser, - DisplayText = $"REFUND {refundDetails.ZRepNumber:D4} {refundDetails.ReceiptNumber:D4} {refundDetails.ReceiptDateTime:ddMMyyyy} {refundDetails.Serialnumber}", - Refunds = request.cbChargeItems?.Select(p => new Refund - { - Description = p.Description, - Quantity = Math.Abs(p.Quantity), - UnitPrice = p.UnitPrice ?? 0, - Amount = Math.Abs(p.Amount), - VatGroup = p.GetVatGroup() - }).ToList(), - PaymentAdjustments = request.GetPaymentAdjustments(), - Payments = request.cbPayItems?.Select(p => new Payment - { - Amount = p.Amount, - Description = p.Description, - PaymentType = p.GetPaymentType(), - }).ToList() - }; - - return fiscalReceiptRequest; - } - - private async Task GetRefundDetailsAsync(ReceiptRequest request) - { - var journalIt = await _journalITRepository.GetAsync().ConfigureAwait(false); - var receipt = journalIt.Where(x => x.cbReceiptReference.Equals(request.cbPreviousReceiptReference)).FirstOrDefault() ?? throw new RefundException($"Receipt {request.cbPreviousReceiptReference} was not found!"); - var scu = await _configurationRepository.GetSignaturCreationUnitITAsync(receipt.ftSignaturCreationUnitITId).ConfigureAwait(false); - var deviceInfo = JsonConvert.DeserializeObject(scu.InfoJson); - return new RefundDetails() - { - ReceiptNumber = receipt.ReceiptNumber, - ZRepNumber = receipt.ZRepNumber, - ReceiptDateTime = receipt.ReceiptDateTime, - Serialnumber = deviceInfo.SerialNumber - }; - } - - public override async Task ReceiptNeedsReprocessing(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) - { - var journalIt = await _journalITRepository.GetByQueueItemId(queueItem.ftQueueItemId).ConfigureAwait(false); - return journalIt == null; - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/YearlyClosingReceiptCommand.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/YearlyClosingReceiptCommand.cs deleted file mode 100644 index baa24ee42..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/YearlyClosingReceiptCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.storage.V0; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public class YearlyClosingReceiptCommand : Contracts.RequestCommands.YearlyClosingReceiptCommand - { - private readonly long _countryBaseState; - protected override long CountryBaseState => _countryBaseState; - private readonly ICountrySpecificQueueRepository _countrySpecificQueueRepository; - - public YearlyClosingReceiptCommand(ICountrySpecificSettings countryspecificSettings) - { - _countrySpecificQueueRepository = countryspecificSettings.CountrySpecificQueueRepository; - _countryBaseState = countryspecificSettings.CountryBaseState; - } - - protected override async Task GetCashboxIdentificationAsync(Guid ftQueueId) - { - var queueIt = await _countrySpecificQueueRepository.GetQueueAsync(ftQueueId).ConfigureAwait(false); - return queueIt.CashBoxIdentification; - } - - public override Task ReceiptNeedsReprocessing(ftQueue queue, ReceiptRequest request, ftQueueItem queueItem) => Task.FromResult(false); - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/ZeroReceiptCommandIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/ZeroReceiptCommandIT.cs deleted file mode 100644 index 2f841f854..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/RequestCommands/ZeroReceiptCommandIT.cs +++ /dev/null @@ -1,18 +0,0 @@ -using fiskaltrust.storage.V0; -using Microsoft.Extensions.Logging; -using fiskaltrust.Middleware.Contracts.RequestCommands; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.RequestCommands.Factories; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Interfaces; - -namespace fiskaltrust.Middleware.Localization.QueueIT.RequestCommands -{ - public class ZeroReceiptCommandIT : ZeroReceiptCommand - { - public ZeroReceiptCommandIT(ISSCD signingDevice, ICountrySpecificSettings countryspecificSettings, IMiddlewareQueueItemRepository queueItemRepository, IRequestCommandFactory requestCommandFactory, ILogger logger, IActionJournalRepository actionJournalRepository) : - base(signingDevice, countryspecificSettings, queueItemRepository, requestCommandFactory, logger, actionJournalRepository) - { - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/IITSSCDProvider.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/IITSSCDProvider.cs deleted file mode 100644 index c90574db4..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/IITSSCDProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1.it; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Services -{ - public interface IITSSCDProvider - { - IITSSCD Instance { get; } - - Task RegisterCurrentScuAsync(); - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/ITSSCDProvider.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/ITSSCDProvider.cs deleted file mode 100644 index d950e874f..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/ITSSCDProvider.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.Abstractions; -using fiskaltrust.Middleware.Contracts.Models; -using fiskaltrust.storage.V0; -using Newtonsoft.Json; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Services -{ - public class ITSSCDProvider : IITSSCDProvider - { - - private readonly IClientFactory _clientFactory; - private readonly MiddlewareConfiguration _middlewareConfiguration; - - private readonly SemaphoreSlim _semaphoreInstance = new SemaphoreSlim(1, 1); - private readonly SemaphoreSlim _semaphoreRegister = new SemaphoreSlim(1, 1); - - private IITSSCD _instance; - - public IITSSCD Instance - { - get - { - try - { - _semaphoreInstance.Wait(); - if (_instance == null) - { - RegisterCurrentScuAsync().Wait(); - } - - return _instance; - } - finally - { - _semaphoreInstance.Release(); - } - } - } - - public ITSSCDProvider(IClientFactory clientFactory, MiddlewareConfiguration middlewareConfiguration) - { - _clientFactory = clientFactory; - _middlewareConfiguration = middlewareConfiguration; - } - - public async Task RegisterCurrentScuAsync() - { - try - { - await _semaphoreRegister.WaitAsync().ConfigureAwait(false); - var ftSignaturCreationUnitIT = JsonConvert.DeserializeObject>(_middlewareConfiguration.Configuration["init_ftSignaturCreationUnitIT"].ToString()); - - var uri = GetUriForSignaturCreationUnit(ftSignaturCreationUnitIT.FirstOrDefault().Url); - var config = new ClientConfiguration - { - Url = uri.ToString(), - UrlType = uri.Scheme - }; - - _instance = _clientFactory.CreateClient(config); - } - finally - { - _semaphoreRegister.Release(); - } - } - - private static Uri GetUriForSignaturCreationUnit(string url) - { - - try - { - var urls = JsonConvert.DeserializeObject(url); - var grpcUrl = urls.FirstOrDefault(x => x.StartsWith("grpc://")); - url = grpcUrl ?? urls.First(); - } - catch { } - - return new Uri(url); - } - - } - -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/SscdIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/SscdIT.cs deleted file mode 100644 index 1cc0b7f17..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/Services/SscdIT.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using fiskaltrust.ifPOS.v1.it; -using Newtonsoft.Json; -using fiskaltrust.Middleware.Contracts.Interfaces; - -namespace fiskaltrust.Middleware.Localization.QueueIT.Services -{ - public class SscdIT : ISSCD - { - private readonly IITSSCD _client; - private readonly ILogger _logger; - - - public SscdIT(IITSSCDProvider itIsscdProvider, ILogger logger) - { - _client = itIsscdProvider.Instance; - _logger = logger; - } - - public async Task IsSSCDAvailable() - { - try - { - var deviceInfo = await _client.GetDeviceInfoAsync().ConfigureAwait(false); - _logger.LogDebug(JsonConvert.SerializeObject(deviceInfo)); - return true; - }catch (Exception ex) { - _logger.LogError(ex, "Error on DeviceInfo Request."); - return false; - } - } - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessor.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessor.cs new file mode 100644 index 000000000..e09228481 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessor.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.Contracts.Extensions; +using fiskaltrust.Middleware.Contracts.Interfaces; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; +using fiskaltrust.Middleware.Localization.QueueIT.Extensions; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.storage.V0; + +namespace fiskaltrust.Middleware.Localization.QueueIT +{ + public class SignProcessor : IMarketSpecificSignProcessor + { + protected readonly IConfigurationRepository _configurationRepository; + private readonly SignProcessorIT _signProcessorIT; + + public SignProcessor(IConfigurationRepository configurationRepository, SignProcessorIT signProcessorIT) + { + _configurationRepository = configurationRepository; + _signProcessorIT = signProcessorIT; + } + + public async Task<(ReceiptResponse receiptResponse, List actionJournals)> ProcessAsync(ReceiptRequest request, ftQueue queue, ftQueueItem queueItem) + { + + var receiptIdentification = $"ft{queue.ftReceiptNumerator:X}#"; + var receiptResponse = new ReceiptResponse + { + ftCashBoxID = request.ftCashBoxID, + ftQueueID = queueItem.ftQueueId.ToString(), + ftQueueItemID = queueItem.ftQueueItemId.ToString(), + ftQueueRow = queueItem.ftQueueRow, + cbTerminalID = request.cbTerminalID, + cbReceiptReference = request.cbReceiptReference, + ftReceiptMoment = DateTime.UtcNow, + ftState = Cases.BASE_STATE, + ftReceiptIdentification = receiptIdentification + }; + + if (queue.IsDeactivated()) + { + return ReturnWithQueueIsDisabled(queue, receiptResponse, queueItem); + } + + if (request.IsInitialOperation() && !queue.IsNew()) + { + receiptResponse.SetReceiptResponseError("The queue is already operational. It is not allowed to send another InitOperation Receipt"); + return (receiptResponse, new List()); + } + + if (!request.IsInitialOperation() && queue.IsNew()) + { + return ReturnWithQueueIsNotActive(queue, receiptResponse, queueItem); + } + + return await _signProcessorIT.ProcessAsync(request, receiptResponse, queue, queueItem).ConfigureAwait(false); + } + + public (ReceiptResponse receiptResponse, List actionJournals) ReturnWithQueueIsNotActive(ftQueue queue, ReceiptResponse receiptResponse, ftQueueItem queueItem) + { + var actionJournals = new List + { + new ftActionJournal + { + ftActionJournalId = Guid.NewGuid(), + ftQueueId = queueItem.ftQueueId, + ftQueueItemId = queueItem.ftQueueItemId, + Moment = DateTime.UtcNow, + Message = $"QueueId {queueItem.ftQueueId} has not been activated yet." + } + }; + receiptResponse.ftState += ftStatesFlags.SECURITY_MECHAMISN_DEACTIVATED; + receiptResponse.ftReceiptIdentification = $"ft{queue.ftReceiptNumerator:X}#"; + return (receiptResponse, actionJournals); + } + + public (ReceiptResponse receiptResponse, List actionJournals) ReturnWithQueueIsDisabled(ftQueue queue, ReceiptResponse receiptResponse, ftQueueItem queueItem) + { + var actionJournals = new List + { + new ftActionJournal + { + ftActionJournalId = Guid.NewGuid(), + ftQueueId = queueItem.ftQueueId, + ftQueueItemId = queueItem.ftQueueItemId, + Moment = DateTime.UtcNow, + Message = $"QueueId {queueItem.ftQueueId} has been disabled." + } + }; + receiptResponse.ftState += ftStatesFlags.SECURITY_MECHAMISN_DEACTIVATED; + receiptResponse.ftReceiptIdentification = $"ft{queue.ftReceiptNumerator:X}#"; + return (receiptResponse, actionJournals); + } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessorIT.cs index 93e327d23..5d986728e 100644 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessorIT.cs +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignProcessorIT.cs @@ -2,56 +2,82 @@ using System.Collections.Generic; using System.Threading.Tasks; using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.Localization.QueueIT.Extensions; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.Middleware.Localization.QueueIT.v2; using fiskaltrust.storage.V0; -using System.Linq; -using fiskaltrust.Middleware.Contracts.Exceptions; -using fiskaltrust.Middleware.Localization.QueueIT.RequestCommands; -using fiskaltrust.Middleware.Contracts.RequestCommands.Factories; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Interfaces; using Microsoft.Extensions.Logging; namespace fiskaltrust.Middleware.Localization.QueueIT { - public class SignProcessorIT : IMarketSpecificSignProcessor + public class SignProcessorIT { - private readonly ICountrySpecificSettings _countrySpecificSettings; - private readonly IRequestCommandFactory _requestCommandFactory; protected readonly IConfigurationRepository _configurationRepository; - private readonly ISSCD _signingDevice; - private readonly ILogger _logger; + private readonly LifecyclCommandProcessorIT _lifecyclCommandProcessorIT; + private readonly ReceiptCommandProcessorIT _receiptCommandProcessorIT; + private readonly DailyOperationsCommandProcessorIT _dailyOperationsCommandProcessorIT; + private readonly InvoiceCommandProcessorIT _invoiceCommandProcessorIT; + private readonly ProtocolCommandProcessorIT _protocolCommandProcessorIT; + private readonly ILogger _logger; - public SignProcessorIT(ISSCD signingDevice, ILogger logger, ICountrySpecificSettings countrySpecificSettings, IRequestCommandFactory requestCommandFactory, IConfigurationRepository configurationRepository) + public SignProcessorIT(ILogger logger, IConfigurationRepository configurationRepository, LifecyclCommandProcessorIT lifecyclCommandProcessorIT, ReceiptCommandProcessorIT receiptCommandProcessorIT, DailyOperationsCommandProcessorIT dailyOperationsCommandProcessorIT, InvoiceCommandProcessorIT invoiceCommandProcessorIT, ProtocolCommandProcessorIT protocolCommandProcessorIT) { - _requestCommandFactory = requestCommandFactory; _configurationRepository = configurationRepository; - _countrySpecificSettings = countrySpecificSettings; - _signingDevice = signingDevice; + _lifecyclCommandProcessorIT = lifecyclCommandProcessorIT; + _receiptCommandProcessorIT = receiptCommandProcessorIT; + _dailyOperationsCommandProcessorIT = dailyOperationsCommandProcessorIT; + _invoiceCommandProcessorIT = invoiceCommandProcessorIT; + _protocolCommandProcessorIT = protocolCommandProcessorIT; _logger = logger; } - public async Task<(ReceiptResponse receiptResponse, List actionJournals)> ProcessAsync(ReceiptRequest request, ftQueue queue, ftQueueItem queueItem) + public async Task<(ReceiptResponse receiptResponse, List actionJournals)> ProcessAsync(ReceiptRequest request, ReceiptResponse receiptResponse, ftQueue queue, ftQueueItem queueItem) { var queueIT = await _configurationRepository.GetQueueITAsync(queue.ftQueueId).ConfigureAwait(false); - if (!queueIT.ftSignaturCreationUnitITId.HasValue) - { - throw new NullReferenceException(nameof(queueIT.ftSignaturCreationUnitITId)); - } - var requestCommand = _requestCommandFactory.Create(request); + receiptResponse.ftCashBoxIdentification = queueIT.CashBoxIdentification; - var scu = await _configurationRepository.GetSignaturCreationUnitITAsync(queueIT.ftSignaturCreationUnitITId.Value); - if (string.IsNullOrEmpty(scu.InfoJson) && requestCommand is not InitialOperationReceiptCommand) + try { - throw new MissiningInitialOpException(); - } - if (queueIT.SSCDFailCount > 0 && requestCommand is not ZeroReceiptCommandIT) + if (request.IsDailyOperation()) + { + (var response, var actionJournals) = await _dailyOperationsCommandProcessorIT.ProcessReceiptAsync(new ProcessCommandRequest(queue, queueIT, request, receiptResponse, queueItem)).ConfigureAwait(false); + return (response, actionJournals); + } + + if (request.IsLifeCycleOperation()) + { + (var response, var actionJournals) = await _lifecyclCommandProcessorIT.ProcessReceiptAsync(new ProcessCommandRequest(queue, queueIT, request, receiptResponse, queueItem)).ConfigureAwait(false); + return (response, actionJournals); + } + + if (request.IsReceiptOperation()) + { + var (response, actionJournals) = await _receiptCommandProcessorIT.ProcessReceiptAsync(new ProcessCommandRequest(queue, queueIT, request, receiptResponse, queueItem)).ConfigureAwait(false); + return (response, actionJournals); + } + + if (request.IsProtocolOperation()) + { + var (response, actionJournals) = await _protocolCommandProcessorIT.ProcessReceiptAsync(new ProcessCommandRequest(queue, queueIT, request, receiptResponse, queueItem)).ConfigureAwait(false); + return (response, actionJournals); + } + + if (request.IsInvoiceOperation()) + { + var (response, actionJournals) = await _invoiceCommandProcessorIT.ProcessReceiptAsync(new ProcessCommandRequest(queue, queueIT, request, receiptResponse, queueItem)).ConfigureAwait(false); + return (response, actionJournals); + } + + receiptResponse.SetReceiptResponseError($"The given ftReceiptCase 0x{request.ftReceiptCase:x} is not supported. Please refer to docs.fiskaltrust.cloud for supported cases."); + return (receiptResponse, new List()); + } + catch (Exception ex) { - var requestCommandResponse = await requestCommand.ProcessFailedReceiptRequest(_signingDevice, _logger, _countrySpecificSettings, queue, queueItem, request).ConfigureAwait(false); - return (requestCommandResponse.ReceiptResponse, requestCommandResponse.ActionJournals.ToList()); + _logger.LogError(ex, "Failed to process receiptcase 0x{receiptcase}", request.ftReceiptCase.ToString("X")); + receiptResponse.SetReceiptResponseError($"Failed to process receiptcase 0x{request.ftReceiptCase.ToString("X")}. with the following exception message: " + ex.Message); + return (receiptResponse, new List()); } - var response = await requestCommand.ExecuteAsync(queue, request, queueItem).ConfigureAwait(false); - return (response.ReceiptResponse, response.ActionJournals.ToList()); } } } diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignatureTypesIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignatureTypesIT.cs deleted file mode 100644 index 457236bd8..000000000 --- a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/SignatureTypesIT.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace fiskaltrust.Middleware.Localization.QueueIT -{ - public enum SignatureTypesIT - { - ReceiptNumber = 0x01, - ZNumber = 0x02, - ReceiptAmount = 0x03, - ReceiptTimestamp = 0x04 - } -} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/DailyOperationsCommandProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/DailyOperationsCommandProcessorIT.cs new file mode 100644 index 000000000..f4f46b0d2 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/DailyOperationsCommandProcessorIT.cs @@ -0,0 +1,176 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; +using fiskaltrust.Middleware.Localization.QueueIT.Factories; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.Middleware.Localization.QueueIT.Models; +using fiskaltrust.storage.V0; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public class DailyOperationsCommandProcessorIT + { + private readonly IJournalITRepository _journalITRepository; + private readonly IConfigurationRepository _configurationRepository; + private readonly IITSSCDProvider _itSSCDProvider; + + public DailyOperationsCommandProcessorIT(IITSSCDProvider itSSCDProvider, IJournalITRepository journalITRepository, IConfigurationRepository configurationRepository) + { + _itSSCDProvider = itSSCDProvider; + _journalITRepository = journalITRepository; + _configurationRepository = configurationRepository; + } + + public async Task ProcessReceiptAsync(ProcessCommandRequest request) + { + var receiptCase = (request.ReceiptRequest.ftReceiptCase & 0xFFFF); + if (receiptCase == (int) ReceiptCases.ZeroReceipt0x2000) + return await ZeroReceipt0x2000Async(request); + + if (receiptCase == (int) ReceiptCases.OneReceipt0x2001) + return await OneReceipt0x2001Async(request); + + if (receiptCase == (int) ReceiptCases.ShiftClosing0x2010) + return await ShiftClosing0x2010Async(request); + + if (receiptCase == (int) ReceiptCases.DailyClosing0x2011) + return await DailyClosing0x2011Async(request); + + if (receiptCase == (int) ReceiptCases.MonthlyClosing0x2012) + return await MonthlyClosing0x2012Async(request); + + if (receiptCase == (int) ReceiptCases.YearlyClosing0x2013) + return await YearlyClosing0x2013Async(request); + + request.ReceiptResponse.SetReceiptResponseError($"The given ReceiptCase 0x{request.ReceiptRequest.ftReceiptCase:x} is not supported. Please refer to docs.fiskaltrust.cloud for supported cases."); + return new ProcessCommandResponse(request.ReceiptResponse, new List()); + } + + public async Task ZeroReceipt0x2000Async(ProcessCommandRequest request) + { + var (queue, queueIT, receiptRequest, receiptResponse, queueItem) = request; + if (queueIT.SSCDFailCount != 0) + { + queueIT.SSCDFailCount = 0; + queueIT.SSCDFailMoment = null; + queueIT.SSCDFailQueueItemId = null; + await _configurationRepository.InsertOrUpdateQueueITAsync(queueIT).ConfigureAwait(false); + } + + var establishConnection = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse + }); + if (establishConnection.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(establishConnection.ReceiptResponse, new List()); + } + + if (establishConnection.ReceiptResponse.ftState == 0x4954_2001_0000_0000) + { + return new ProcessCommandResponse(establishConnection.ReceiptResponse, new List()); + } + return new ProcessCommandResponse(establishConnection.ReceiptResponse, new List()); + } + + public async Task OneReceipt0x2001Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())); + + public async Task ShiftClosing0x2010Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())); + + public async Task DailyClosing0x2011Async(ProcessCommandRequest request) + { + var (queue, queueIt, receiptRequest, receiptResponse, queueItem) = request; + var actionJournalEntry = ftActionJournalFactory.CreateDailyClosingActionJournal(queue, queueItem, receiptRequest); + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(result.ReceiptResponse, new List()); + } + + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber).Data; + receiptResponse.ftReceiptIdentification += $"Z{zNumber.PadLeft(4, '0')}"; + receiptResponse.ftSignatures = result.ReceiptResponse.ftSignatures; + + var journalIT = ftJournalITFactory.CreateFrom(queueItem, queueIt, new ScuResponse() + { + ftReceiptCase = receiptRequest.ftReceiptCase, + ZRepNumber = long.Parse(zNumber) + }); + await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); + + return new ProcessCommandResponse(receiptResponse, new List + { + actionJournalEntry + }); + } + + public async Task MonthlyClosing0x2012Async(ProcessCommandRequest request) + { + var (queue, queueIt, receiptRequest, receiptResponse, queueItem) = request; + var actionJournalEntry = ftActionJournalFactory.CreateMonthlyClosingActionJournal(queue, queueItem, receiptRequest); + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(result.ReceiptResponse, new List()); + } + + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber).Data; + receiptResponse.ftReceiptIdentification += $"Z{zNumber.PadLeft(4, '0')}"; + receiptResponse.ftSignatures = result.ReceiptResponse.ftSignatures; + + var journalIT = ftJournalITFactory.CreateFrom(queueItem, queueIt, new ScuResponse() + { + ftReceiptCase = receiptRequest.ftReceiptCase, + ZRepNumber = long.Parse(zNumber) + }); + await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); + + return new ProcessCommandResponse(receiptResponse, new List + { + actionJournalEntry + }); + } + + public async Task YearlyClosing0x2013Async(ProcessCommandRequest request) + { + var (queue, queueIt, receiptRequest, receiptResponse, queueItem) = request; + + var actionJournalEntry = ftActionJournalFactory.CreateYearlyClosingClosingActionJournal(queue, queueItem, receiptRequest); + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(result.ReceiptResponse, new List()); + } + + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber).Data; + receiptResponse.ftReceiptIdentification += $"Z{zNumber.PadLeft(4, '0')}"; + receiptResponse.ftSignatures = result.ReceiptResponse.ftSignatures; + var journalIT = ftJournalITFactory.CreateFrom(queueItem, queueIt, new ScuResponse() + { + ftReceiptCase = receiptRequest.ftReceiptCase, + ZRepNumber = long.Parse(zNumber) + }); + await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); + return new ProcessCommandResponse(receiptResponse, new List + { + actionJournalEntry + }); + } + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/InvoiceCommandProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/InvoiceCommandProcessorIT.cs new file mode 100644 index 000000000..08208f45d --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/InvoiceCommandProcessorIT.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.storage.V0; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public class InvoiceCommandProcessorIT + { + public async Task ProcessReceiptAsync(ProcessCommandRequest request) + { + var receiptCase = (request.ReceiptRequest.ftReceiptCase & 0xFFFF); + if (receiptCase == (int)ReceiptCases.InvoiceUnknown0x1000) + return await InvoiceUnknown0x1000Async(request); + + if (receiptCase == (int)ReceiptCases.InvoiceB2C0x1001) + return await InvoiceB2C0x1001Async(request); + + if (receiptCase == (int)ReceiptCases.InvoiceB2B0x1002) + return await InvoiceB2B0x1002Async(request); + + if (receiptCase == (int)ReceiptCases.InvoiceB2G0x1003) + return await InvoiceB2G0x1003Async(request); + + request.ReceiptResponse.SetReceiptResponseError($"The given ftReceiptCase 0x{request.ReceiptRequest.ftReceiptCase:x} is not supported. Please refer to docs.fiskaltrust.cloud for supported cases."); + return new ProcessCommandResponse(request.ReceiptResponse, new List()); + } + + public async Task InvoiceUnknown0x1000Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task InvoiceB2C0x1001Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task InvoiceB2B0x1002Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task InvoiceB2G0x1003Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/LifecyclCommandProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/LifecyclCommandProcessorIT.cs new file mode 100644 index 000000000..dc2047132 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/LifecyclCommandProcessorIT.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Localization.QueueIT.Factories; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.storage.V0; +using Newtonsoft.Json; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public class LifecyclCommandProcessorIT + { + private readonly IITSSCDProvider _itSSCDProvider; + private readonly IJournalITRepository _journalITRepository; + private readonly IConfigurationRepository _configurationRepository; + + public LifecyclCommandProcessorIT(IITSSCDProvider itSSCDProvider, IJournalITRepository journalITRepository, IConfigurationRepository configurationRepository) + { + _itSSCDProvider = itSSCDProvider; + _journalITRepository = journalITRepository; + _configurationRepository = configurationRepository; + } + + public async Task ProcessReceiptAsync(ProcessCommandRequest request) + { + var receiptCase = (request.ReceiptRequest.ftReceiptCase & 0xFFFF); + if (receiptCase == (int) ReceiptCases.InitialOperationReceipt0x4001) + return await InitialOperationReceipt0x4001Async(request); + + if (receiptCase == (int) ReceiptCases.OutOfOperationReceipt0x4002) + return await OutOfOperationReceipt0x4002Async(request); + + if (receiptCase == (int) ReceiptCases.InitSCUSwitch0x4011) + return await InitSCUSwitch0x4011Async(request); + + if (receiptCase == (int) ReceiptCases.FinishSCUSwitch0x4012) + return await FinishSCUSwitch0x4012Async(request); + + request.ReceiptResponse.SetReceiptResponseError($"The given ReceiptCase 0x{request.ReceiptRequest.ftReceiptCase:x} is not supported. Please refer to docs.fiskaltrust.cloud for supported cases."); + return new ProcessCommandResponse(request.ReceiptResponse, new List()); + } + + public async Task InitialOperationReceipt0x4001Async(ProcessCommandRequest request) + { + // TODO SKE => We need to figure a way to retry this functionality in case we fail to do something. There are a few states that + // we need to take care of: + // - SCU is not rechable => initial operation fails with EEEE_EEEE and needs to be retried by the caller + // - SCU is reachable but fails internall => initial operation fails with EEEE_EEEE and needs to be retried by the caller + // - SCU succeeds, but the Queue fails to receive / store the result for whatever reason => initial operation fails with EEEE_EEEE and needs to be retried by the caller but the SCU should be capable of handling that + // + // A few more points regarding the activation + // - If we fail to receive the result the point of activation doesn't match with the one given in the QueueItem. + // - + var (queue, queueIt, receiptRequest, receiptResponse, queueItem) = request; + var scu = await _configurationRepository.GetSignaturCreationUnitITAsync(queueIt.ftSignaturCreationUnitITId.Value).ConfigureAwait(false); + var deviceInfo = await _itSSCDProvider.GetRTInfoAsync().ConfigureAwait(false); + if (string.IsNullOrEmpty(scu.InfoJson)) + { + scu.InfoJson = JsonConvert.SerializeObject(deviceInfo); + await _configurationRepository.InsertOrUpdateSignaturCreationUnitITAsync(scu).ConfigureAwait(false); + } + + var signature = SignaturItemFactory.CreateInitialOperationSignature(queueIt, deviceInfo); + var actionJournal = ftActionJournalFactory.CreateInitialOperationActionJournal(queue, queueItem, queueIt, receiptRequest); + + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse, + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(receiptResponse, new List()); + } + + var signatures = new List + { + signature + }; + queue.StartMoment = DateTime.UtcNow; + await _configurationRepository.InsertOrUpdateQueueAsync(queue).ConfigureAwait(false); + signatures.AddRange(result.ReceiptResponse.ftSignatures); + receiptResponse.ftSignatures = signatures.ToArray(); + + return new ProcessCommandResponse(receiptResponse, new List + { + actionJournal + }); + } + + public async Task OutOfOperationReceipt0x4002Async(ProcessCommandRequest request) + { + var (queue, queueIt, receiptRequest, receiptResponse, queueItem) = request; + + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse, + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(receiptResponse, new List()); + } + + queue.StopMoment = DateTime.UtcNow; + await _configurationRepository.InsertOrUpdateQueueAsync(queue); + + var signatureItem = SignaturItemFactory.CreateOutOfOperationSignature(queueIt); + var actionJournal = ftActionJournalFactory.CreateOutOfOperationActionJournal(queue, queueItem, queueIt, receiptRequest); + var signatures = new List + { + signatureItem + }; + signatures.AddRange(result.ReceiptResponse.ftSignatures); + receiptResponse.ftSignatures = signatures.ToArray(); + return new ProcessCommandResponse(receiptResponse, new List + { + actionJournal + }); + } + + public async Task InitSCUSwitch0x4011Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task FinishSCUSwitch0x4012Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Models/ProcessCommandRequest.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Models/ProcessCommandRequest.cs new file mode 100644 index 000000000..ef2fee048 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Models/ProcessCommandRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.storage.V0; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public record ProcessCommandRequest(ftQueue Queue, ftQueueIT QueueIt, ReceiptRequest ReceiptRequest, ReceiptResponse ReceiptResponse, ftQueueItem QueueItem); +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Models/ProcessCommandResponse.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Models/ProcessCommandResponse.cs new file mode 100644 index 000000000..01203a4b2 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Models/ProcessCommandResponse.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.storage.V0; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public record ProcessCommandResponse(ReceiptResponse receiptResponse, List actionJournals); +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/ProtocolCommandProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/ProtocolCommandProcessorIT.cs new file mode 100644 index 000000000..e595ed613 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/ProtocolCommandProcessorIT.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Contracts.Repositories; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.storage.V0; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public class ProtocolCommandProcessorIT + { + private readonly IITSSCDProvider _itSSCDProvider; + private readonly IJournalITRepository _journalITRepository; + private readonly IMiddlewareQueueItemRepository _queueItemRepository; + private readonly ILogger _logger; + + public ProtocolCommandProcessorIT(IITSSCDProvider itSSCDProvider, IJournalITRepository journalITRepository, IMiddlewareQueueItemRepository queueItemRepository, ILogger logger) + { + _itSSCDProvider = itSSCDProvider; + _journalITRepository = journalITRepository; + _queueItemRepository = queueItemRepository; + _logger = logger; + } + + public async Task ProcessReceiptAsync(ProcessCommandRequest request) + { + var receiptCase = (request.ReceiptRequest.ftReceiptCase & 0xFFFF); + if (receiptCase == (int) ReceiptCases.ProtocolUnspecified0x3000) + return await ProtocolUnspecified0x3000Async(request); + + if (receiptCase == (int) ReceiptCases.ProtocolTechnicalEvent0x3001) + return await ProtocolTechnicalEvent0x3001Async(request); + + if (receiptCase == (int) ReceiptCases.ProtocolAccountingEvent0x3002) + return await ProtocolAccountingEvent0x3002Async(request); + + if (receiptCase == (int) ReceiptCases.InternalUsageMaterialConsumption0x3003) + return await InternalUsageMaterialConsumption0x3003Async(request); + + if (receiptCase == (int) ReceiptCases.Order0x3004) + return await Order0x3004Async(request); + + if (receiptCase == (int) ReceiptCases.CopyReceiptPrintExistingReceipt0x3010) + return await CopyReceiptPrintExistingReceipt0x3010Async(request); + + request.ReceiptResponse.SetReceiptResponseError($"The given ftReceiptCase 0x{request.ReceiptRequest.ftReceiptCase:x} is not supported. Please refer to docs.fiskaltrust.cloud for supported cases."); + return new ProcessCommandResponse(request.ReceiptResponse, new List()); + } + + public async Task ProtocolUnspecified0x3000Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task ProtocolTechnicalEvent0x3001Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task ProtocolAccountingEvent0x3002Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task InternalUsageMaterialConsumption0x3003Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task Order0x3004Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task CopyReceiptPrintExistingReceipt0x3010Async(ProcessCommandRequest request) + { + var (queue, queueIT, receiptRequest, receiptResponse, queueItem) = request; + await LoadReceiptReferencesToResponse(receiptRequest, queueItem, receiptResponse); + try + { + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(result.ReceiptResponse, new List()); + } + return new ProcessCommandResponse(result.ReceiptResponse, new List()); + } + catch (Exception ex) + { + receiptResponse.SetReceiptResponseError(ex.Message); + return new ProcessCommandResponse(receiptResponse, new List()); + } + } + + private async Task LoadReceiptReferencesToResponse(ReceiptRequest request, ftQueueItem queueItem, ReceiptResponse receiptResponse) + { + var queueItems = _queueItemRepository.GetByReceiptReferenceAsync(request.cbPreviousReceiptReference, request.cbTerminalID); + await foreach (var existingQueueItem in queueItems) + { + var referencedResponse = JsonConvert.DeserializeObject(existingQueueItem.response); + var documentNumber = referencedResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber).Data; + var zNumber = referencedResponse.GetSignaturItem(SignatureTypesIT.RTZNumber).Data; + var documentMoment = referencedResponse.GetSignaturItem(SignatureTypesIT.RTDocumentMoment)?.Data; + documentMoment ??= queueItem.cbReceiptMoment.ToString("yyyy-MM-dd"); + var signatures = new List(); + signatures.AddRange(receiptResponse.ftSignatures); + signatures.AddRange(new List + { + new SignaturItem + { + Caption = "", + Data = zNumber.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }, + new SignaturItem + { + Caption = "", + Data = documentNumber.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = documentMoment, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }, + }); + receiptResponse.ftSignatures = signatures.ToArray(); + break; + } + } + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/ReceiptCommandProcessorIT.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/ReceiptCommandProcessorIT.cs new file mode 100644 index 000000000..690111cda --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/ReceiptCommandProcessorIT.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Contracts.Repositories; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; +using fiskaltrust.Middleware.Localization.QueueIT.Extensions; +using fiskaltrust.Middleware.Localization.QueueIT.Factories; +using fiskaltrust.Middleware.Localization.QueueIT.Helpers; +using fiskaltrust.Middleware.Localization.QueueIT.Models; +using fiskaltrust.storage.V0; +using Newtonsoft.Json; + +#pragma warning disable + +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public class ReceiptCommandProcessorIT + { + private readonly IITSSCDProvider _itSSCDProvider; + private readonly IJournalITRepository _journalITRepository; + private readonly IMiddlewareQueueItemRepository _queueItemRepository; + + public ReceiptCommandProcessorIT(IITSSCDProvider itSSCDProvider, IJournalITRepository journalITRepository, IMiddlewareQueueItemRepository queueItemRepository) + { + _itSSCDProvider = itSSCDProvider; + _journalITRepository = journalITRepository; + _queueItemRepository = queueItemRepository; + } + + public async Task ProcessReceiptAsync(ProcessCommandRequest request) + { + var receiptCase = (request.ReceiptRequest.ftReceiptCase & 0xFFFF); + if (receiptCase == (int) ReceiptCases.UnknownReceipt0x0000) + return await UnknownReceipt0x0000Async(request); + + if (receiptCase == (int) ReceiptCases.PointOfSaleReceipt0x0001) + return await PointOfSaleReceipt0x0001Async(request); + + if (receiptCase == (int) ReceiptCases.PaymentTransfer0x0002) + return await PaymentTransfer0x0002Async(request); + + if (receiptCase == (int) ReceiptCases.PointOfSaleReceiptWithoutObligation0x0003) + return await PointOfSaleReceiptWithoutObligation0x0003Async(request); + + if (receiptCase == (int) ReceiptCases.ECommerce0x0004) + return await ECommerce0x0004Async(request); + + if (receiptCase == (int) ReceiptCases.Protocol0x0005) + return await Protocol0x0005Async(request); + + request.ReceiptResponse.SetReceiptResponseError($"The given ftReceiptCase 0x{request.ReceiptRequest.ftReceiptCase:x} is not supported. Please refer to docs.fiskaltrust.cloud for supported cases."); + return new ProcessCommandResponse(request.ReceiptResponse, new List()); + } + + public async Task UnknownReceipt0x0000Async(ProcessCommandRequest request) => await PointOfSaleReceipt0x0001Async(request); + + public async Task PointOfSaleReceipt0x0001Async(ProcessCommandRequest request) + { + if (request.ReceiptRequest.IsVoid() || request.ReceiptRequest.IsRefund()) + { + await LoadReceiptReferencesToResponse(request.ReceiptRequest, request.QueueItem, request.ReceiptResponse); + } + + var (queue, queueIt, receiptRequest, receiptResponse, queueItem) = request; + + var result = await _itSSCDProvider.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = receiptRequest, + ReceiptResponse = receiptResponse, + }); + if (result.ReceiptResponse.HasFailed()) + { + return new ProcessCommandResponse(result.ReceiptResponse, new List()); + } + + var documentNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber); + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber); + receiptResponse.ftReceiptIdentification += $"{zNumber.Data.PadLeft(4, '0')}-{documentNumber.Data.PadLeft(4, '0')}"; + receiptResponse.ftSignatures = result.ReceiptResponse.ftSignatures; + receiptResponse.InsertSignatureItems(SignaturItemFactory.CreatePOSReceiptFormatSignatures(receiptResponse)); + var journalIT = ftJournalITFactory.CreateFrom(queueItem, queueIt, new ScuResponse() + { + ftReceiptCase = receiptRequest.ftReceiptCase, + ReceiptNumber = long.Parse(documentNumber.Data), + ZRepNumber = long.Parse(zNumber.Data) + }); + await _journalITRepository.InsertAsync(journalIT).ConfigureAwait(false); + return new ProcessCommandResponse(receiptResponse, new List()); + } + + public async Task PaymentTransfer0x0002Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task PointOfSaleReceiptWithoutObligation0x0003Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task ECommerce0x0004Async(ProcessCommandRequest request) => await Task.FromResult(new ProcessCommandResponse(request.ReceiptResponse, new List())).ConfigureAwait(false); + + public async Task Protocol0x0005Async(ProcessCommandRequest request) => await PointOfSaleReceipt0x0001Async(request); + + private async Task LoadReceiptReferencesToResponse(ReceiptRequest request, ftQueueItem queueItem, ReceiptResponse receiptResponse) + { + var queueItems = _queueItemRepository.GetByReceiptReferenceAsync(request.cbPreviousReceiptReference, request.cbTerminalID); + // What should we do in this case? Cannot really proceed with the storno but we + await foreach (var existingQueueItem in queueItems) + { + var referencedResponse = JsonConvert.DeserializeObject(existingQueueItem.response); + var documentNumber = referencedResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber).Data; + var zNumber = referencedResponse.GetSignaturItem(SignatureTypesIT.RTZNumber).Data; + var documentMoment = referencedResponse.GetSignaturItem(SignatureTypesIT.RTDocumentMoment)?.Data; + documentMoment ??= queueItem.cbReceiptMoment.ToString("yyyy-MM-dd"); + var signatures = new List(); + signatures.AddRange(receiptResponse.ftSignatures); + signatures.AddRange(new List + { + new SignaturItem + { + Caption = "", + Data = zNumber.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }, + new SignaturItem + { + Caption = "", + Data = documentNumber.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = documentMoment, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }, + }); + receiptResponse.ftSignatures = signatures.ToArray(); + break; + } + } + } +} diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Tagging/ITReceiptCases.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Tagging/ITReceiptCases.cs new file mode 100644 index 000000000..83da13716 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Tagging/ITReceiptCases.cs @@ -0,0 +1,36 @@ +namespace fiskaltrust.Middleware.Localization.QueueIT.v2 +{ + public enum ReceiptCases : long + { + UnknownReceipt0x0000 = 0x0000, + PointOfSaleReceipt0x0001 = 0x0001, + PaymentTransfer0x0002 = 0x0002, + PointOfSaleReceiptWithoutObligation0x0003 = 0x0003, + ECommerce0x0004 = 0x0004, + Protocol0x0005 = 0x0005, + + InvoiceUnknown0x1000 = 0x1000, + InvoiceB2C0x1001 = 0x1001, + InvoiceB2B0x1002 = 0x1002, + InvoiceB2G0x1003 = 0x1003, + + ZeroReceipt0x2000 = 0x2000, + OneReceipt0x2001 = 0x2001, + ShiftClosing0x2010 = 0x2010, + DailyClosing0x2011 = 0x2011, + MonthlyClosing0x2012 = 0x2012, + YearlyClosing0x2013 = 0x2013, + + ProtocolUnspecified0x3000 = 0x3000, + ProtocolTechnicalEvent0x3001 = 0x3001, + ProtocolAccountingEvent0x3002 = 0x3002, + InternalUsageMaterialConsumption0x3003 = 0x3003, + Order0x3004 = 0x3004, + CopyReceiptPrintExistingReceipt0x3010 = 0x3010, + + InitialOperationReceipt0x4001 = 0x4001, + OutOfOperationReceipt0x4002 = 0x4002, + InitSCUSwitch0x4011 = 0x4011, + FinishSCUSwitch0x4012 = 0x4012, + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Tagging/ftStatesFlags.cs b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Tagging/ftStatesFlags.cs new file mode 100644 index 000000000..703bd7b36 --- /dev/null +++ b/queue/src/fiskaltrust.Middleware.Localization.QueueIT/v2/Tagging/ftStatesFlags.cs @@ -0,0 +1,19 @@ +namespace fiskaltrust.Middleware.Localization.QueueIT.Constants +{ + public static class ftStatesFlags + { + public const long SECURITY_MECHAMISN_DEACTIVATED = 0x0000_0000_0000_0001; + + public const long SCU_TEMPORARY_OUT_OF_SERVICE = 0x0000_0000_0000_0002; + + public const long LATESIGNINGMODE_ISACTIVE = 0x0000_0000_0000_0008; + + public const long MESSAGE_IS_PENDING = 0x0000_0000_0000_0040; + + public const long DAILY_CLOSING_IS_DUE = 0x0000_0000_0000_0100; + + public const long ERROR = 0x0000_0000_EEEE_EEEE; + + public const long FAIIL = 0x0000_0000_FFFF_FFFF; + } +} \ No newline at end of file diff --git a/queue/src/fiskaltrust.Middleware.Queue.AzureTableStorage/version.json b/queue/src/fiskaltrust.Middleware.Queue.AzureTableStorage/version.json index 5b52c5c85..6b2ce375c 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.AzureTableStorage/version.json +++ b/queue/src/fiskaltrust.Middleware.Queue.AzureTableStorage/version.json @@ -1,5 +1,5 @@ { - "version": "1.3.49", + "version": "1.3.50-rc1", "releaseBranches": [ "^refs/tags/queue/azuretablestorage/v\\d+(?:\\.\\d+)*(?:-.*)?$" ] diff --git a/queue/src/fiskaltrust.Middleware.Queue.EF/version.json b/queue/src/fiskaltrust.Middleware.Queue.EF/version.json index dcc6ca445..bac787247 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.EF/version.json +++ b/queue/src/fiskaltrust.Middleware.Queue.EF/version.json @@ -1,5 +1,5 @@ { - "version": "1.3.49", + "version": "1.3.50-rc1", "releaseBranches": [ "^refs/tags/queue/ef/v\\d+(?:\\.\\d+)*(?:-.*)?$" ] diff --git a/queue/src/fiskaltrust.Middleware.Queue.InMemory/version.json b/queue/src/fiskaltrust.Middleware.Queue.InMemory/version.json index 80184f6a3..03c3e3d7d 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.InMemory/version.json +++ b/queue/src/fiskaltrust.Middleware.Queue.InMemory/version.json @@ -1,5 +1,5 @@ { - "version": "1.3.49", + "version": "1.3.50-rc1", "releaseBranches": [ "^refs/tags/queue/inmemory/v\\d+(?:\\.\\d+)*(?:-.*)?$" ] diff --git a/queue/src/fiskaltrust.Middleware.Queue.MySQL/version.json b/queue/src/fiskaltrust.Middleware.Queue.MySQL/version.json index e3a253e60..7780c640e 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.MySQL/version.json +++ b/queue/src/fiskaltrust.Middleware.Queue.MySQL/version.json @@ -1,5 +1,5 @@ { - "version": "1.3.49", + "version": "1.3.50-rc1", "releaseBranches": [ "^refs/tags/queue/mysql/v\\d+(?:\\.\\d+)*(?:-.*)?$" ] diff --git a/queue/src/fiskaltrust.Middleware.Queue.PostgreSQL/version.json b/queue/src/fiskaltrust.Middleware.Queue.PostgreSQL/version.json index 571a678ff..adbee9504 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.PostgreSQL/version.json +++ b/queue/src/fiskaltrust.Middleware.Queue.PostgreSQL/version.json @@ -1,5 +1,5 @@ { - "version": "1.3.49", + "version": "1.3.50-rc1", "releaseBranches": [ "^refs/tags/queue/postgresql/v\\d+(?:\\.\\d+)*(?:-.*)?$" ] diff --git a/queue/src/fiskaltrust.Middleware.Queue.SQLite/.nuspec b/queue/src/fiskaltrust.Middleware.Queue.SQLite/.nuspec index a924d2f16..c3efb67d4 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.SQLite/.nuspec +++ b/queue/src/fiskaltrust.Middleware.Queue.SQLite/.nuspec @@ -19,7 +19,7 @@ - + diff --git a/queue/src/fiskaltrust.Middleware.Queue.SQLite/version.json b/queue/src/fiskaltrust.Middleware.Queue.SQLite/version.json index 7cdf36b5f..8f85e51b4 100644 --- a/queue/src/fiskaltrust.Middleware.Queue.SQLite/version.json +++ b/queue/src/fiskaltrust.Middleware.Queue.SQLite/version.json @@ -1,5 +1,5 @@ { - "version": "1.3.49", + "version": "1.3.50-rc1", "releaseBranches": [ "^refs/tags/queue/sqlite/v\\d+(?:\\.\\d+)*(?:-.*)?$" ] diff --git a/queue/src/fiskaltrust.Middleware.Queue/SignProcessor.cs b/queue/src/fiskaltrust.Middleware.Queue/SignProcessor.cs index 03477893c..3cc6399f3 100644 --- a/queue/src/fiskaltrust.Middleware.Queue/SignProcessor.cs +++ b/queue/src/fiskaltrust.Middleware.Queue/SignProcessor.cs @@ -169,9 +169,21 @@ private async Task InternalSign(ftQueue queue, ReceiptRequest d await _queueItemRepository.InsertOrUpdateAsync(queueItem).ConfigureAwait(false); _logger.LogTrace("SignProcessor.InternalSign: Updating Queue in database."); await _configurationRepository.InsertOrUpdateQueueAsync(queue).ConfigureAwait(false); - _logger.LogTrace("SignProcessor.InternalSign: Adding ReceiptJournal to database."); - receiptJournal = await CreateReceiptJournalAsync(queue, queueItem, data).ConfigureAwait(false); + if ((receiptResponse.ftState & 0xFFFF_FFFF) == 0xEEEE_EEEE) + { + // TODO: This state indicates that something went wrong while processing the receipt request. + // While we will probably introduce a parameter for this we are right now just returning + // the receipt response as it is. + // Another thing that needs to be considered is if and when we put things into the security + // mechanism. Since there might be cases where we still need to store it though. + return receiptResponse; + } + else + { + _logger.LogTrace("SignProcessor.InternalSign: Adding ReceiptJournal to database."); + receiptJournal = await CreateReceiptJournalAsync(queue, queueItem, data).ConfigureAwait(false); + } return receiptResponse; } finally diff --git a/queue/src/fiskaltrust.Middleware.Storage.Base/BaseStorageBootStrapper.cs b/queue/src/fiskaltrust.Middleware.Storage.Base/BaseStorageBootStrapper.cs index 53ef7d470..3c2fb0af5 100644 --- a/queue/src/fiskaltrust.Middleware.Storage.Base/BaseStorageBootStrapper.cs +++ b/queue/src/fiskaltrust.Middleware.Storage.Base/BaseStorageBootStrapper.cs @@ -113,7 +113,7 @@ public async Task PersistConfigurationAsync(StorageBaseInitConfiguration config, await InitSignaturCreationUnitFRAsync(config.SignaturCreationUnitsFR, configurationRepository).ConfigureAwait(false); await InitSignaturCreationUnitDEAsync(config.SignaturCreationUnitsDE, configurationRepository, enforceUpdateUserDefinedConfig).ConfigureAwait(false); await InitSignaturCreationUnitMEAsync(config.SignaturCreationUnitsME, configurationRepository).ConfigureAwait(false); - await InitSignaturCreationUnitITAsync(config.SignaturCreationUnitsIT, configurationRepository).ConfigureAwait(false); + await InitSignaturCreationUnitITAsync(config.SignaturCreationUnitsIT, configurationRepository, enforceUpdateUserDefinedConfig).ConfigureAwait(false); } private T ParseParameter(Dictionary config, string key) where T : new() @@ -405,15 +405,30 @@ private async Task InitSignaturCreationUnitMEAsync(List signaturCreationUnitsIT, IConfigurationRepository configurationRepository) + private async Task InitSignaturCreationUnitITAsync(List signaturCreationUnitsIT, IConfigurationRepository configurationRepository, bool enforceUpdateUserDefinedConfig) { foreach (var item in signaturCreationUnitsIT) { - var scu = await configurationRepository.GetSignaturCreationUnitITAsync(item.ftSignaturCreationUnitITId).ConfigureAwait(false); - if (scu == null) + var db_scu = await configurationRepository.GetSignaturCreationUnitITAsync(item.ftSignaturCreationUnitITId).ConfigureAwait(false); + if (db_scu == null) { await configurationRepository.InsertOrUpdateSignaturCreationUnitITAsync(item).ConfigureAwait(false); } + else if (db_scu.TimeStamp < item.TimeStamp || enforceUpdateUserDefinedConfig) + { + var changed = false; + if (!string.IsNullOrEmpty(item.Url) && db_scu.Url != item.Url) + { + changed = true; + db_scu.Url = item.Url; + } + + if (changed) + { + db_scu.TimeStamp = item.TimeStamp; + await configurationRepository.InsertOrUpdateSignaturCreationUnitITAsync(db_scu).ConfigureAwait(false); + } + } } } } diff --git a/queue/test/Directory.Build.props b/queue/test/Directory.Build.props index 1f5b36f51..1441fbeab 100644 --- a/queue/test/Directory.Build.props +++ b/queue/test/Directory.Build.props @@ -1,20 +1,24 @@ - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - + + NU1901;NU1902;NU1903;NU1904 + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/queue/test/Manual/fiskaltrust.Middleware.Queue.Test.Launcher/fiskaltrust.Middleware.Queue.Test.Launcher.csproj b/queue/test/Manual/fiskaltrust.Middleware.Queue.Test.Launcher/fiskaltrust.Middleware.Queue.Test.Launcher.csproj index 7d13d6b26..ad2c224ba 100644 --- a/queue/test/Manual/fiskaltrust.Middleware.Queue.Test.Launcher/fiskaltrust.Middleware.Queue.Test.Launcher.csproj +++ b/queue/test/Manual/fiskaltrust.Middleware.Queue.Test.Launcher/fiskaltrust.Middleware.Queue.Test.Launcher.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/Extensions.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/Extensions.cs deleted file mode 100644 index 6d9ee4bec..000000000 --- a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/Extensions.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest -{ - public static class Extensions - { - public static void SetGlobalLogger(LogLevel verbosity = LogLevel.Debug) - { - var configuration = new Serilog.LoggerConfiguration() - .Enrich.FromLogContext(); - switch (verbosity) - { - case LogLevel.Trace: - configuration = configuration.MinimumLevel.Verbose(); - break; - case LogLevel.Debug: - configuration = configuration.MinimumLevel.Debug(); - break; - case LogLevel.Information: - configuration = configuration.MinimumLevel.Information(); - break; - case LogLevel.Warning: - configuration = configuration.MinimumLevel.Warning(); - break; - case LogLevel.Error: - configuration = configuration.MinimumLevel.Error(); - break; - case LogLevel.Critical: - configuration = configuration.MinimumLevel.Fatal(); - break; - case LogLevel.None: - break; - default: - configuration = configuration.MinimumLevel.Information(); - break; - } - } - - public static IServiceCollection AddStandardLoggers(this IServiceCollection services, LogLevel verbosity) - { - SetGlobalLogger(verbosity); - - services.AddLogging(builder => builder.SetMinimumLevel(verbosity)); - return services; - } - - public static IEnumerable Flatten(this Exception exception) - { - yield return exception; - while (exception.InnerException != null) - { - yield return exception.InnerException; - exception = exception.InnerException; - } - } - } -} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/InMemoryTestScu.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/InMemoryTestScu.cs deleted file mode 100644 index 0fa86c3f1..000000000 --- a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/InMemoryTestScu.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1.it; - -namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest -{ - internal class InMemoryTestScu : IITSSCD - { - public Task EchoAsync(ScuItEchoRequest request) => throw new NotImplementedException(); - public Task ExecuteDailyClosingAsync(DailyClosingRequest request) => throw new NotImplementedException(); - - public Task FiscalReceiptInvoiceAsync(FiscalReceiptInvoice request) - { - return Task.FromResult(new FiscalReceiptResponse() - { - Amount = 9909.98m, - ReceiptNumber = 245, - ReceiptDateTime = new DateTime(1999, 1, 1, 0, 0, 1), - Success = true, - - }); - } - public Task FiscalReceiptRefundAsync(FiscalReceiptRefund request) => throw new NotImplementedException(); - public Task GetDeviceInfoAsync() => throw new NotImplementedException(); - public Task NonFiscalReceiptAsync(NonFiscalRequest request) => throw new NotImplementedException(); - } -} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/POSReceiptSignatureData.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/POSReceiptSignatureData.cs new file mode 100644 index 000000000..e9a7a451b --- /dev/null +++ b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/POSReceiptSignatureData.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.Localization.QueueIT.Constants; + +namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest +{ + public class POSReceiptSignatureData + { + public string RTSerialNumber { get; set; } = string.Empty; + public long RTZNumber { get; set; } + public long RTDocNumber { get; set; } + public DateTime RTDocMoment { get; set; } + public string RTDocType { get; set; } = string.Empty; + public string RTCodiceLotteria { get; set; } + public string RTCustomerID { get; set; } + public string RTServerSHAMetadata { get; set; } + + public long? RTReferenceZNumber { get; set; } + public long? RTReferenceDocNumber { get; set; } + public DateTime? RTReferenceDocMoment { get; set; } + + public static List CreateDocumentoCommercialeSignatures(POSReceiptSignatureData data) + { + var signatureItems = new List() + { + new SignaturItem + { + Caption = "", + Data = data.RTSerialNumber, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE |(long) SignatureTypesIT.RTSerialNumber + }, + new SignaturItem + { + Caption = "", + Data = data.RTZNumber.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTZNumber + }, + new SignaturItem + { + Caption = "", + Data = data.RTDocNumber.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE |(long) SignatureTypesIT.RTDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = data.RTDocMoment.ToString("yyyy-MM-dd HH:mm:ss"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE |(long) SignatureTypesIT.RTDocumentMoment + }, + new SignaturItem + { + Caption = "", + Data = data.RTDocType, // TODO CoNVert + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE |(long) SignatureTypesIT.RTDocumentType + } + }; + + if (!string.IsNullOrEmpty(data.RTServerSHAMetadata)) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTServerSHAMetadata, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTServerShaMetadata + }); + } + + if (!string.IsNullOrEmpty(data.RTCodiceLotteria)) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTCodiceLotteria, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTLotteryID + }); + } + + if (!string.IsNullOrEmpty(data.RTCustomerID)) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTCustomerID, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTCustomerID + }); + } + + if (data.RTReferenceZNumber.HasValue && data.RTReferenceDocNumber.HasValue && data.RTReferenceDocMoment.HasValue) // TODO WE NEED TO CHECK THAT + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTReferenceZNumber.Value.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }); + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTReferenceDocNumber.Value.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }); + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTReferenceDocMoment.Value.ToString("yyyy-MM-dd"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = Cases.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }); + } + return signatureItems; + } + } +} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/QueueITBootstrapperTests.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/QueueITBootstrapperTests.cs new file mode 100644 index 000000000..8288d7fed --- /dev/null +++ b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/QueueITBootstrapperTests.cs @@ -0,0 +1,50 @@ +using Xunit; +using Microsoft.Extensions.DependencyInjection; +using fiskaltrust.Middleware.Contracts.Interfaces; +using Moq; +using fiskaltrust.storage.V0; +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Contracts.Models; +using fiskaltrust.Middleware.Contracts.Repositories; + +namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest +{ + + + public class ReceiptTypeProcessorFactoryTests + { + [Fact] + public void CreateWithWrongReceiptCase_ShouldThrow() + { + + } + } + + public class QueueITBootstrapperTests + { + [Fact] + public void TryToConstructSignProcessorIT() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + serviceCollection.AddSingleton(Mock.Of()); + serviceCollection.AddSingleton(Mock.Of()); + serviceCollection.AddSingleton(Mock.Of()); + serviceCollection.AddSingleton(Mock.Of>()); + serviceCollection.AddSingleton(new MiddlewareConfiguration + { + Configuration = new System.Collections.Generic.Dictionary + { + { "init_ftSignaturCreationUnitIT", "[{\"Url\":\"https://faker\"}]" } + } + }); + + var bootstrapper = new QueueITBootstrapper(); + bootstrapper.ConfigureServices(serviceCollection); + + serviceCollection.BuildServiceProvider().GetRequiredService(); + } + } + +} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/QueueITStateTests.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/QueueITStateTests.cs new file mode 100644 index 000000000..b79a03592 --- /dev/null +++ b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/QueueITStateTests.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.Middleware.Contracts.Interfaces; +using fiskaltrust.Middleware.Contracts.Models; +using fiskaltrust.Middleware.Contracts.Repositories; +using fiskaltrust.Middleware.Localization.QueueIT.v2; +using fiskaltrust.storage.V0; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Newtonsoft.Json; +using Xunit; + +namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest +{ + public class QueueITStateTests + { + private static readonly Guid _queueID = new Guid(); + + private readonly ftQueue _queue = new ftQueue + { + ftQueueId = _queueID, + }; + + private readonly ftQueue _queueStarted = new ftQueue + { + ftQueueId = _queueID, + StartMoment = DateTime.UtcNow, + ftReceiptNumerator = 1 + }; + + private readonly ftQueue _queueStopped = new ftQueue + { + ftQueueId = _queueID, + StartMoment = DateTime.UtcNow, + StopMoment = DateTime.UtcNow + }; + + private IMarketSpecificSignProcessor GetSUT() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + serviceCollection.AddSingleton(Mock.Of(MockBehavior.Strict)); + serviceCollection.AddSingleton(Mock.Of()); + serviceCollection.AddSingleton(Mock.Of>(MockBehavior.Strict)); + serviceCollection.AddSingleton(Mock.Of(MockBehavior.Strict)); + serviceCollection.AddSingleton(new MiddlewareConfiguration()); + + var bootstrapper = new QueueITBootstrapper(); + bootstrapper.ConfigureServices(serviceCollection); + + return serviceCollection.BuildServiceProvider().GetRequiredService(); + } + + public static IEnumerable allNonInitialOperationReceipts() + { + foreach (var number in Enum.GetValues(typeof(ReceiptCases))) + { + if ((long) number == (long) ReceiptCases.InitialOperationReceipt0x4001) + { + continue; + } + + yield return new object[] { number }; + } + } + + public static IEnumerable allReceipts() + { + foreach (var number in Enum.GetValues(typeof(ReceiptCases))) + { + yield return new object[] { number }; + } + } + + [Fact] + public async Task DoNotAllowInitialOperationDuringInitializedState() + { + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "{{Guid.NewGuid()}}", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000000000 | (long) ReceiptCases.InitialOperationReceipt0x4001}}, + "ftReceiptCaseData": "", + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetSUT(); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + + receiptResponse.ftSignatures.Should().HaveCount(1); + receiptResponse.ftSignatures[0].Data.Should().Be($"The queue is already operational. It is not allowed to send another InitOperation Receipt"); + receiptResponse.ftState.Should().Be(0x4954_2000_EEEE_EEEE); + } + + [Theory] + [MemberData(nameof(allNonInitialOperationReceipts))] + public async Task AllNonInitialOperationReceiptCases_ShouldReturnDisabledMessage_IfQueueHasNotStarted(ReceiptCases receiptCase) + { + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "{{Guid.NewGuid()}}", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000000000 | (long) receiptCase}}, + "ftReceiptCaseData": "", + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetSUT(); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queue, new ftQueueItem { }); + + receiptResponse.ftSignatures.Should().BeEmpty(); + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0001); + + actionJournals.Should().HaveCount(1); + actionJournals[0].Message.Should().Be($"QueueId {_queue.ftQueueId} has not been activated yet."); + } + + [Theory] + [MemberData(nameof(allReceipts))] + public async Task AllReceiptCases_ShouldReturnDisabledMessage_IfQueueIsDeactivated(ReceiptCases receiptCase) + { + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "{{Guid.NewGuid()}}", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000000000 | (long) receiptCase}}, + "ftReceiptCaseData": "", + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetSUT(); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStopped, new ftQueueItem { }); + + receiptResponse.ftSignatures.Should().BeEmpty(); + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0001); + + actionJournals.Should().HaveCount(1); + actionJournals[0].Message.Should().Be($"QueueId {_queue.ftQueueId} has been disabled."); + } + } +} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/RequestCommandsTest/PosReceiptCommandTest.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/RequestCommandsTest/PosReceiptCommandTest.cs deleted file mode 100644 index 1bddb672e..000000000 --- a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/RequestCommandsTest/PosReceiptCommandTest.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1; -using fiskaltrust.storage.V0; -using System.Linq; -using Xunit; -using fiskaltrust.Middleware.Localization.QueueIT.RequestCommands; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.DependencyInjection; -using fiskaltrust.Middleware.Localization.QueueIT.Factories; -using FluentAssertions; -using Moq; -using fiskaltrust.Middleware.Localization.QueueIT.Services; -using fiskaltrust.Middleware.Contracts.Repositories; -using fiskaltrust.Middleware.Contracts.Constants; -using fiskaltrust.Middleware.Contracts.Interfaces; - -namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest -{ - public class PosReceiptCommandTest - { - - [Fact] - public async Task ExecuteAsync_RegisterInvoice_ValidResultAsync() - { - var request = new ReceiptRequest() - { - cbReceiptReference = "Reference007", - cbChargeItems = new[] - { - new ChargeItem() - { - Description = "Testitem1", - Amount = 9999.98m, - ftChargeItemCase = 0x4954000000000001, - Quantity= 2, - }, - new ChargeItem() - { - Description = "Testitem2", - Amount = 10, - ftChargeItemCase = 0x4954000000000002, - Quantity= 1, - }, - new ChargeItem() - { - Description = "Discount 22% vat", - Amount = -100, - ftChargeItemCase = 0x4954000000000023, - }, - }, - cbPayItems = new PayItem[] - { - new PayItem(){ - Description = "Cash", - Amount = 9909.98m, - ftPayItemCase = 0x4954000000000001 - } - } - }; - var inMemoryTestScu = new InMemoryTestScu(); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddStandardLoggers(LogLevel.Debug); - var desscdMock = new Mock(); - desscdMock.SetupGet( x => x.Instance).Returns(inMemoryTestScu); - - - var queueIt = new ftQueueIT() { CashBoxIdentification = "testserial", ftSignaturCreationUnitITId = Guid.NewGuid()}; - var configRepoMock = new Mock(); - configRepoMock.Setup(x => x.GetQueueITAsync(It.IsAny())).ReturnsAsync(queueIt); - - var queueRepoMock = new Mock(); - queueRepoMock.Setup(x => x.GetQueueAsync(It.IsAny())).ReturnsAsync(queueIt); - - var countrySettingsMock = new Mock(); - countrySettingsMock.Setup( x => x.CountrySpecificQueueRepository).Returns(queueRepoMock.Object); - - var posReceiptCommand = new PosReceiptCommand(Mock.Of(), Mock.Of>(), desscdMock.Object, new SignatureItemFactoryIT(), Mock.Of(), configRepoMock.Object, countrySettingsMock.Object); - - var queue = new ftQueue() { ftQueueId = Guid.NewGuid(), ftReceiptNumerator = 5 }; - var queueItem = new ftQueueItem() { ftQueueId = queue.ftQueueId, ftQueueItemId = Guid.NewGuid(), ftQueueRow = 7 }; - - var response = await posReceiptCommand.ExecuteAsync(queue, request, queueItem); - - var nrSig = response.ReceiptResponse.ftSignatures.Where(x => x.Caption == "").FirstOrDefault(); - var znrSig = response.ReceiptResponse.ftSignatures.Where(x => x.Caption == "").FirstOrDefault(); - var amntSig = response.ReceiptResponse.ftSignatures.Where(x => x.Caption == "").FirstOrDefault(); - var tsmpSig = response.ReceiptResponse.ftSignatures.Where(x => x.Caption == "").FirstOrDefault(); - - - znrSig.Data.Should().Be("0"); - nrSig.Data.Should().Be("245"); - amntSig.Data.Should().Be("9909,98"); - tsmpSig.Data.Should().Be("1999-01-01 00:00:01"); - - } - } -} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/SignProcessorITTests.cs b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/SignProcessorITTests.cs new file mode 100644 index 000000000..2b0cf06a3 --- /dev/null +++ b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/SignProcessorITTests.cs @@ -0,0 +1,528 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.Middleware.Contracts.Interfaces; +using fiskaltrust.Middleware.Contracts.Models; +using fiskaltrust.Middleware.Contracts.Repositories; +using fiskaltrust.Middleware.Localization.QueueIT.v2; +using fiskaltrust.storage.serialization.DE.V0; +using fiskaltrust.storage.V0; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Newtonsoft.Json; +using Xunit; + +namespace fiskaltrust.Middleware.Localization.QueueIT.UnitTest +{ + + public class SignProcessorITTests + { + private static readonly Guid _queueID = new Guid(); + + private readonly ftQueue _queue = new ftQueue + { + ftQueueId = _queueID, + }; + + private readonly ftQueue _queueStarted = new ftQueue + { + ftQueueId = _queueID, + StartMoment = DateTime.UtcNow, + ftReceiptNumerator = 1 + }; + + private readonly ftQueue _queueStopped = new ftQueue + { + ftQueueId = _queueID, + StartMoment = DateTime.UtcNow, + StopMoment = DateTime.UtcNow + }; + + private readonly ftQueueIT _queueIT = new ftQueueIT + { + ftQueueITId = _queueID, + ftSignaturCreationUnitITId = Guid.NewGuid(), + }; + + private readonly ftQueueIT _queueITSCUDeviceOutOfService = new ftQueueIT + { + ftQueueITId = _queueID, + ftSignaturCreationUnitITId = Guid.NewGuid(), + SSCDFailCount = 1, + SSCDFailMoment = DateTime.UtcNow, + SSCDFailQueueItemId = Guid.NewGuid() + }; + + + private IMarketSpecificSignProcessor GetSCUDeviceOutOfServiceSUT(ftQueue queue) => GetSUT(queue, _queueIT); + + private IMarketSpecificSignProcessor GetDefaultSUT(ftQueue queue, IITSSCD itSSCD = null) => GetSUT(queue, _queueIT, itSSCD); + + public static SignaturItem[] CreateFakeReceiptSignatures() + { + return POSReceiptSignatureData.CreateDocumentoCommercialeSignatures(new POSReceiptSignatureData + { + RTSerialNumber = "DEMORTDEVICE", + RTZNumber = 1, + RTDocNumber = 2, + RTDocMoment = DateTime.UtcNow, + RTDocType = "POSRECEIPT", + }).ToArray(); + } + + private IMarketSpecificSignProcessor GetSUT(ftQueue queue, ftQueueIT queueIT, IITSSCD itSSCD = null) + { + var middlewareQueueItemRepositoryMock = new Mock(); + + var configurationRepositoryMock = new Mock(); + configurationRepositoryMock.Setup(x => x.GetQueueAsync(_queue.ftQueueId)).ReturnsAsync(queue); + configurationRepositoryMock.Setup(x => x.GetQueueITAsync(_queue.ftQueueId)).ReturnsAsync(queueIT); + configurationRepositoryMock.Setup(x => x.GetSignaturCreationUnitITAsync(_queueIT.ftSignaturCreationUnitITId.Value)).ReturnsAsync(new ftSignaturCreationUnitIT + { + ftSignaturCreationUnitITId = _queueIT.ftSignaturCreationUnitITId.Value, + Url = "grpc://localhost:14300", + InfoJson = null + }); + + if (itSSCD == null) + { + var itSSCDMock = new Mock(); + itSSCDMock.Setup(x => x.ProcessReceiptAsync(It.IsAny())).ReturnsAsync((ProcessRequest request) => + { + request.ReceiptResponse.ftSignatures = CreateFakeReceiptSignatures(); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + }); + itSSCDMock.Setup(x => x.GetRTInfoAsync()).ReturnsAsync(new RTInfo()); + itSSCD = itSSCDMock.Object; + } + + var clientFactoryMock = new Mock>(); + clientFactoryMock.Setup(x => x.CreateClient(It.IsAny())).Returns(itSSCD); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + serviceCollection.AddSingleton(configurationRepositoryMock.Object); + serviceCollection.AddSingleton(Mock.Of()); + serviceCollection.AddSingleton(clientFactoryMock.Object); + serviceCollection.AddSingleton(middlewareQueueItemRepositoryMock.Object); + serviceCollection.AddSingleton(new MiddlewareConfiguration + { + Configuration = new Dictionary + { + { "init_ftSignaturCreationUnitIT", "[{\"Url\":\"grpc://localhost:14300\"}]" } + } + }); + + var bootstrapper = new QueueITBootstrapper(); + bootstrapper.ConfigureServices(serviceCollection); + + return serviceCollection.BuildServiceProvider().GetRequiredService(); + } + + public static IEnumerable rtHandledReceipts() + { + yield return new object[] { ReceiptCases.UnknownReceipt0x0000 }; + yield return new object[] { ReceiptCases.PointOfSaleReceipt0x0001 }; + yield return new object[] { ReceiptCases.Protocol0x0005 }; + } + + [Theory] + [MemberData(nameof(rtHandledReceipts))] + public async Task AllReceiptCases_ShouldContain_ZNumber_And_DocumentNumber_InReceiptIdentification(ReceiptCases receiptCase) + { + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "{{Guid.NewGuid()}}", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000000000 | (long) receiptCase}}, + "ftReceiptCaseData": "", + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetDefaultSUT(_queueStarted); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000); + receiptResponse.ftReceiptIdentification.Should().Be("ft1#0001-0002"); + } + + [Fact] + public async Task Process_InitialOperationReceipt() + { + var initOperationReceipt = $$""" +{ + "ftCashBoxId": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "INIT", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184539649, + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetDefaultSUT(_queue); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queue, new ftQueueItem { }); + + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000); + actionJournals.Should().HaveCount(1); + var notification = JsonConvert.DeserializeObject(actionJournals[0].DataJson); + notification.IsStartReceipt.Should().BeTrue(); + + receiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == 0x4954_2000_0001_1001); + } + + [Fact] + public async Task Process_OutOfOperationReceipt() + { + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "OutOfOperation", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184539650, + "ftReceiptCaseData": "", + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetDefaultSUT(_queueStarted); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000); + actionJournals.Should().HaveCount(1); + var notification = JsonConvert.DeserializeObject(actionJournals[0].DataJson); + notification.IsStopReceipt.Should().BeTrue(); + + receiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == 0x4954_2000_0001_1002); + } + + [Fact] + public async Task Process_ZeroReceipt() + { + var zeroReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Zero", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184531456, + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(zeroReceipt); + var sut = GetDefaultSUT(_queueStarted); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000, $"{receiptResponse.ftState:x}"); + actionJournals.Should().HaveCount(0); + } + + [Fact] + public async Task Process_ZeroReceipt_ShouldNeverFail() + { + var zeroReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Zero", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184531456, + "cbUser": "Admin" +} +"""; + var itSSCDMock = new Mock(); + itSSCDMock.Setup(x => x.ProcessReceiptAsync(It.IsAny())).ReturnsAsync((ProcessRequest request) => throw new Exception("So here we go no error")); + itSSCDMock.Setup(x => x.GetRTInfoAsync()).ReturnsAsync(() => throw new Exception("So here we go no error")); + + var receiptRequest = JsonConvert.DeserializeObject(zeroReceipt); + var sut = GetDefaultSUT(_queueStarted, itSSCDMock.Object); + + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + receiptResponse.ftState.Should().Be(0x4954_2000_EEEE_EEEE, $"{receiptResponse.ftState:x}"); + actionJournals.Should().HaveCount(0); + } + + [Fact] + public async Task Process_DailyClosingReceipt() + { + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Daily-Closing", + "cbReceiptMoment": "{{DateTime.UtcNow.ToString("o")}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184531473, + "cbUser": "Admin" +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetDefaultSUT(_queueStarted); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + + receiptResponse.ftReceiptIdentification.Should().Be("ft1#Z0001"); + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000); + actionJournals.Should().HaveCount(1); + actionJournals[0].Type.Should().Be(receiptRequest.ftReceiptCase.ToString("x")); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetDefaultSUT(_queueStarted); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + receiptResponse.ftSignatures.Should().HaveCountGreaterOrEqualTo(1); + receiptResponse.ftReceiptIdentification.Should().Be("ft1#0001-0002"); + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000); + actionJournals.Should().HaveCount(0); + } + + [Fact] + public async Task ProcessPosReceiptRefund_0x4954_2000_0002_0001() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var initOperationReceipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0005", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -2.0, + "Amount": -221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186751507, + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "ftChargeItemCase": 5283883447186751505, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -88, + "VATRate": 5, + "ftChargeItemCase": 5283883447186751506, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -90, + "VATRate": 4, + "ftChargeItemCase": 5283883447186751508, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186755604, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186759700, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186763796, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186767892, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186771988, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186784276, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -566 + } + ], + "ftReceiptCase": 5283883447184654337 +} +"""; + var receiptRequest = JsonConvert.DeserializeObject(initOperationReceipt); + var sut = GetDefaultSUT(_queueStarted); + var (receiptResponse, actionJournals) = await sut.ProcessAsync(receiptRequest, _queueStarted, new ftQueueItem { }); + receiptResponse.ftSignatures.Should().HaveCountGreaterOrEqualTo(1); + receiptResponse.ftState.Should().Be(0x4954_2000_0000_0000); + receiptResponse.ftReceiptIdentification.Should().Be("ft1#0001-0002"); + actionJournals.Should().HaveCount(0); + } + } +} diff --git a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/fiskaltrust.Middleware.Localization.QueueIT.UnitTest.csproj b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/fiskaltrust.Middleware.Localization.QueueIT.UnitTest.csproj index e07464145..d5d0af27b 100644 --- a/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/fiskaltrust.Middleware.Localization.QueueIT.UnitTest.csproj +++ b/queue/test/fiskaltrust.Middleware.Localization.QueueIT.UnitTest/fiskaltrust.Middleware.Localization.QueueIT.UnitTest.csproj @@ -1,17 +1,11 @@  - net461;net6 false + 11 - - - - - - @@ -21,11 +15,8 @@ - - - diff --git a/scu-it/Directory.Build.props b/scu-it/Directory.Build.props index 1acb803c0..1d3d45673 100644 --- a/scu-it/Directory.Build.props +++ b/scu-it/Directory.Build.props @@ -1,19 +1,20 @@ - - 1.3.0-local - 1.3.0.0 - 1.3.0.0 - fiskaltrust - fiskaltrust - Copyright 2022 - fiskaltrust signing - false - fiskaltrust - true - NU5104 - true - 11.0 - + + 1.3.0-local + 1.3.0.0 + 1.3.0.0 + fiskaltrust + fiskaltrust + Copyright 2022 + fiskaltrust signing + false + fiskaltrust + true + NU5104 + true + 11.0 + NU1901;NU1902;NU1903;NU1904 + diff --git a/scu-it/fiskaltrust.Middleware.SCU.IT.sln b/scu-it/fiskaltrust.Middleware.SCU.IT.sln index 0659a35f3..d7543ab54 100644 --- a/scu-it/fiskaltrust.Middleware.SCU.IT.sln +++ b/scu-it/fiskaltrust.Middleware.SCU.IT.sln @@ -4,8 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D3735F43-830E-4992-8663-7182B6970DA2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.Epson", "src\fiskaltrust.Middleware.SCU.IT.Epson\fiskaltrust.Middleware.SCU.IT.Epson.csproj", "{612776C5-9C63-4C00-8195-C9ECADD27F11}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D46180D0-C3B0-4544-8571-46FCF7783EE0}" EndProject @@ -15,16 +16,26 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Manual", "Manual", "{5B3E82 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.TestLauncher", "test\TestLauncher\fiskaltrust.Middleware.SCU.IT.TestLauncher.csproj", "{C8B07134-996B-4F14-A661-8327843F8089}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.CustomRTServer", "src\fiskaltrust.Middleware.SCU.IT.CustomRTServer\fiskaltrust.Middleware.SCU.IT.CustomRTServer.csproj", "{93EDC9D1-2E21-4F2A-B785-4AE81AF92A50}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.CustomRTPrinter", "src\fiskaltrust.Middleware.SCU.IT.CustomRTPrinter\fiskaltrust.Middleware.SCU.IT.CustomRTPrinter.csproj", "{9F015827-32AD-4C85-B35E-B912C5C04C07}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.Abstraction", "src\fiskaltrust.Middleware.SCU.IT.Abstraction\fiskaltrust.Middleware.SCU.IT.Abstraction.csproj", "{5198570C-6420-4ACC-A8CD-EC86987810A5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest", "test\fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest\fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest.csproj", "{77811328-6B61-4F31-BE0E-DD6C4D322F3F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter", "src\fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter\fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.csproj", "{BB286047-1A66-4CEF-9666-87D5645A1CFD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest", "test\fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest\fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest.csproj", "{8A91A975-2DE2-4D9D-9A0F-7EEE13034AE6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.AcceptanceTests", "test\fiskaltrust.Middleware.SCU.IT.AcceptanceTests\fiskaltrust.Middleware.SCU.IT.AcceptanceTests.csproj", "{B530EACC-2000-45E9-BE23-DFF022FA5883}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {612776C5-9C63-4C00-8195-C9ECADD27F11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {612776C5-9C63-4C00-8195-C9ECADD27F11}.Debug|Any CPU.Build.0 = Debug|Any CPU - {612776C5-9C63-4C00-8195-C9ECADD27F11}.Release|Any CPU.ActiveCfg = Release|Any CPU - {612776C5-9C63-4C00-8195-C9ECADD27F11}.Release|Any CPU.Build.0 = Release|Any CPU {94946668-08ED-4AF7-B331-1774A2E94C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {94946668-08ED-4AF7-B331-1774A2E94C99}.Debug|Any CPU.Build.0 = Debug|Any CPU {94946668-08ED-4AF7-B331-1774A2E94C99}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -33,15 +44,49 @@ Global {C8B07134-996B-4F14-A661-8327843F8089}.Debug|Any CPU.Build.0 = Debug|Any CPU {C8B07134-996B-4F14-A661-8327843F8089}.Release|Any CPU.ActiveCfg = Release|Any CPU {C8B07134-996B-4F14-A661-8327843F8089}.Release|Any CPU.Build.0 = Release|Any CPU + {93EDC9D1-2E21-4F2A-B785-4AE81AF92A50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93EDC9D1-2E21-4F2A-B785-4AE81AF92A50}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93EDC9D1-2E21-4F2A-B785-4AE81AF92A50}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93EDC9D1-2E21-4F2A-B785-4AE81AF92A50}.Release|Any CPU.Build.0 = Release|Any CPU + {9F015827-32AD-4C85-B35E-B912C5C04C07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F015827-32AD-4C85-B35E-B912C5C04C07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F015827-32AD-4C85-B35E-B912C5C04C07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F015827-32AD-4C85-B35E-B912C5C04C07}.Release|Any CPU.Build.0 = Release|Any CPU + {5198570C-6420-4ACC-A8CD-EC86987810A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5198570C-6420-4ACC-A8CD-EC86987810A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5198570C-6420-4ACC-A8CD-EC86987810A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5198570C-6420-4ACC-A8CD-EC86987810A5}.Release|Any CPU.Build.0 = Release|Any CPU + {77811328-6B61-4F31-BE0E-DD6C4D322F3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77811328-6B61-4F31-BE0E-DD6C4D322F3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77811328-6B61-4F31-BE0E-DD6C4D322F3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77811328-6B61-4F31-BE0E-DD6C4D322F3F}.Release|Any CPU.Build.0 = Release|Any CPU + {BB286047-1A66-4CEF-9666-87D5645A1CFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB286047-1A66-4CEF-9666-87D5645A1CFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB286047-1A66-4CEF-9666-87D5645A1CFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB286047-1A66-4CEF-9666-87D5645A1CFD}.Release|Any CPU.Build.0 = Release|Any CPU + {8A91A975-2DE2-4D9D-9A0F-7EEE13034AE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A91A975-2DE2-4D9D-9A0F-7EEE13034AE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A91A975-2DE2-4D9D-9A0F-7EEE13034AE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A91A975-2DE2-4D9D-9A0F-7EEE13034AE6}.Release|Any CPU.Build.0 = Release|Any CPU + {B530EACC-2000-45E9-BE23-DFF022FA5883}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B530EACC-2000-45E9-BE23-DFF022FA5883}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B530EACC-2000-45E9-BE23-DFF022FA5883}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B530EACC-2000-45E9-BE23-DFF022FA5883}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {612776C5-9C63-4C00-8195-C9ECADD27F11} = {D3735F43-830E-4992-8663-7182B6970DA2} {94946668-08ED-4AF7-B331-1774A2E94C99} = {D46180D0-C3B0-4544-8571-46FCF7783EE0} {5B3E8231-CFD7-4E36-A24B-929DE8BB67D8} = {D46180D0-C3B0-4544-8571-46FCF7783EE0} {C8B07134-996B-4F14-A661-8327843F8089} = {5B3E8231-CFD7-4E36-A24B-929DE8BB67D8} + {93EDC9D1-2E21-4F2A-B785-4AE81AF92A50} = {D3735F43-830E-4992-8663-7182B6970DA2} + {9F015827-32AD-4C85-B35E-B912C5C04C07} = {D3735F43-830E-4992-8663-7182B6970DA2} + {5198570C-6420-4ACC-A8CD-EC86987810A5} = {D3735F43-830E-4992-8663-7182B6970DA2} + {77811328-6B61-4F31-BE0E-DD6C4D322F3F} = {D46180D0-C3B0-4544-8571-46FCF7783EE0} + {BB286047-1A66-4CEF-9666-87D5645A1CFD} = {D3735F43-830E-4992-8663-7182B6970DA2} + {8A91A975-2DE2-4D9D-9A0F-7EEE13034AE6} = {D46180D0-C3B0-4544-8571-46FCF7783EE0} + {B530EACC-2000-45E9-BE23-DFF022FA5883} = {D46180D0-C3B0-4544-8571-46FCF7783EE0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1855DFED-93D8-4A05-B062-5958E4B3114E} diff --git a/scu-it/src/.DS_Store b/scu-it/src/.DS_Store new file mode 100644 index 000000000..aaa60ff16 Binary files /dev/null and b/scu-it/src/.DS_Store differ diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/Customer.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/Customer.cs new file mode 100644 index 000000000..d1b68e76a --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/Customer.cs @@ -0,0 +1,13 @@ +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public class Customer +{ + public string? CustomerName { get; set; } + public string? CustomerId { get; set; } + public string? CustomerType { get; set; } + public string? CustomerStreet { get; set; } + public string? CustomerZip { get; set; } + public string? CustomerCity { get; set; } + public string? CustomerCountry { get; set; } + public string? CustomerVATId { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ITConstants.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ITConstants.cs new file mode 100644 index 000000000..aa53bf439 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ITConstants.cs @@ -0,0 +1,15 @@ +using System.Globalization; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public static class ITConstants +{ + public const long BASE_STATE = 0x4954_2000_0000_0000; + + public static NumberFormatInfo CurrencyFormatter => new() + { + NumberDecimalSeparator = ",", + NumberGroupSeparator = "", + CurrencyDecimalDigits = 2 + }; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ITReceiptCases.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ITReceiptCases.cs new file mode 100644 index 000000000..9bda99b29 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ITReceiptCases.cs @@ -0,0 +1,35 @@ +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public enum ITReceiptCases : long +{ + UnknownReceipt0x0000 = 0x0000, + PointOfSaleReceipt0x0001 = 0x0001, + PaymentTransfer0x0002 = 0x0002, + PointOfSaleReceiptWithoutObligation0x0003 = 0x0003, + ECommerce0x0004 = 0x0004, + Protocol0x0005 = 0x0005, + + InvoiceUnknown0x1000 = 0x1000, + InvoiceB2C0x1001 = 0x1001, + InvoiceB2B0x1002 = 0x1002, + InvoiceB2G0x1003 = 0x1003, + + ZeroReceipt0x200 = 0x2000, + OneReceipt0x2001 = 0x2001, + ShiftClosing0x2010 = 0x2010, + DailyClosing0x2011 = 0x2011, + MonthlyClosing0x2012 = 0x2012, + YearlyClosing0x2013 = 0x2013, + + ProtocolUnspecified0x3000 = 0x3000, + ProtocolTechnicalEvent0x3001 = 0x3001, + ProtocolAccountingEvent0x3002 = 0x3002, + InternalUsageMaterialConsumption0x3003 = 0x3003, + Order0x3004 = 0x3004, + Reprint0x3010 = 0x3010, + + InitialOperationReceipt0x4001 = 0x4001, + OutOfOperationReceipt0x4002 = 0x4002, + InitSCUSwitch0x4011 = 0x4011, + FinishSCUSwitch0x4012 = 0x4012, +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/LegacySCU.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/LegacySCU.cs new file mode 100644 index 000000000..09d8d49a9 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/LegacySCU.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public abstract class LegacySCU + : IITSSCD +{ + public Task GetDeviceInfoAsync() => throw new NotImplementedException(); + public Task FiscalReceiptInvoiceAsync(FiscalReceiptInvoice request) => throw new NotImplementedException(); + public Task FiscalReceiptRefundAsync(FiscalReceiptRefund request) => throw new NotImplementedException(); + public Task ExecuteDailyClosingAsync(DailyClosingRequest request) => throw new NotImplementedException(); + public Task NonFiscalReceiptAsync(NonFiscalRequest request) => throw new NotImplementedException(); + public abstract Task ProcessReceiptAsync(ProcessRequest request); + public abstract Task GetRTInfoAsync(); + public abstract Task EchoAsync(ScuItEchoRequest request); +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/POSReceiptSignatureData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/POSReceiptSignatureData.cs new file mode 100644 index 000000000..d914caca6 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/POSReceiptSignatureData.cs @@ -0,0 +1,19 @@ +using System; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public class POSReceiptSignatureData +{ + public string RTSerialNumber { get; set; } = string.Empty; + public long RTZNumber { get; set; } + public long RTDocNumber { get; set; } + public DateTime RTDocMoment { get; set; } + public string RTDocType { get; set; } = string.Empty; + public string? RTCodiceLotteria { get; set; } + public string? RTCustomerID { get; set; } + public string? RTServerSHAMetadata { get; set; } + + public long? RTReferenceZNumber { get; set; } + public long? RTReferenceDocNumber { get; set; } + public DateTime? RTReferenceDocMoment { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ProcessResponseHelpers.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ProcessResponseHelpers.cs new file mode 100644 index 000000000..ae1525861 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ProcessResponseHelpers.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.ifPOS.v1; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public class ProcessResponseHelpers +{ + public static ProcessResponse CreateResponse(ReceiptResponse response, string? stateData, List signaturItems) + { + if (response.ftSignatures.Length > 0) + { + var list = new List(); + list.AddRange(response.ftSignatures); + list.AddRange(signaturItems); + response.ftSignatures = list.ToArray(); + } + else + { + response.ftSignatures = signaturItems.ToArray(); + } + response.ftStateData = stateData; + return new ProcessResponse + { + ReceiptResponse = response + }; + } + + public static ProcessResponse CreateResponse(ReceiptResponse response, List signaturItems) + { + if (response.ftSignatures.Length > 0) + { + var list = new List(); + list.AddRange(response.ftSignatures); + list.AddRange(signaturItems); + response.ftSignatures = list.ToArray(); + } + else + { + response.ftSignatures = signaturItems.ToArray(); + } + + return new ProcessResponse + { + ReceiptResponse = response + }; + } + +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ReceiptCaseHelper.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ReceiptCaseHelper.cs new file mode 100644 index 000000000..1c5173660 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ReceiptCaseHelper.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public static class ReceiptCaseHelper +{ + public static bool IsV2Receipt(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_F000_0000_0000) == 0x0000_2000_0000_0000; + + public static long GetReceiptCase(this ReceiptRequest request) => request.ftReceiptCase & 0x0000_0000_0000_FFFF; + + public static bool IsDailyClosing(this ReceiptRequest request) => (request.ftReceiptCase & 0x0000_0000_0000_FFFF) == (long) ITReceiptCases.DailyClosing0x2011; + + + public static bool IsReprint(this ReceiptRequest request) => (request.ftReceiptCase & 0x0000_0000_0000_FFFF) == (long) ITReceiptCases.Reprint0x3010; + + public static bool IsZeroReceipt(this ReceiptRequest request) => (request.ftReceiptCase & 0x0000_0000_0000_FFFF) == (long) ITReceiptCases.ZeroReceipt0x200; + + public static bool IsOutOfOperationReceipt(this ReceiptRequest request) => (request.ftReceiptCase & 0x0000_0000_0000_FFFF) == (long) ITReceiptCases.OutOfOperationReceipt0x4002; + + public static bool IsInitialOperationReceipt(this ReceiptRequest request) => (request.ftReceiptCase & 0x0000_0000_0000_FFFF) == (long) ITReceiptCases.InitialOperationReceipt0x4001; + + public static bool IsUsedFailed(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0001_0000) > 0x0000; + + public static bool IsLateSigning(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0001_0000) > 0x0000; + + public static bool IsGroupingRequest(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0800_0000) > 0x0000; + + public static bool IsTraining(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0002_0000) > 0x0000; + + public static bool IsVoid(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0004_0000) > 0x0000; + + public static bool IsVoid(this ChargeItem chargeItem) => (chargeItem.ftChargeItemCase & 0x0000_0000_0001_0000) > 0x0000; + + public static bool IsVoid(this PayItem payItem) => (payItem.ftPayItemCase & 0x0000_0000_0001_0000) > 0x0000; + + public static bool IsHandwritten(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0008_0000) > 0x0000; + + public static bool IsSmallBusinessReceipt(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0010_0000) > 0x0000; + + public static bool IsReceiverBusiness(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0020_0000) > 0x0000; + + public static bool IsReceiverKnown(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0040_0000) > 0x0000; + + public static bool IsSalesInForeignCountry(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0080_0000) > 0x0000; + + public static bool IsRefund(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_0100_0000) > 0x0000; + + public static bool IsRefund(this ChargeItem chargeItem) => (chargeItem.ftChargeItemCase & 0x0000_0000_0002_0000) > 0x0000; + + public static bool IsTip(this ChargeItem chargeItem) => (chargeItem.ftChargeItemCase & 0x0000_0000_0000_00F0) == 0x30; + + public static bool IsRefund(this PayItem payItem) => (payItem.ftPayItemCase & 0x0000_0000_0002_0000) > 0x0000; + + public static bool IsReceiptRequest(this ReceiptRequest receiptRequest) => (receiptRequest.ftReceiptCase & 0x0000_0000_8000_0000) > 0x0000; + public static Customer? GetCustomer(this ReceiptRequest receiptRequest) => GetValueOrNull(receiptRequest?.cbCustomer); + + private static T? GetValueOrNull(string? data) where T : class + { + if (string.IsNullOrEmpty(data)) + { + return null; + } + + try + { + return JsonConvert.DeserializeObject(data!); + } + catch (Exception) + { + return null; + } + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ReceiptResponseHelper.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ReceiptResponseHelper.cs new file mode 100644 index 000000000..ddbac9eeb --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/ReceiptResponseHelper.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; +using fiskaltrust.ifPOS.v1; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction +{ + public static class ReceiptResponseHelper + { + public static void SetReceiptResponseErrored(this ReceiptResponse receiptResponse, string errorMessage) + { + receiptResponse.ftState |= 0xEEEE_EEEE; + receiptResponse.ftSignatures = new List().ToArray(); + receiptResponse.AddSignatureItem(new SignaturItem + { + Caption = "FAILURE", + Data = errorMessage, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + }); + } + + public static void AddSignatureItem(this ReceiptResponse receiptResponse, SignaturItem signaturItem) + { + var data = receiptResponse.ftSignatures.ToList(); + data.Add(signaturItem); + receiptResponse.ftSignatures = data.ToArray(); + } + + public static bool HasFailed(this ReceiptResponse receiptRespons) => (receiptRespons.ftState & 0xFFFF_FFFF) == 0xEEEE_EEEE; + + public static SignaturItem? GetSignaturItem(this ReceiptResponse receiptResponse, SignatureTypesIT signatureTypesIT) => receiptResponse.ftSignatures.FirstOrDefault(x => (x.ftSignatureType & 0xFF) == (long) signatureTypesIT); + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/SignatureFactory.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/SignatureFactory.cs new file mode 100644 index 000000000..8144f04bc --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/SignatureFactory.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; + +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public static class SignatureFactory +{ + public static SignaturItem[] CreateInitialOperationSignatures() => new SignaturItem[] { }; + + public static SignaturItem[] CreateOutOfOperationSignatures() => new SignaturItem[] { }; + + public static SignaturItem[] CreateZeroReceiptSignatures() => new SignaturItem[] { }; + + public static SignaturItem[] CreateDailyClosingReceiptSignatures(long zRepNumber) + { + return new SignaturItem[] + { + new SignaturItem + { + Caption = "", + Data = zRepNumber.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber + }, + }; + } + + public static SignaturItem[] CreateVoucherSignatures(NonFiscalRequest nonFiscalRequest) + { + + var signs = new List(); + var cnt = nonFiscalRequest.NonFiscalPrints.Count; + for (var i = 0; i < cnt; i++) + { + var dat = nonFiscalRequest.NonFiscalPrints[i].Data; + if (dat == "***Voucher***") + { + var dat2 = i + 1 < cnt ? nonFiscalRequest.NonFiscalPrints[i + 1].Data : null; + var isAmount = decimal.TryParse(dat2, NumberStyles.Number, new CultureInfo("it-It", false), out var amnt); + if (!isAmount) + { + dat2 = i + 2 < cnt ? nonFiscalRequest.NonFiscalPrints[i + 2].Data : null; + isAmount = decimal.TryParse(dat2, NumberStyles.Number, new CultureInfo("it-It", false), out amnt); + } + if (isAmount) + { + signs.Add(new SignaturItem + { + Caption = "", + Data = Math.Abs(amnt).ToString(new NumberFormatInfo + { + NumberDecimalSeparator = ",", + NumberGroupSeparator = "", + CurrencyDecimalDigits = 2 + }), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE & (long) SignatureTypesIT.RTAmount + }); + } + } + } + return signs.ToArray(); + } + + public static List CreateDocumentoCommercialeSignatures(POSReceiptSignatureData data) + { + var signatureItems = new List() + { + new SignaturItem + { + Caption = "", + Data = data.RTSerialNumber, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE |(long) SignatureTypesIT.RTSerialNumber + }, + new SignaturItem + { + Caption = "", + Data = data.RTZNumber.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber + }, + new SignaturItem + { + Caption = "", + Data = data.RTDocNumber.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE |(long) SignatureTypesIT.RTDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = data.RTDocMoment.ToString("yyyy-MM-dd HH:mm:ss"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE |(long) SignatureTypesIT.RTDocumentMoment + }, + new SignaturItem + { + Caption = "", + Data = data.RTDocType, // TODO CoNVert + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE |(long) SignatureTypesIT.RTDocumentType + } + }; + + if (!string.IsNullOrEmpty(data.RTServerSHAMetadata)) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTServerSHAMetadata, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTServerShaMetadata + }); + } + + if (!string.IsNullOrEmpty(data.RTCodiceLotteria)) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTCodiceLotteria, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTLotteryID + }); + } + + if (!string.IsNullOrEmpty(data.RTCustomerID)) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTCustomerID, + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTCustomerID + }); + } + + if (data.RTReferenceZNumber.HasValue && data.RTReferenceZNumber > 0) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTReferenceZNumber.Value.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }); + } + + if (data.RTReferenceDocNumber.HasValue && data.RTReferenceDocNumber > 0) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTReferenceDocNumber.Value.ToString().PadLeft(4, '0'), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }); + } + + if (data.RTReferenceDocMoment.HasValue) + { + signatureItems.Add(new SignaturItem + { + Caption = "", + Data = data.RTReferenceDocMoment.Value.ToString("yyyy-MM-dd"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }); + } + return signatureItems; + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/SignatureTypesIT.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/SignatureTypesIT.cs new file mode 100644 index 000000000..26d252ac9 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/SignatureTypesIT.cs @@ -0,0 +1,20 @@ +namespace fiskaltrust.Middleware.SCU.IT.Abstraction; + +public enum SignatureTypesIT +{ + PosReceiptPrimarySignature = 0x01, + PosReceiptSecondarySignature = 0x02, + RTSerialNumber = 0x010, + RTZNumber = 0x11, + RTDocumentNumber = 0x12, + RTDocumentMoment = 0x13, + RTDocumentType = 0x14, + RTLotteryID = 0x15, + RTCustomerID = 0x16, + RTServerShaMetadata = 0x17, + RTAmount = 0x18, + + RTReferenceZNumber = 0x20, + RTReferenceDocumentNumber = 0x21, + RTReferenceDocumentMoment = 0x22 +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/fiskaltrust.Middleware.SCU.IT.Abstraction.csproj b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/fiskaltrust.Middleware.SCU.IT.Abstraction.csproj new file mode 100644 index 000000000..53b33f582 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Abstraction/fiskaltrust.Middleware.SCU.IT.Abstraction.csproj @@ -0,0 +1,29 @@ + + + + The fiskaltrust Middleware implementation of the Custom RT Printer SCU for Italy. + netstandard2.0;net461;net6 + $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage + enable + + + + + + + + + + + + + + + + + + + true + + + \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/CustomRTPrinter.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/CustomRTPrinter.cs new file mode 100644 index 000000000..eed14fda1 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/CustomRTPrinter.cs @@ -0,0 +1,41 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; +using Microsoft.Extensions.Logging; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTPrinter; + +#pragma warning disable + +#nullable enable +public sealed class CustomRTPrinter : IITSSCD +{ + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0, 1); + + public CustomRTPrinter(ILogger logger, CustomRTPrinterConfiguration configuration) + { + _logger = logger; + if (string.IsNullOrEmpty(configuration.DeviceUrl)) + { + throw new NullReferenceException("ServerUrl is not set."); + } + _httpClient = new HttpClient + { + BaseAddress = new Uri(configuration.DeviceUrl), + Timeout = TimeSpan.FromMilliseconds(configuration.ClientTimeoutMs) + }; + } + + public Task EchoAsync(ScuItEchoRequest request) => throw new NotImplementedException(); + public Task ExecuteDailyClosingAsync(DailyClosingRequest request) => throw new NotImplementedException(); + public Task FiscalReceiptInvoiceAsync(FiscalReceiptInvoice request) => throw new NotImplementedException(); + public Task FiscalReceiptRefundAsync(FiscalReceiptRefund request) => throw new NotImplementedException(); + public Task GetDeviceInfoAsync() => throw new NotImplementedException(); + public Task GetRTInfoAsync() => throw new NotImplementedException(); + public Task NonFiscalReceiptAsync(NonFiscalRequest request) => throw new NotImplementedException(); + public Task ProcessReceiptAsync(ProcessRequest request) => throw new NotImplementedException(); +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/CustomRTPrinterConfiguration.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/CustomRTPrinterConfiguration.cs new file mode 100644 index 000000000..b0b5bfc1d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/CustomRTPrinterConfiguration.cs @@ -0,0 +1,8 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTPrinter +{ + public class CustomRTPrinterConfiguration + { + public string? DeviceUrl { get; set; } + public double ClientTimeoutMs { get; internal set; } + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Directory.Build.props b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/Directory.Build.props similarity index 100% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Directory.Build.props rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/Directory.Build.props diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/ScuBootstrapper.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/ScuBootstrapper.cs new file mode 100644 index 000000000..c5ead3ea2 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/ScuBootstrapper.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTPrinter +{ + public class ScuBootstrapper : IMiddlewareBootstrapper + { + public Guid Id { get; set; } + public Dictionary Configuration { get; set; } = null!; + + public void ConfigureServices(IServiceCollection serviceCollection) + { + var configuration = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(Configuration)); + + _ = serviceCollection + .AddSingleton(configuration) + .AddScoped(); + } + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter.csproj b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter.csproj new file mode 100644 index 000000000..e3f4a6117 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter.csproj @@ -0,0 +1,29 @@ + + + + The fiskaltrust Middleware implementation of the Custom RT Printer SCU for Italy. + netstandard2.0;net461;net6 + $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage + enable + + + + + + + + + + + + + + + + + + + true + + + \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/version.json b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/version.json new file mode 100644 index 000000000..02e08d4e9 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTPrinter/version.json @@ -0,0 +1,6 @@ +{ + "version": "1.3.48-rc1", + "releaseBranches": [ + "^refs/tags/scu-it/customrtprinter/v\\d+(?:\\.\\d+)*(?:-.*)?$" + ] +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerClient.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerClient.cs new file mode 100644 index 000000000..aec7b8990 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerClient.cs @@ -0,0 +1,286 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel.Security; +using System.Text; +using System.Threading.Tasks; +using fiskaltrust.Middleware.SCU.IT.CustomRTServer; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +public class CustomRTServerClient +{ + private readonly HttpClient _httpClient; + private readonly string _password; + private readonly CustomRTServerConfiguration _customRTServerConfiguration; + private readonly ILogger _logger; + + public CustomRTServerClient(CustomRTServerConfiguration customRTServerConfiguration, ILogger logger) + { + if (string.IsNullOrEmpty(customRTServerConfiguration.ServerUrl)) + { + throw new NullReferenceException("ServerUrl is not set."); + } + + if (customRTServerConfiguration.DisabelSSLValidation) + { + var handler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true + }; + + _httpClient = new HttpClient(handler) + { + BaseAddress = new Uri(customRTServerConfiguration.ServerUrl), + Timeout = TimeSpan.FromMilliseconds(customRTServerConfiguration.RTServerHttpTimeoutInMs) + }; + } + else + { + _httpClient = new HttpClient() + { + BaseAddress = new Uri(customRTServerConfiguration.ServerUrl), + Timeout = TimeSpan.FromMilliseconds(customRTServerConfiguration.RTServerHttpTimeoutInMs) + }; + } + + if (!string.IsNullOrEmpty(customRTServerConfiguration.AccountMasterData)) + { + var accountMasterData = JsonConvert.DeserializeObject(customRTServerConfiguration.AccountMasterData); + _password = accountMasterData.AccountId.ToString(); + } + else + { + _password = customRTServerConfiguration.Password; + } + _customRTServerConfiguration = customRTServerConfiguration; + _logger = logger; + } + + public async Task GetDeviceMemStatusAsync() => await PerformCallToRTServerWithAdminAsync("/getDeviceMemStatus.php", JsonConvert.SerializeObject(new + { + data = new + { + type = "3" + } + })); + + public async Task GetDailyStatusArrayAsync() => await PerformCallToRTServerWithAdminAsync("/getDailyStatusArray.php", JsonConvert.SerializeObject(new + { + data = new { } + })); + + public async Task GetDailyStatusAsync(string cashuuid) + { + var request = new + { + data = new + { + cashuuid + } + }; + + return await PerformCallToRTServerAsync("/getDailyStatus.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + public async Task GetDailyOpenAsync(string cashuuid, DateTime dateTime) + { + var request = new + { + data = new + { + cashuuid, + dtime = dateTime.ToString("yyyy-MM-dd HH:mm:ss") + } + }; + + return await PerformCallToRTServerAsync("/getDailyOpen.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + public async Task InsertZDocumentAsync(string cashuuid, DateTime dateTime, long znum, string amount) + { + var request = new + { + data = new + { + cashuuid, + znum, + dtime = dateTime.ToString("yyyy-MM-dd HH:mm:ss"), + amount + } + }; + return await PerformCallToRTServerAsync("/insertZDocument.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + public async Task InsertFiscalDocumentAsync(string cashuuid, CommercialDocument commercialDocument) => await PerformCallToRTServerAsync("/insertFiscalDocument2.php", cashuuid, JsonConvert.SerializeObject(commercialDocument)); + + private static void ThrowExceptionForErrorCode(string endpoint, CustomRTDResponse data) + { + if (data.responseCode == 1201) + { + var message = $""" +Calling endpoint '{endpoint}' failed with error code {data.responseCode}. +Messagio: Reso/annulo: documento non travoto +Esempio: È stato indicato un documento di refierimento inesistente +Azione Corretiva: Verificare i dati insertiti e ripetere l'operazione. +"""; + throw new CustomRTServerCommunicationException(message, data.responseCode); + } + + if (data.responseCode == 1206) + { + var message = $""" +Calling endpoint '{endpoint}' failed with error code {data.responseCode}. +Messagio: Valore non valido +Esempio: Il valore del campo "amount" del metodo "insertFiscalDocument" o del metodo "insertFiscalDocument2" è negatiov o non numerico +Azione Corretiva: Verificare i dati insertiti e ripetere l'operazione. +"""; + throw new CustomRTServerCommunicationException(message, data.responseCode); + } + + if (data.responseCode != 0) + { + var message = $""" +Calling endpoint '{endpoint}' failed with error code {data.responseCode}. + +{data.responseDesc} +"""; + throw new CustomRTServerCommunicationException(message, data.responseCode); + } + } + + public async Task InsertFiscalDocumentArrayAsync(string cashuuid, List commercialDocuments) + { + var request = new + { + fiscalArray = commercialDocuments + }; + return await PerformCallToRTServerAsync("/insertFiscalDocumentArray.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + public async Task InsertCashRegisterAsync(string description, string shop, string name, string password, string cf) + { + var request = new + { + data = new + { + description, + shop, + name, + password, + cf + } + }; + return await PerformCallToRTServerWithAdminAsync("/insertCashRegister.php", JsonConvert.SerializeObject(request)); + } + + public async Task CancelCashRegisterAsync(string cashuuid, string cf) + { + var request = new + { + data = new + { + type = 1, + cf, + cashuuid + } + }; + return await PerformCallToRTServerAsync("/updateCashRegister.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + public async Task InsertFiscalDocumentLotteryAsync(string cashuuid, FDocumentLottery fiscalData, QrCodeData qrCodeData) + { + var request = new + { + fiscalData, + qrCodeData + }; + return await PerformCallToRTServerAsync("/insertFiscalDocumentLottery.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + public async Task InsertFiscalDocumentArrayLotteryAsync(string cashuuid, List commercialDocuments) + { + var request = new + { + fiscalArray = commercialDocuments + }; + return await PerformCallToRTServerAsync("/insertFiscalDocumentArrayLottery.php", cashuuid, JsonConvert.SerializeObject(request)); + } + + private async Task PerformCallToRTServerAsync(string endpoint, string cashuuid, string payload) where TResponse : CustomRTDResponse + { + if (string.IsNullOrEmpty(_password)) + { + return await PerformCallToRTServerWithAdminAsync(endpoint, payload); + } + + var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint) + { + Content = new StringContent(payload) + }; + var authHeader = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{cashuuid}:{_password}")); + requestMessage.Headers.Add("Authorization", $"Basic {authHeader}"); + var result = await _httpClient.SendAsync(requestMessage); + var resultContent = await result.Content.ReadAsStringAsync(); + if (result.IsSuccessStatusCode) + { + var data = JsonConvert.DeserializeObject(resultContent); + if (data.responseCode != 0) + { + #pragma warning disable + try + { + ThrowExceptionForErrorCode(endpoint, data); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Calling endpoint '{endpoint}' failed with error code {data.responseCode}. {data.responseDesc}"); + if(!_customRTServerConfiguration.IgnoreRTServerErrors) + { + throw; + } + } + } + return data; + } + else + { + throw new Exception($"Something went wrong while communicating with the RT Server. Statuscode: {result.StatusCode}. Reasonphrase: {result.ReasonPhrase}. Content: {resultContent}."); + } + } + + private async Task PerformCallToRTServerWithAdminAsync(string endpoint, string payload) where TResponse : CustomRTDResponse + { + var authHeader = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_customRTServerConfiguration.Username}:{_customRTServerConfiguration.Password}")); + var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint) + { + Content = new StringContent(payload) + }; + requestMessage.Headers.Add("Authorization", $"Basic {authHeader}"); + var result = await _httpClient.SendAsync(requestMessage); + var resultContent = await result.Content.ReadAsStringAsync(); + if (result.IsSuccessStatusCode) + { + var data = JsonConvert.DeserializeObject(resultContent); + if (data.responseCode != 0) + { + try + { + ThrowExceptionForErrorCode(endpoint, data); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Calling endpoint '{endpoint}' failed with error code {data.responseCode}. {data.responseDesc}"); + } + } + return data; + } + else + { + throw new Exception($"Something went wrong while communicating with the RT Server. Statuscode: {result.StatusCode}. Reasonphrase: {result.ReasonPhrase}. Content: {resultContent}."); + } + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerCommunicationException.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerCommunicationException.cs new file mode 100644 index 000000000..8e3733bf8 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerCommunicationException.cs @@ -0,0 +1,17 @@ +using System; +using System.Runtime.Serialization; + +[Serializable] +internal class CustomRTServerCommunicationException : Exception +{ + public int CustomRTServerErrorCode { get; } + + public CustomRTServerCommunicationException(string message, int errorCode) : base(message) + { + CustomRTServerErrorCode = errorCode; + } + + protected CustomRTServerCommunicationException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerCommunicationQueue.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerCommunicationQueue.cs new file mode 100644 index 000000000..a89ca9b99 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerCommunicationQueue.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; +#pragma warning disable + +public class CustomRTServerCommunicationQueue : IDisposable +{ + private readonly Dictionary> _receiptQueue = new Dictionary>(); + private readonly Guid _id; + private readonly CustomRTServerClient _client; + private readonly ILogger _logger; + private readonly CustomRTServerConfiguration _customRTServerConfiguration; + + private string _scuCacheFolder; + private string _documentsPath; + + private bool _requestCancellation = false; + private bool _processingReceipts = false; + + public CustomRTServerCommunicationQueue(Guid id, CustomRTServerClient client, ILogger logger, CustomRTServerConfiguration customRTServerConfiguration) + { + _id = id; + _client = client; + _logger = logger; + _customRTServerConfiguration = customRTServerConfiguration; + + if (!string.IsNullOrEmpty(customRTServerConfiguration.ServiceFolder)) + { + _scuCacheFolder = customRTServerConfiguration.ServiceFolder!; + } + if (string.IsNullOrEmpty(_scuCacheFolder)) + { + _scuCacheFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + } + + _documentsPath = Path.Combine(_scuCacheFolder, "customrtservercache", id.ToString()); + if (!string.IsNullOrEmpty(customRTServerConfiguration.CacheDirectory)) + { + _documentsPath = customRTServerConfiguration.CacheDirectory; + } + if (!Directory.Exists(_documentsPath)) + { + Directory.CreateDirectory(_documentsPath); + } + + _ = Task.Run(ProcessReceiptsInBackground); + } + + public async Task EnqueueDocument(string cashuuid, CommercialDocument commercialDocument, long zRepNumber, long docNumber) + { + if (_customRTServerConfiguration.SendReceiptsSync) + { + await _client.InsertFiscalDocumentAsync(cashuuid, commercialDocument); + + } + else + { + if (!Directory.Exists(Path.Combine(_documentsPath, cashuuid))) + { + Directory.CreateDirectory(Path.Combine(_documentsPath, cashuuid)); + } + File.WriteAllText(Path.Combine(_documentsPath, cashuuid, $"{DateTime.UtcNow.Ticks}__{zRepNumber.ToString().PadLeft(4, '0')}-{docNumber.ToString().PadLeft(4, '0')}_commercialdocument.json"), JsonConvert.SerializeObject(commercialDocument)); + } + } + + + public async Task ProcessReceiptsInBackground() + { + while (true) + { + _processingReceipts = true; + if (_requestCancellation) + { + _processingReceipts = false; + return; + } + + try + { + foreach (var directory in Directory.GetDirectories(_documentsPath)) + { + var cashuuid = Path.GetFileName(directory); + foreach (var document in Directory.GetFiles(directory, "*_commercialdocument.json").OrderBy(x => x)) + { + if (_requestCancellation) + { + _processingReceipts = false; + return; + } + + var fileName = Path.GetFileNameWithoutExtension(document); + await _client.InsertFiscalDocumentAsync(cashuuid, JsonConvert.DeserializeObject(File.ReadAllText(document))); + File.Delete(document); + } + } + + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed tro transmit receipt..."); + } + finally + { + await Task.Delay(2000); + } + } + } + + public long GetCountOfDocumentsForInCache() + { + var count = 0; + foreach (var directory in Directory.GetDirectories(_documentsPath)) + { + count += Directory.GetFiles(directory, $"*_commercialdocument.json").Length; + } + return count; + } + + public long GetCountOfDocumentsForInCache(string cashuuid) + { + if (!Directory.Exists(Path.Combine(_documentsPath, cashuuid))) + { + return 0; + } + return Directory.GetFiles(Path.Combine(_documentsPath, cashuuid), $"*_commercialdocument.json")?.Length ?? 0; + } + + public async Task ProcessAllReceipts(string cashuuid) + { + _requestCancellation = true; + while (_processingReceipts) + { + await Task.Delay(10); + } + try + { + if (!Directory.Exists(Path.Combine(_documentsPath, cashuuid))) + { + return; + } + + foreach (var document in Directory.GetFiles(Path.Combine(_documentsPath, cashuuid), $"*_commercialdocument.json").OrderBy(x => x)) + { + await _client.InsertFiscalDocumentAsync(cashuuid, JsonConvert.DeserializeObject(File.ReadAllText(document))); + File.Delete(document); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed tro transmit receipt..."); + throw; + } + finally + { + _requestCancellation = false; + Task.Run(() => ProcessReceiptsInBackground()); + } + } + + public void Dispose() + { + _requestCancellation = true; + _logger.LogInformation("Stopping to process receipts in background for scu {scuid}. {amountofdocuments} documents left.", _id, GetCountOfDocumentsForInCache()); + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerConfiguration.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerConfiguration.cs new file mode 100644 index 000000000..e1a2a271e --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerConfiguration.cs @@ -0,0 +1,37 @@ +using System; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer +{ + public class CustomRTServerConfiguration + { + public string? ServerUrl { get; set; } + public string AccountMasterData { get; set; } = string.Empty; + public string Username { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public bool SendReceiptsSync { get; set; } + public bool IgnoreRTServerErrors { get; set; } = true; + public int RTServerHttpTimeoutInMs { get; set; } = 5000; + public bool DisabelSSLValidation { get; set; } + public string? ServiceFolder { get; set; } + public string? CacheDirectory { get; set; } + } + + public class AccountMasterData + { + public Guid AccountId { get; set; } + + public string? AccountName { get; set; } + + public string? Street { get; set; } + + public string? Zip { get; set; } + + public string? City { get; set; } + + public string? Country { get; set; } + + public string? TaxId { get; set; } + + public string? VatId { get; set; } + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerMapping.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerMapping.cs new file mode 100644 index 000000000..6e1329ed0 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerMapping.cs @@ -0,0 +1,485 @@ +using System.Collections.Generic; +using System; +using fiskaltrust.ifPOS.v1; +using System.Linq; +using Newtonsoft.Json; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using fiskaltrust.Middleware.SCU.IT.CustomRTServer.Models; +using System.Globalization; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +#pragma warning disable + +public static class CustomRTServerMapping +{ + public static (CommercialDocument commercialDocument, FDocument fiscalDocument) CreateAnnuloDocument(ReceiptRequest receiptRequest, QueueIdentification queueIdentification, ReceiptResponse receiptResponse) + { + var referenceZNumber = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceZNumber)?.Data; + var referenceDocNumber = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentNumber)?.Data; + var referenceDateTime = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentMoment)?.Data; + string? refCashUuid = receiptResponse.ftCashBoxIdentification; + if (string.IsNullOrEmpty(referenceZNumber) || string.IsNullOrEmpty(referenceDocNumber) || string.IsNullOrEmpty(referenceDateTime)) + { + referenceZNumber = "-1"; + referenceDocNumber = "-1"; + referenceDateTime = receiptRequest.cbReceiptMoment.ToString("yyyy-MM-dd HH:mm:ss"); + refCashUuid = "ND"; + } + (var totalAmount, var vatAmount, var items) = GenerateItemDataForReceiptRequest(receiptRequest, queueIdentification.LastZNumber + 1, queueIdentification.LastDocNumber + 1); + var fiscalDocument = new FDocument + { + document = new DocumentData + { + cashuuid = queueIdentification.CashUuId, + doctype = 5, + dtime = receiptRequest.cbReceiptMoment.ToString("yyyy-MM-dd HH:mm:ss"), + docnumber = queueIdentification.LastDocNumber + 1, + docznumber = queueIdentification.LastZNumber + 1, + amount = ConvertToFullAmountInt(totalAmount), + fiscalcode = "", + vatcode = "", + fiscaloperator = "", + businessname = null, + prevSignature = queueIdentification.LastSignature, + grandTotal = queueIdentification.CurrentGrandTotal, + referenceClosurenumber = long.Parse(referenceZNumber), + referenceDocnumber = long.Parse(referenceDocNumber), + referenceDtime = DateTime.Parse(referenceDateTime).ToString("yyyy-MM-dd 00:00:00"), + referenceCashuuid = refCashUuid + }, + items = items, + taxs = GenerateTaxDataForReceiptRequest(receiptRequest) + }; + var json = JsonConvert.SerializeObject(fiscalDocument); + var qrCodeData = GenerateQRCodeData(json, queueIdentification.CashHmacKey); + var commercialDocument = new CommercialDocument + { + fiscalData = json, + qrData = qrCodeData, + }; + + + return (commercialDocument, fiscalDocument); + } + + public static (CommercialDocument commercialDocument, FDocument fiscalDocument) CreateResoDocument(ReceiptRequest receiptRequest, QueueIdentification queueIdentification, ReceiptResponse receiptResponse) + { + var referenceZNumber = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceZNumber)?.Data; + var referenceDocNumber = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentNumber)?.Data; + var referenceDateTime = receiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentMoment)?.Data; + var refCashUuid = receiptResponse.ftCashBoxIdentification; + if (string.IsNullOrEmpty(referenceZNumber) || string.IsNullOrEmpty(referenceDocNumber) || string.IsNullOrEmpty(referenceDateTime)) + { + referenceZNumber = "0"; + referenceDocNumber = "0"; + referenceDateTime = receiptRequest.cbReceiptMoment.ToString("yyyy-MM-dd HH:mm:ss"); + refCashUuid = "ND"; + } + (var totalAmount, var vatAmount, var items) = GenerateItemDataForReceiptRequest(receiptRequest, queueIdentification.LastZNumber + 1, queueIdentification.LastDocNumber + 1); + + var fiscalDocument = new FDocument + { + document = new DocumentData + { + cashuuid = queueIdentification.CashUuId, + doctype = 3, + dtime = receiptRequest.cbReceiptMoment.ToString("yyyy-MM-dd HH:mm:ss"), + docnumber = queueIdentification.LastDocNumber + 1, + docznumber = queueIdentification.LastZNumber + 1, + amount = ConvertToFullAmountInt(totalAmount), + fiscalcode = "", + vatcode = "", + fiscaloperator = "", + businessname = null, + prevSignature = queueIdentification.LastSignature, + grandTotal = queueIdentification.CurrentGrandTotal, + referenceClosurenumber = long.Parse(referenceZNumber), + referenceDocnumber = long.Parse(referenceDocNumber), + referenceDtime = DateTime.Parse(referenceDateTime).ToString("yyyy-MM-dd 00:00:00"), + referenceCashuuid = refCashUuid + }, + items = items, + taxs = GenerateTaxDataForReceiptRequest(receiptRequest) + }; + var json = JsonConvert.SerializeObject(fiscalDocument); + var qrCodeData = GenerateQRCodeData(json, queueIdentification.CashHmacKey); + var commercialDocument = new CommercialDocument + { + fiscalData = json, + qrData = qrCodeData, + }; + +#pragma warning disable + var data = JsonConvert.SerializeObject(fiscalDocument); + return (commercialDocument, fiscalDocument); + } + + public static (CommercialDocument commercialDocument, FDocument fiscalDocument) GenerateFiscalDocument(ReceiptRequest receiptRequest, QueueIdentification queueIdentification) => GenerateFiscalDocument(receiptRequest, queueIdentification, 1); + + public static (CommercialDocument commercialDocument, FDocument fiscalDocument) GenerateFiscalDocument(ReceiptRequest receiptRequest, QueueIdentification queueIdentification, int docType) + { + (var totalAmount, var vatAmount, var items) = GenerateItemDataForReceiptRequest(receiptRequest, queueIdentification.LastZNumber + 1, queueIdentification.LastDocNumber + 1); + var fiscalDocument = new FDocument + { + document = new DocumentData + { + cashuuid = queueIdentification.CashUuId, + doctype = docType, + dtime = receiptRequest.cbReceiptMoment.ToString("yyyy-MM-dd HH:mm:ss"), + docnumber = queueIdentification.LastDocNumber + 1, + docznumber = queueIdentification.LastZNumber + 1, + amount = ConvertToFullAmountInt(totalAmount), + fiscalcode = "", + vatcode = "", + fiscaloperator = "", + businessname = null, + prevSignature = queueIdentification.LastSignature, + grandTotal = queueIdentification.CurrentGrandTotal, + referenceClosurenumber = -1, + referenceDocnumber = -1, + referenceDtime = null, + }, + items = items, + taxs = GenerateTaxDataForReceiptRequest(receiptRequest) + }; + var json = JsonConvert.SerializeObject(fiscalDocument); + var qrCodeData = GenerateQRCodeData(json, queueIdentification.CashHmacKey); + var commercialDocument = new CommercialDocument + { + fiscalData = json, + qrData = qrCodeData, + }; + +#pragma warning disable + var data = JsonConvert.SerializeObject(fiscalDocument); + + return (commercialDocument, fiscalDocument); + } + + public static QrCodeData GenerateQRCodeData(string data, string key) + { + var qrCode = new QrCodeData + { + shaMetadata = GlobalTools.GetSHA256(data) + }; + qrCode.signature = GlobalTools.CreateHMAC(Convert.FromBase64String(key), qrCode.shaMetadata); + return qrCode; + } + + public static bool InverseAmount(ReceiptRequest receiptRequest, ChargeItem chargeItem) => receiptRequest.IsRefund() || receiptRequest.IsVoid() || chargeItem.IsRefund() || chargeItem.IsVoid(); + + public static bool InverseAmount(ReceiptRequest receiptRequest, PayItem payItem) => receiptRequest.IsRefund() || receiptRequest.IsVoid() || payItem.IsRefund() || payItem.IsVoid(); + + public static (decimal totalAmount, decimal vatAmount, List) GenerateItemDataForReceiptRequest(ReceiptRequest receiptRequest, long zNumber, long receiptNumber) + { + var items = new List(); + var totalAmount = 0m; + var totalVatAmount = 0m; + foreach (var chargeItem in receiptRequest.cbChargeItems) + { + var amount = GetGrossAmount(receiptRequest, chargeItem); + var vatAmount = GetVATAmount(receiptRequest, chargeItem); + totalAmount += amount; + totalVatAmount += vatAmount; + items.Add(new DocumentItemData + { + type = GetTypeForChargeItem(chargeItem), + description = GenerateChargeItemCaseDescription(receiptRequest, chargeItem), + amount = ConvertToFullAmount(amount), + quantity = ConvertTo1000FullAmount(GetQuantity(chargeItem)), + unitprice = ConvertToFullAmount(amount / GetQuantity(chargeItem)), + vatvalue = ConvertToFullAmount(chargeItem.VATRate), + paymentid = "", + plu = "", + department = "", + vatcode = GetVatCodeForChargeItemCase(chargeItem.ftChargeItemCase) + }); + } + items.Add(new DocumentItemData + { + type = DocumentItemDataTaypes.DESCRITTIVA, + description = $"TOTALE COMPLESSIVO {ConvertToString(totalAmount)}", + amount = ConvertToFullAmount(totalAmount), + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + items.Add(new DocumentItemData + { + type = DocumentItemDataTaypes.DESCRITTIVA, + description = $"DI CUI IVA {ConvertToString(totalVatAmount)}", + amount = ConvertToFullAmount(totalVatAmount), + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + + foreach (var payitem in receiptRequest.cbPayItems) + { + items.Add(new DocumentItemData + { + type = GetTypeForPayItem(payitem), + description = GeneratePayItemCaseDescription(payitem), + amount = ConvertToFullAmount(GetPayItemAmount(receiptRequest, payitem)), + quantity = ConvertTo1000FullAmount(payitem.Quantity), + unitprice = "", + vatvalue = "", + paymentid = GetPaymentIdForPayItem(payitem), + plu = "", + department = "" + }); + items.Add(new DocumentItemData + { + type = DocumentItemDataTaypes.DESCRITTIVA, + description = payitem.Description, + amount = ConvertToFullAmount(GetPayItemAmount(receiptRequest, payitem)), + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + } + var payedAmount = receiptRequest.cbPayItems.Where(x => !IsScontoAPagare(x)).Sum(x => GetPayItemAmount(receiptRequest, x)); + items.Add(new DocumentItemData + { + type = DocumentItemDataTaypes.PAGAMENTO, + description = $"NON RISCOSSO 0,00", + amount = "0", + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + items.Add(new DocumentItemData + { + type = DocumentItemDataTaypes.PAGAMENTO, + description = $"RESTO 0,00", + amount = "0", + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + if (receiptRequest.cbPayItems.Count(x => IsScontoAPagare(x)) == 0) + { + items.Add(new DocumentItemData + { + type = DocumentItemDataTaypes.PAGAMENTO, + description = $"SCONTO A PAGARE 0,00", + amount = "0", + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + } + items.Add(new DocumentItemData + { + type = "97", + description = $"IMPORTO PAGATO {ConvertToString(payedAmount)}", + amount = ConvertToFullAmount(payedAmount), + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + items.Add(new DocumentItemData + { + type = "97", + description = $"{receiptRequest.cbReceiptMoment:dd/MM/yyyy HH:mm:ss} DOC.N.{zNumber.ToString().PadLeft(4, '0')}-{receiptNumber.ToString().PadLeft(4, '0')}", + amount = "", + quantity = ConvertTo1000FullAmount(1), + unitprice = "", + vatvalue = "", + paymentid = "", + plu = "", + department = "" + }); + return (totalAmount, totalVatAmount, items); + } + + public static string GetTypeForChargeItem(ChargeItem chargeItem) => chargeItem.ftChargeItemCase switch + { + _ => DocumentItemDataTaypes.VENDITA, + }; + + public static string GetTypeForPayItem(PayItem payItem) => ((long) payItem.ftPayItemCase & 0xFF) switch + { + _ => DocumentItemDataTaypes.PAGAMENTO + }; + + public static bool IsScontoAPagare(PayItem payItem) => ((long) payItem.ftPayItemCase & 0xFF) switch + { + 0x06 => true, + _ => false + }; + + public static string GetPaymentIdForPayItem(PayItem payItem) => ((long) payItem.ftPayItemCase & 0xFF) switch + { + 0x00 => DocumentItemPaymentIds.CONTANTE, + 0x01 => DocumentItemPaymentIds.CONTANTE, + 0x02 => DocumentItemPaymentIds.CONTANTE, + 0x03 => DocumentItemPaymentIds.CONTANTE, + 0x04 => DocumentItemPaymentIds.ELETTRONICO, + 0x05 => DocumentItemPaymentIds.ELETTRONICO, + 0x06 => DocumentItemPaymentIds.SCONTO_A_PAGARE, + 0x07 => DocumentItemPaymentIds.ELETTRONICO, + 0x08 => DocumentItemPaymentIds.SCONTO_A_PAGARE, + 0x09 => DocumentItemPaymentIds.ELETTRONICO, + 0x0A => DocumentItemPaymentIds.ELETTRONICO, + 0x0B => DocumentItemPaymentIds.ELETTRONICO, + 0x0C => DocumentItemPaymentIds.CONTANTE, + _ => DocumentItemPaymentIds.CONTANTE + }; + + public static string GetDescriptionForPayItem(PayItem payItem) => ((long) payItem.ftPayItemCase & 0xFF) switch + { + 0x00 => "PAGAMENTO CONTANTE", + 0x01 => "PAGAMENTO CONTANTE", + 0x02 => "PAGAMENTO CONTANTE", + 0x03 => "PAGAMENTO CONTANTE", + 0x04 => "PAGAMENTO ELETTRONICO", + 0x05 => "PAGAMENTO ELETTRONICO", + 0x06 => "SCONTO A PAGARE", + 0x07 => "PAGAMENTO ELETTRONICO", + 0x08 => "SCONTO A PAGARE", + 0x09 => "PAGAMENTO ELETTRONICO", + 0x0A => "PAGAMENTO ELETTRONICO", + 0x0B => "PAGAMENTO ELETTRONICO", + 0x0C => "PAGAMENTO CONTANTE", + _ => "PAGAMENTO CONTANTE" + }; + + public static string ConvertTo1000FullAmount(decimal value) => ((int) (value * 1000)).ToString(); + + public static string ConvertToFullAmount(decimal value) => ((int) (value * 100)).ToString(); + + public static int ConvertToFullAmountInt(decimal value) => (int) (value * 100); + + public static List GenerateTaxDataForReceiptRequest(ReceiptRequest receiptRequest) + { + var items = new List(); + var groupedItems = receiptRequest.cbChargeItems.GroupBy(x => (GetVatCodeForChargeItemCase(x.ftChargeItemCase), x.VATRate)); + foreach (var chargeItems in groupedItems) + { + var tax = 0.0m; + var gross = 0.0m; + foreach (var chargeItem in chargeItems) + { + tax += GetVATAmount(receiptRequest, chargeItem); + gross += GetGrossAmount(receiptRequest, chargeItem); + } + + var taxData = new DocumentTaxData + { + gross = ConvertToFullAmountInt(gross), + tax = ConvertToFullAmountInt(tax), + vatvalue = ConvertToFullAmountInt(chargeItems.Key.VATRate), + vatcode = chargeItems.Key.Item1, + additional_tax_data = new List() + }; + items.Add(taxData); + } + return items; + } + + public static string GetVatCodeForChargeItemCase(long chargeItemCase) => chargeItemCase switch + { + 0x4954_2000_0020_0013 => "", + 0x4954_2000_0020_0011 => "", + 0x4954_2000_0020_0012 => "", + 0x4954_2000_0020_0014 => "", + 0x4954_2000_0020_1014 => "N3", + 0x4954_2000_0020_2014 => "N2", + 0x4954_2000_0020_3014 => "N4", + 0x4954_2000_0020_4014 => "N5", + 0x4954_2000_0020_5014 => "N6", + 0x4954_2000_0020_8014 => "N1", + 0x4954_2000_0020_7014 => "VI", + 0x4954_2000_0000_8038 => "N1", + 0x4954_2000_0022_0013 => "", + 0x4954_2000_0022_0011 => "", + 0x4954_2000_0022_0012 => "", + 0x4954_2000_0022_0014 => "", + 0x4954_2000_0022_1014 => "N3", + 0x4954_2000_0022_2014 => "N2", + 0x4954_2000_0022_3014 => "N4", + 0x4954_2000_0022_4014 => "N5", + 0x4954_2000_0022_5014 => "N6", + 0x4954_2000_0022_8014 => "N1", + 0x4954_2000_0022_7014 => "VI", + 0x4954_2000_0021_0013 => "", + 0x4954_2000_0021_0011 => "", + 0x4954_2000_0021_0012 => "", + 0x4954_2000_0021_0014 => "", + _ => "" + }; + + public static string GeneratePayItemCaseDescription(PayItem payItem) + { + var payItemDesc = GetDescriptionForPayItem(payItem); + var payItemAmount = ConvertToString(payItem.Amount); + var lengthRest = 40 - payItemDesc.Length + payItemAmount.Length; + return $"{payItemDesc.PadRight(lengthRest, ' ')}{payItemAmount}"; + } + + public static string GenerateChargeItemCaseDescription(ReceiptRequest receiptRequest, ChargeItem chargeItem) + { + var chargeItemVatRate = ""; + if (chargeItem.VATRate > 0) + { + chargeItemVatRate = $"{chargeItem.VATRate}%"; + } + else + { + var nature = GetVatCodeForChargeItemCase(chargeItem.ftChargeItemCase); + chargeItemVatRate = $"{nature}*"; + } + var chargeitemDesc = chargeItem.Description.TruncateLongString(20); + var charegItemPrice = ConvertToString(GetGrossAmount(receiptRequest, chargeItem)); + return $"{chargeitemDesc.PadRight(20, ' ')}{chargeItemVatRate.PadLeft(6, ' ')}{charegItemPrice.PadLeft(14, ' ')}"; + } + + public static string ConvertToString(decimal value) + { + var info = CultureInfo.InvariantCulture.Clone() as CultureInfo; + info.NumberFormat.NumberDecimalSeparator = ","; + + return value.ToString($"F2", info); + } + + public static string TruncateLongString(this string str, int maxLength) + { + if (string.IsNullOrEmpty(str)) + return str; + + return str.Substring(0, Math.Min(str.Length, maxLength)); + } + + public static decimal GetQuantity(ChargeItem chargeItem) => Math.Abs(chargeItem.Quantity); + + public static decimal GetPayItemAmount(ReceiptRequest receiptRequest, PayItem payItem) => InverseAmount(receiptRequest, payItem) ? Math.Abs(payItem.Amount) : payItem.Amount; + + public static decimal GetGrossAmount(ReceiptRequest receiptRequest, ChargeItem chargeItem) => InverseAmount(receiptRequest, chargeItem) ? Math.Abs(chargeItem.Amount) : chargeItem.Amount; + + public static decimal GetVATAmount(ReceiptRequest receiptRequest, ChargeItem chargeItem) => InverseAmount(receiptRequest, chargeItem) ? Math.Abs(GetVATAmount(chargeItem)) : GetVATAmount(chargeItem); + + public static decimal GetVATAmount(ChargeItem chargeItem) => (decimal) (chargeItem.VATAmount.HasValue ? chargeItem.VATAmount : Math.Round((chargeItem.Amount - (chargeItem.Amount / (1m + (chargeItem.VATRate / 100m)))), 2, MidpointRounding.AwayFromZero)); +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerSCU.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerSCU.cs new file mode 100644 index 000000000..da1b123d9 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/CustomRTServerSCU.cs @@ -0,0 +1,391 @@ +using System.Collections.Generic; +using System; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using Microsoft.Extensions.Logging; +using fiskaltrust.ifPOS.v1; +using System.Linq; +using Newtonsoft.Json; +using fiskaltrust.Middleware.SCU.IT.CustomRTServer.Models; +using System.IO; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public sealed class CustomRTServerSCU : LegacySCU +{ + private readonly Guid _id; +#pragma warning disable IDE0052 // Remove unread private members + private readonly ILogger _logger; +#pragma warning restore IDE0052 // Remove unread private members + private readonly CustomRTServerClient _client; + private readonly CustomRTServerCommunicationQueue _customRTServerCommunicationQueue; + private readonly AccountMasterData? _accountMasterData; + private Dictionary CashUUIdMappings = new Dictionary(); + private readonly string _scuCacheFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + + private string _stateCacheFilePath => Path.Combine(_scuCacheFolder, $"{_id}_customrtserver_statecache.json"); + + public CustomRTServerSCU(Guid id, ILogger logger, CustomRTServerConfiguration configuration, CustomRTServerClient client, CustomRTServerCommunicationQueue customRTServerCommunicationQueue) + { + _id = id; + _logger = logger; + _client = client; + _customRTServerCommunicationQueue = customRTServerCommunicationQueue; + if (!string.IsNullOrEmpty(configuration.AccountMasterData)) + { + _accountMasterData = JsonConvert.DeserializeObject(configuration.AccountMasterData); + } + + + if (!string.IsNullOrEmpty(configuration.ServiceFolder)) + { + _scuCacheFolder = configuration.ServiceFolder!; + } + if (string.IsNullOrEmpty(_scuCacheFolder)) + { + _scuCacheFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + } + } + + public override Task EchoAsync(ScuItEchoRequest request) => Task.FromResult(new ScuItEchoResponse { Message = request.Message }); + + public override async Task GetRTInfoAsync() + { + var result = await _client.GetDailyStatusArrayAsync(); + return new RTInfo + { + SerialNumber = result.ArrayResponse.FirstOrDefault()?.fiscalBoxId, + InfoData = JsonConvert.SerializeObject(result.ArrayResponse) + }; + } + + public override async Task ProcessReceiptAsync(ProcessRequest request) + { + try + { + var receiptCase = request.ReceiptRequest.GetReceiptCase(); + if (request.ReceiptRequest.IsInitialOperationReceipt()) + { + (var signatures, var state) = await PerformInitOperationAsync(request.ReceiptRequest, request.ReceiptResponse); + request.ReceiptResponse.ftState = state; + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + + if (request.ReceiptRequest.IsOutOfOperationReceipt()) + { + (var signatures, var state) = await PerformOutOfOperationAsync(request.ReceiptResponse); + request.ReceiptResponse.ftState = state; + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + + if (request.ReceiptRequest.IsZeroReceipt()) + { + (var signatures, var stateData, var state) = await PerformZeroReceiptOperationAsync(request.ReceiptRequest, request.ReceiptResponse, request.ReceiptResponse.ftCashBoxIdentification); + request.ReceiptResponse.ftState = state; + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, stateData, signatures); + } + + if (!CashUUIdMappings.ContainsKey(Guid.Parse(request.ReceiptResponse.ftQueueID))) + { + await ReloadCashUUID(request.ReceiptResponse); + } + + var cashuuid = CashUUIdMappings[Guid.Parse(request.ReceiptResponse.ftQueueID)]; + + if (request.ReceiptRequest.IsVoid()) + { + (var commercialDocument, var fiscalDocument) = CustomRTServerMapping.CreateAnnuloDocument(request.ReceiptRequest, cashuuid, request.ReceiptResponse); + var signatures = await ProcessFiscalDocumentAsync(request.ReceiptResponse, cashuuid, commercialDocument, fiscalDocument); + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + + if (request.ReceiptRequest.IsRefund()) + { + (var commercialDocument, var fiscalDocument) = CustomRTServerMapping.CreateResoDocument(request.ReceiptRequest, cashuuid, request.ReceiptResponse); + var signatures = await ProcessFiscalDocumentAsync(request.ReceiptResponse, cashuuid, commercialDocument, fiscalDocument); + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + + if (request.ReceiptRequest.IsDailyClosing()) + { + (var signatures, var state) = await PerformDailyCosingAsync(request.ReceiptRequest, request.ReceiptResponse, cashuuid); + request.ReceiptResponse.ftState = state; + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + + switch (receiptCase) + { + case (long) ITReceiptCases.UnknownReceipt0x0000: + case (long) ITReceiptCases.PointOfSaleReceipt0x0001: + case (long) ITReceiptCases.PaymentTransfer0x0002: + case (long) ITReceiptCases.Protocol0x0005: + (var commercialDocument, var fiscalDocument) = CustomRTServerMapping.GenerateFiscalDocument(request.ReceiptRequest, cashuuid); + var signatures = await ProcessFiscalDocumentAsync(request.ReceiptResponse, cashuuid, commercialDocument, fiscalDocument); + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + + throw new Exception($"The given receiptcase 0x{receiptCase.ToString("X")} is not supported."); + } + catch (Exception ex) + { + var signatures = new List + { + new SignaturItem + { + Caption = "rt-server-generic-error", + Data = $"{ex}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + } + }; + request.ReceiptResponse.ftState = 0x4954_2001_EEEE_EEEE; + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + } + + private async Task<(List signatures, long ftState)> PerformInitOperationAsync(ReceiptRequest receiptRequest, ReceiptResponse receiptResponse) + { + try + { + var shop = receiptResponse.ftCashBoxIdentification.Substring(0, 4); + var name = receiptResponse.ftCashBoxIdentification.Substring(4, 4); + _ = await _client.InsertCashRegisterAsync(receiptResponse.ftQueueID, shop, name, _accountMasterData?.AccountId.ToString() ?? "", _accountMasterData?.VatId ?? _accountMasterData?.TaxId ?? ""); + await ReloadCashUUID(receiptResponse); + var cashuuid = CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)]; + if (cashuuid.CashStatus == "0") + { + await OpenNewdayAsync(receiptRequest, receiptResponse); + } + return (SignatureFactory.CreateInitialOperationSignatures().ToList(), 0x4954_2000_0000_0000); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Faild to call RT Server"); + return (new List + { + new SignaturItem + { + Caption = "rt-server-initoperation-error", + Data = $"{ex}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + } + }, 0x4954_2001_EEEE_EEEE); + } + } + + private async Task<(List signatures, long ftState)> PerformOutOfOperationAsync(ReceiptResponse receiptResponse) + { + try + { + _ = await _client.CancelCashRegisterAsync(receiptResponse.ftCashBoxIdentification, _accountMasterData?.VatId ?? ""); + return (SignatureFactory.CreateOutOfOperationSignatures().ToList(), 0x4954_2000_0000_0000); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Faild to call RT Server"); + return (new List + { + new SignaturItem + { + Caption = "rt-server-outofoperation-error", + Data = $"{ex}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + } + }, 0x4954_2001_EEEE_EEEE); + } + } + + private async Task OpenNewdayAsync(ReceiptRequest receiptRequest, ReceiptResponse receiptResponse) + { + var dailyOpen = await _client.GetDailyOpenAsync(receiptResponse.ftCashBoxIdentification, receiptRequest.cbReceiptMoment); + UpdateCashUUIDMappingsWithDay(receiptResponse, dailyOpen); + } + + private async Task<(List signaturItems, string? ftStateData, long ftState)> PerformZeroReceiptOperationAsync(ReceiptRequest receiptRequest, ReceiptResponse receiptResponse, string cashUuid) + { + try + { + var result = await _client.GetDailyStatusAsync(cashUuid); + if (result.cashStatus == "0") + { + await OpenNewdayAsync(receiptRequest, receiptResponse); + // TODO let's check if we really should auto open a day + } + var resultMemStatus = await _client.GetDeviceMemStatusAsync(); + var signatures = SignatureFactory.CreateZeroReceiptSignatures().ToList(); + var stateData = JsonConvert.SerializeObject(new + { + DeviceMemStatus = resultMemStatus, + DeviceDailyStatus = result, + DocumentsInCache = _customRTServerCommunicationQueue.GetCountOfDocumentsForInCache(cashUuid), + SigningDeviceAvailable = true + }); + return (signatures, stateData, 0x4954_2000_0000_0000); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Faild to call RT Server"); + var stateData = JsonConvert.SerializeObject(new + { + DocumentsInCache = _customRTServerCommunicationQueue.GetCountOfDocumentsForInCache(cashUuid), + SigningDeviceAvailable = false + }); + return (new List + { + new SignaturItem + { + Caption = "rt-server-zeroreceipt-warning", + Data = $"{ex}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_2000 + }, + new SignaturItem + { + Caption = "rt-server-zeroreceipt-cached-documents", + Data = $"{_customRTServerCommunicationQueue.GetCountOfDocumentsForInCache(cashUuid)}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_2000 + } + }, stateData, 0x4954_2001_0000_0000); + } + } + + private async Task ReloadCashUUID(ReceiptResponse receiptResponse) + { + if (File.Exists(_stateCacheFilePath)) + { + CashUUIdMappings = JsonConvert.DeserializeObject>(File.ReadAllText(_stateCacheFilePath)); + } + if (CashUUIdMappings.ContainsKey(Guid.Parse(receiptResponse.ftQueueID))) + { + return; + } + + var dailyOpen = await _client.GetDailyStatusAsync(receiptResponse.ftCashBoxIdentification); + CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)] = new QueueIdentification + { + RTServerSerialNumber = dailyOpen.fiscalBoxId, + CashHmacKey = dailyOpen.cashHmacKey, + LastZNumber = int.Parse(dailyOpen.numberClosure), + LastDocNumber = int.Parse(dailyOpen.cashLastDocNumber), + CashUuId = receiptResponse.ftCashBoxIdentification, + LastSignature = dailyOpen.cashToken, + CurrentGrandTotal = int.Parse(dailyOpen.grandTotalDB), + CashStatus = dailyOpen.cashStatus + }; + File.WriteAllText(_stateCacheFilePath, JsonConvert.SerializeObject(CashUUIdMappings)); + } + + private void UpdateCashUUIDMappingsWithDay(ReceiptResponse receiptResponse, GetDailyOpenResponse dailyOpen) + { + CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)] = new QueueIdentification + { + RTServerSerialNumber = dailyOpen.fiscalBoxId, + CashHmacKey = dailyOpen.cashHmacKey, + LastZNumber = int.Parse(dailyOpen.numberClosure), + LastDocNumber = int.Parse(string.IsNullOrWhiteSpace(dailyOpen.cashLastDocNumber) ? "0" : dailyOpen.cashLastDocNumber), + CashUuId = receiptResponse.ftCashBoxIdentification, + LastSignature = dailyOpen.cashToken, + CurrentGrandTotal = int.Parse(string.IsNullOrWhiteSpace(dailyOpen.grandTotalDB) ? "0" : dailyOpen.grandTotalDB), + CashStatus = dailyOpen.cashStatus + }; + File.WriteAllText(_stateCacheFilePath, JsonConvert.SerializeObject(CashUUIdMappings)); + } + + private void UpdatedCashUUID(ReceiptResponse receiptResponse, DocumentData document, QrCodeData qrCodeData) + { + CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)].LastDocNumber = document.docnumber; + CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)].LastSignature = qrCodeData.signature; + CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)].CurrentGrandTotal = CashUUIdMappings[Guid.Parse(receiptResponse.ftQueueID)].CurrentGrandTotal + document.amount; + File.WriteAllText(_stateCacheFilePath, JsonConvert.SerializeObject(CashUUIdMappings)); + } + + private async Task> ProcessFiscalDocumentAsync(ReceiptResponse receiptResponse, QueueIdentification cashuuid, CommercialDocument commercialDocument, FDocument fiscalDocument) + { + await _customRTServerCommunicationQueue.EnqueueDocument(receiptResponse.ftCashBoxIdentification, commercialDocument, fiscalDocument.document.docznumber, fiscalDocument.document.docnumber); + UpdatedCashUUID(receiptResponse, fiscalDocument.document, commercialDocument.qrData); + var docType = ""; + if (fiscalDocument.document.doctype == 5) + { + docType = "VOID"; + } + else if (fiscalDocument.document.doctype == 3) + { + docType = "REFUND"; + } + else if (fiscalDocument.document.doctype == 1) + { + docType = "POSRECEIPT"; + } + var data = new POSReceiptSignatureData + { + RTSerialNumber = cashuuid.RTServerSerialNumber, + RTZNumber = fiscalDocument.document.docznumber, + RTDocNumber = fiscalDocument.document.docnumber, + RTDocMoment = DateTime.Parse(fiscalDocument.document.dtime), + RTDocType = docType, + RTServerSHAMetadata = commercialDocument.qrData.shaMetadata, + RTCodiceLotteria = "", + RTCustomerID = "", + RTReferenceZNumber = fiscalDocument.document.referenceClosurenumber, + RTReferenceDocNumber = fiscalDocument.document.referenceDocnumber, + RTReferenceDocMoment = string.IsNullOrEmpty(fiscalDocument.document.referenceDtime) ? null : DateTime.Parse(fiscalDocument.document.referenceDtime) + }; + return SignatureFactory.CreateDocumentoCommercialeSignatures(data); + } + + private async Task<(List, long ftState)> PerformDailyCosingAsync(ReceiptRequest receiptRequest, ReceiptResponse receiptResponse, QueueIdentification cashuuid) + { + var warnings = new List(); + + GetDailyStatusResponse? status; + try + { + status = await _client.GetDailyStatusAsync(receiptResponse.ftCashBoxIdentification); + } + catch (Exception ex) + { + _logger.LogError(ex, "Faild to call RT Server"); + return (new List + { + new SignaturItem + { + Caption = "rt-server-dailyclosing-error", + Data = $"{ex}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + }, + new SignaturItem + { + Caption = "rt-server-dailyclosing-cached-documents", + Data = $"{_customRTServerCommunicationQueue.GetCountOfDocumentsForInCache(receiptResponse.ftCashBoxIdentification)}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_1000 + } + }, 0x4954_2001_EEEE_EEEE); + } + + await _customRTServerCommunicationQueue.ProcessAllReceipts(receiptResponse.ftCashBoxIdentification); + + var currentZNumber = int.Parse(status.numberClosure) + 1; + // process left over receipts + var dailyClosingResponse = await _client.InsertZDocumentAsync(cashuuid.CashUuId, receiptRequest.cbReceiptMoment, currentZNumber, status.grandTotalDB); + await OpenNewdayAsync(receiptRequest, receiptResponse); + warnings.AddRange(dailyClosingResponse.responseSubCode); + var signatures = SignatureFactory.CreateDailyClosingReceiptSignatures(currentZNumber).ToList(); + if (warnings.Count > 0) + { + signatures.Add(new SignaturItem + { + Caption = "rt-server-dailyclosing-warning", + Data = $"[{string.Join(",", warnings.ToArray())}]", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_2000 + }); + } + return (signatures, 0x4954_2000_0000_0000); + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Directory.Build.props b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Directory.Build.props new file mode 100644 index 000000000..e3a2a1b0e --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Directory.Build.props @@ -0,0 +1,5 @@ + + + + + diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/GlobalTools.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/GlobalTools.cs new file mode 100644 index 000000000..44aa536b9 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/GlobalTools.cs @@ -0,0 +1,43 @@ +using System; +using System.Text; +using System.Security.Cryptography; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public static class GlobalTools +{ + public static string GetSHA256(string input) + { + using var shA256Managed = SHA256.Create(); + var stringBuilder = new StringBuilder(); + var bytes = Encoding.UTF8.GetBytes(input); + var byteCount = Encoding.UTF8.GetByteCount(input); + return Convert.ToBase64String(shA256Managed.ComputeHash(bytes, 0, byteCount)); + } + + private static byte[] HashHMAC(byte[] key, byte[] message) => new HMACSHA256(key).ComputeHash(message); + + private static byte[] ConvertStringToByteArray(string text) => Encoding.UTF8.GetBytes(text); + + public static string CreateHMAC(byte[] key, string source) + { + var byteArray = GlobalTools.ConvertStringToByteArray(source); + return Convert.ToBase64String(GlobalTools.HashHMAC(key, byteArray)); + } + + public static bool VerifyHMAC(byte[] key, string hmacValue, string source) + { + var flag = false; + var numArray1 = Convert.FromBase64String(hmacValue); + var byteArray = GlobalTools.ConvertStringToByteArray(source); + var numArray2 = GlobalTools.HashHMAC(key, byteArray); + for (var index = 0; index < numArray1.Length; ++index) + { + if (numArray2[index] != numArray1[index]) + { + flag = true; + } + } + return !flag; + } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/AdditionalTaxData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/AdditionalTaxData.cs new file mode 100644 index 000000000..07f59972f --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/AdditionalTaxData.cs @@ -0,0 +1,8 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class AdditionalTaxData +{ + public string type { get; set; } = string.Empty; + public int gross { get; set; } + public int vatvalue { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CancelCashRegisterResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CancelCashRegisterResponse.cs new file mode 100644 index 000000000..cf1468b9b --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CancelCashRegisterResponse.cs @@ -0,0 +1 @@ +public class CancelCashRegisterResponse : CustomRTDResponse { } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CommercialDocument.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CommercialDocument.cs new file mode 100644 index 000000000..8a4ec7cd5 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CommercialDocument.cs @@ -0,0 +1,7 @@ +using fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class CommercialDocument +{ + public QrCodeData qrData { get; set; } = null!; + public string fiscalData { get; set; } = null!; +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CustomRTDResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CustomRTDResponse.cs new file mode 100644 index 000000000..75b06c922 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CustomRTDResponse.cs @@ -0,0 +1,5 @@ +public class CustomRTDResponse +{ + public int responseCode { get; set; } + public string responseDesc { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CustomRTDetailedResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CustomRTDetailedResponse.cs new file mode 100644 index 000000000..99361e5de --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/CustomRTDetailedResponse.cs @@ -0,0 +1,4 @@ +public class CustomRTDetailedResponse : CustomRTDResponse +{ + public ResponseBodyErrory? responseErr { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentData.cs new file mode 100644 index 000000000..79ad8fbc6 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentData.cs @@ -0,0 +1,28 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class DocumentData +{ + + public string cashuuid { get; set; } = string.Empty; + public int doctype { get; set; } + public string dtime { get; set; } = string.Empty; + public int docnumber { get; set; } + public int docznumber { get; set; } + public int amount { get; set; } + public string fiscalcode { get; set; } = string.Empty; + public string vatcode { get; set; } = string.Empty; + public string fiscaloperator { get; set; } = string.Empty; + public string? businessname { get; set; } = null; + public string? prevSignature { get; set; } = string.Empty; + public string type_signature_id => "1"; + public int grandTotal { get; set; } + public long referenceClosurenumber { get; set; } + public long referenceDocnumber { get; set; } + public string? referenceDtime { get; set; } = null; + public string? refSerialNum { get; set; } = null; + public string? referenceCashuuid { get; set; } = null; + + public string? errSignature => null; + public int? err_number => null; + public int? err_znumber => null; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentDataLottery.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentDataLottery.cs new file mode 100644 index 000000000..59620a28a --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentDataLottery.cs @@ -0,0 +1,6 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class DocumentDataLottery : DocumentData +{ + public string lottery_client_code { get; set; }= string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentItemData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentItemData.cs new file mode 100644 index 000000000..e633fe6e4 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentItemData.cs @@ -0,0 +1,19 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class DocumentItemData +{ + public string type { get; set; } = string.Empty; + public string description { get; set; } = string.Empty; + public string amount { get; set; } = string.Empty; + public string quantity { get; set; } = string.Empty; + public string unitprice { get; set; } = string.Empty; + public string vatvalue { get; set; } = string.Empty; + public string? fiscalvoid { get; set; } = "0"; + public string signid { get; set; } = "1"; + public string paymentid { get; set; } = string.Empty; + public string plu { get; set; } = string.Empty; + public string department { get; set; } = string.Empty; + public string? vatcode { get; set; } = null; + public string? service { get; } = "0"; + public string? businesscode { get; } = ""; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentItemDataTaypes.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentItemDataTaypes.cs new file mode 100644 index 000000000..35bd1a1ce --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentItemDataTaypes.cs @@ -0,0 +1,32 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer.Models; + +public static class DocumentItemDataTaypes +{ + public const string VENDITA = "1"; + + public const string PAGAMENTO = "5"; + + public const string STORNO_ACCONTO = "7"; + + public const string OMAGGIO = "8"; + + public const string DESCRITTIVA = "97"; +} + +public static class DocumentItemPaymentIds +{ + public const string CONTANTE = "1"; + + public const string ELETTRONICO = "2"; + + public const string NON_RISCOSSO = "3"; + + public const string TICKET_RESTAURANT = "4"; + + public const string NON_RISCOSSO_SERVIZI_GENERICO = "5"; + + public const string NON_RISCOSSO_FATTURE = "6"; + + public const string NON_RISCOSSO_DCR_A_SSN = "7"; + public const string SCONTO_A_PAGARE = "8"; +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentTaxData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentTaxData.cs new file mode 100644 index 000000000..db4b7081d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/DocumentTaxData.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class DocumentTaxData +{ + public int gross { get; set; } + public int tax { get; set; } + public int vatvalue { get; set; } + public string vatcode { get; set; } = string.Empty; + + // deprecated + public string? businesscode { get; set; } + public List additional_tax_data { get; set; } = new List(); +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/FDocument.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/FDocument.cs new file mode 100644 index 000000000..90917ad07 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/FDocument.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class FDocument +{ + public DocumentData document { get; set; } = new DocumentData(); + public List items { get; set; } = new List(); + public List taxs { get; set; } = new List(); +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/FDocumentLottery.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/FDocumentLottery.cs new file mode 100644 index 000000000..5c10d3698 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/FDocumentLottery.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class FDocumentLottery +{ + public DocumentDataLottery? document { get; set; } + public List items { get; set; } = new List(); + public List taxs { get; set; } = new List(); +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyOpenResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyOpenResponse.cs new file mode 100644 index 000000000..277b7234d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyOpenResponse.cs @@ -0,0 +1,14 @@ +public class GetDailyOpenResponse : CustomRTDetailedResponse +{ + public string numberClosure { get; set; } = string.Empty; + public string idClosure { get; set; } = string.Empty; + public string fiscalBoxId { get; set; } = string.Empty; + public string cashName { get; set; } = string.Empty; + public string cashShop { get; set; } = string.Empty; + public string cashDesc { get; set; } = string.Empty; + public string cashToken { get; set; } = string.Empty; + public string cashHmacKey { get; set; } = string.Empty; + public string cashStatus { get; set; } = string.Empty; + public string cashLastDocNumber { get; set; } = string.Empty; + public string grandTotalDB { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusArrayResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusArrayResponse.cs new file mode 100644 index 000000000..01099bd3d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusArrayResponse.cs @@ -0,0 +1,7 @@ +using System.Collections.Generic; + +public class GetDailyStatusArrayResponse : CustomRTDetailedResponse +{ + public List ArrayResponse { get; set; } = new List(); + +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusResponse.cs new file mode 100644 index 000000000..a656d6760 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusResponse.cs @@ -0,0 +1,15 @@ +public class GetDailyStatusResponse : CustomRTDetailedResponse +{ + public string numberClosure { get; set; } = string.Empty; + public string idClosure { get; set; } = string.Empty; + public string fiscalBoxId { get; set; } = string.Empty; + public string cashName { get; set; } = string.Empty; + public string cashShop { get; set; } = string.Empty; + public string cashDesc { get; set; } = string.Empty; + public string cashToken { get; set; } = string.Empty; + public string cashHmacKey { get; set; } = string.Empty; + public string cashStatus { get; set; } = string.Empty; + public string cashLastDocNumber { get; set; } = string.Empty; + public string grandTotalDB { get; set; } = string.Empty; + public string dateTimeServer { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusResponseContent.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusResponseContent.cs new file mode 100644 index 000000000..f5e59b95d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDailyStatusResponseContent.cs @@ -0,0 +1,19 @@ +public class GetDailyStatusResponseContent +{ + public string numberClosure { get; set; } = string.Empty; + public string idClosure { get; set; } = string.Empty; + public string jsonResponse { get; set; } = string.Empty; + public string fiscalBoxId { get; set; } = string.Empty; + public string cashName { get; set; } = string.Empty; + public string cashShop { get; set; } = string.Empty; + public string cashDesc { get; set; } = string.Empty; + public string cashToken { get; set; } = string.Empty; + public string cashHmacKey { get; set; } = string.Empty; + public string cashStatus { get; set; } = string.Empty; + public int responseCode { get; set; } + public string responseDesc { get; set; } = string.Empty; + public string dateTimeServer { get; set; } = string.Empty; + public string cashLastDocNumber { get; set; } = string.Empty; + public string grandTotalDB { get; set; } = string.Empty; + public string cashuuid { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDeviceMemStatusResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDeviceMemStatusResponse.cs new file mode 100644 index 000000000..749ec39f5 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/GetDeviceMemStatusResponse.cs @@ -0,0 +1,7 @@ +public class GetDeviceMemStatusResponse : CustomRTDetailedResponse +{ + public int ej_capacity { get; set; } + public int ej_used { get; set; } + public int ej_available { get; set; } + public int average_erase_count { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertCashRegisterAsyncResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertCashRegisterAsyncResponse.cs new file mode 100644 index 000000000..cc8acc4ef --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertCashRegisterAsyncResponse.cs @@ -0,0 +1,4 @@ +public class InsertCashRegisterAsyncResponse : CustomRTDResponse +{ + public string cashUuid { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentArrayResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentArrayResponse.cs new file mode 100644 index 000000000..65a695832 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentArrayResponse.cs @@ -0,0 +1,7 @@ +using System.Collections.Generic; + +public class InsertFiscalDocumentArrayResponse : CustomRTDetailedResponse +{ + public List responseArraySubCode { get; set; } = new List(); + public List ArrayResponse { get; set; } = new List(); +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentArraySubResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentArraySubResponse.cs new file mode 100644 index 000000000..c9c655040 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentArraySubResponse.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +public class InsertFiscalDocumentArraySubResponse +{ + public int id { get; set; } + public string? signedDigest { get; set; } + public string? publKey { get; set; } + public List responseSubCode { get; set; } = new List(); + public string fiscalDocID { get; set; } = string.Empty; + public int responseCode { get; set; } + public string responseDesc { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentResponse.cs new file mode 100644 index 000000000..e03a86d9d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertFiscalDocumentResponse.cs @@ -0,0 +1,7 @@ +using System.Collections.Generic; + +public class InsertFiscalDocumentResponse : CustomRTDetailedResponse +{ + public List responseSubCode { get; set; } = new List(); + public int fiscalDocId { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertZDocumentResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertZDocumentResponse.cs new file mode 100644 index 000000000..e3f2f201d --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/InsertZDocumentResponse.cs @@ -0,0 +1,6 @@ +using System.Collections.Generic; + +public class InsertZDocumentResponse : CustomRTDetailedResponse +{ + public List responseSubCode { get; set; } = new List(); +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/QrCodeData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/QrCodeData.cs new file mode 100644 index 000000000..5641aa62b --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/QrCodeData.cs @@ -0,0 +1,8 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class QrCodeData +{ + public string shaMetadata { get; set; } = string.Empty; + public string signature { get; set; } = string.Empty; + public string? addInfo { get; set; } = null; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/QueueIdentification.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/QueueIdentification.cs new file mode 100644 index 000000000..c472e5800 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/QueueIdentification.cs @@ -0,0 +1,13 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer.Models; + +public class QueueIdentification +{ + public string RTServerSerialNumber { get; set; } = string.Empty; + public string CashUuId { get; set; } = string.Empty; + public int LastZNumber { get; set; } + public string CashHmacKey { get; set; } = string.Empty; + public string LastSignature { get; set; } = string.Empty; + public int LastDocNumber { get; set; } + public int CurrentGrandTotal { get; set; } + public string CashStatus { get; set; } = string.Empty; +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/ReactivateCanceledCashRegisterResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/ReactivateCanceledCashRegisterResponse.cs new file mode 100644 index 000000000..a33aa2bd2 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/ReactivateCanceledCashRegisterResponse.cs @@ -0,0 +1 @@ +public class ReactivateCanceledCashRegisterResponse : CustomRTDResponse { } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/ResponseBodyErrory.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/ResponseBodyErrory.cs new file mode 100644 index 000000000..f66e69d91 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/ResponseBodyErrory.cs @@ -0,0 +1,23 @@ +public class ResponseBodyErrory +{ + public int err_fm_present { get; set; } + public int err_ej_present { get; set; } + public int err_mkey_present { get; set; } + public int err_mkey_valid { get; set; } + public int err_ej_full { get; set; } + public int err_fm_full { get; set; } + public int err_hwinit_max { get; set; } + public int err_cert_expired { get; set; } + public int err_count { get; set; } + + public int warn_ej_full { get; set; } + public int warn_fm_full { get; set; } + public int warn_hwinit_max { get; set; } + public int warn_cert_expired { get; set; } + public int warn_count { get; set; } + public int warn_hwinit_val { get; set; } + public int warn_fm_full_val { get; set; } + public int warn_ej_full_val { get; set; } + + public int err_fm_status { get; set; } +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UpdateCashRegisterResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UpdateCashRegisterResponse.cs new file mode 100644 index 000000000..28b7ba321 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UpdateCashRegisterResponse.cs @@ -0,0 +1 @@ +public class UpdateCashRegisterResponse : CustomRTDResponse { } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UserData.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UserData.cs new file mode 100644 index 000000000..532c0d8c9 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UserData.cs @@ -0,0 +1,10 @@ +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class UserData +{ + public string username { get; set; } = string.Empty; + public string email { get; set; } = string.Empty; + public string password { get; set; } = string.Empty; + public string cfiscale { get; set; } = string.Empty; + public string piva { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UserDataArray.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UserDataArray.cs new file mode 100644 index 000000000..87a12bb87 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/Models/UserDataArray.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer; + +public class UserDataArray +{ + public List userdata { get; set; } = new List(); +} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/ScuBootstrapper.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/ScuBootstrapper.cs new file mode 100644 index 000000000..8abcc6074 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/ScuBootstrapper.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer +{ + public class ScuBootstrapper : IMiddlewareBootstrapper + { + public Guid Id { get; set; } + public Dictionary Configuration { get; set; } = null!; + + public void ConfigureServices(IServiceCollection serviceCollection) + { + var configuration = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(Configuration)); + + _ = serviceCollection + .AddSingleton(configuration) + .AddSingleton(x => new CustomRTServerCommunicationQueue(Id, x.GetRequiredService(), x.GetRequiredService>(), x.GetRequiredService())) + .AddScoped() + .AddScoped(x => new CustomRTServerSCU(Id, x.GetRequiredService>(), x.GetRequiredService(), x.GetRequiredService(), x.GetRequiredService())); + } + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/fiskaltrust.Middleware.SCU.IT.CustomRTServer.csproj b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/fiskaltrust.Middleware.SCU.IT.CustomRTServer.csproj new file mode 100644 index 000000000..1fa549c7b --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/fiskaltrust.Middleware.SCU.IT.CustomRTServer.csproj @@ -0,0 +1,34 @@ + + + + The fiskaltrust Middleware implementation of the Custom RT Server SCU for Italy. + netstandard2.0;net461;net6 + $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage + enable + + + + + + + + + + + + + + + + + + + true + + + + + + + + \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/version.json b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/version.json new file mode 100644 index 000000000..ff07fc88e --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.CustomRTServer/version.json @@ -0,0 +1,6 @@ +{ + "version": "1.3.50-rc1", + "releaseBranches": [ + "^refs/tags/scu-it/customrtserver/v\\d+(?:\\.\\d+)*(?:-.*)?$" + ] +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/EpsonSCU.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/EpsonSCU.cs deleted file mode 100644 index 56630097c..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/EpsonSCU.cs +++ /dev/null @@ -1,373 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.ServiceModel; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using fiskaltrust.ifPOS.v1.errors; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; -using fiskaltrust.Middleware.SCU.IT.Epson.Utilities; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; - -namespace fiskaltrust.Middleware.SCU.IT.Epson; - -#nullable enable -public sealed class EpsonSCU : IITSSCD -{ - private readonly ILogger _logger; - private readonly EpsonScuConfiguration _configuration; - private readonly EpsonCommandFactory _epsonXmlWriter; - private readonly HttpClient _httpClient; - private readonly string _commandUrl; - private readonly ErrorInfoFactory _errorCodeFactory = new(); - private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0, 1); - private string _serialnr = ""; - - public EpsonSCU(ILogger logger, EpsonScuConfiguration configuration, EpsonCommandFactory epsonXmlWriter) - { - _logger = logger; - _configuration = configuration; - _epsonXmlWriter = epsonXmlWriter; - if (string.IsNullOrEmpty(configuration.DeviceUrl)) - { - throw new NullReferenceException("EpsonScuConfiguration DeviceUrl not set."); - } - _httpClient = new HttpClient - { - BaseAddress = new Uri(configuration.DeviceUrl), - Timeout = TimeSpan.FromMilliseconds(configuration.ClientTimeoutMs) - }; - _commandUrl = $"cgi-bin/fpmate.cgi?timeout={configuration.ServerTimeoutMs}"; - } - - public Task EchoAsync(ScuItEchoRequest request) => Task.FromResult(new ScuItEchoResponse { Message = request.Message }); - - public async Task FiscalReceiptInvoiceAsync(FiscalReceiptInvoice request) - { - try - { - _semaphore.Wait(_configuration.LockTimeoutMs); - - var content = _epsonXmlWriter.CreateInvoiceRequestContent(request); - - var response = await SendRequestAsync(content); - - using var responseContent = await response.Content.ReadAsStreamAsync(); - var result = SoapSerializer.Deserialize(responseContent); - var fiscalReceiptResponse = new FiscalReceiptResponse() - { - Success = result?.Success ?? false - }; - await SetReceiptResponse(request?.Payments, result, fiscalReceiptResponse); - return fiscalReceiptResponse; - } - catch (Exception e) - { - return ExceptionInfo(e); - } - finally - { - _semaphore.Release(); - } - } - - public async Task GetSerialNumberAsync(string rtType) - { - var serialQuery = new PrinterCommand() { DirectIO = DirectIO.GetSerialNrCommand() }; - var content = SoapSerializer.Serialize(serialQuery); - var responseSerialnr = await SendRequestAsync(content); - - using var responseContent = await responseSerialnr.Content.ReadAsStreamAsync(); - var result = SoapSerializer.Deserialize(responseContent); - - var serialnr = result?.CommandResponse?.ResponseData; - - return serialnr?.Substring(10, 2) + rtType + serialnr?.Substring(8, 2) + serialnr?.Substring(2, 6); - } - - public async Task FiscalReceiptRefundAsync(FiscalReceiptRefund request) - { - try - { - _semaphore.Wait(_configuration.LockTimeoutMs); - - var content = _epsonXmlWriter.CreateRefundRequestContent(request); - var response = await SendRequestAsync(content); - - using var responseContent = await response.Content.ReadAsStreamAsync(); - var result = SoapSerializer.Deserialize(responseContent); - var fiscalReceiptResponse = new FiscalReceiptResponse() - { - Success = result?.Success ?? false - }; - await SetReceiptResponse(request.Payments, result, fiscalReceiptResponse); - return fiscalReceiptResponse; - } - catch (Exception e) - { - return ExceptionInfo(e); - } - finally - { - _semaphore.Release(); - } - } - - public async Task ExecuteDailyClosingAsync(DailyClosingRequest request) - { - try - { - _semaphore.Wait(_configuration.LockTimeoutMs); - - var content = _epsonXmlWriter.CreatePrintZReportRequestContent(request); - var response = await SendRequestAsync(content); - - using var responseContent = await response.Content.ReadAsStreamAsync(); - var result = SoapSerializer.Deserialize(responseContent); - var dailyClosingResponse = new DailyClosingResponse() - { - Success = result?.Success ?? false - }; - - if (!dailyClosingResponse.Success) - { - dailyClosingResponse.SSCDErrorInfo = GetErrorInfo(result?.Code, result?.Status, null); - await ResetPrinter(); - } - else - { - dailyClosingResponse.ZRepNumber = result?.ReportInfo?.ZRepNumber != null ? long.Parse(result.ReportInfo.ZRepNumber) : 0; - dailyClosingResponse.DailyAmount = result?.ReportInfo?.DailyAmount != null ? decimal.Parse(result.ReportInfo.DailyAmount, new CultureInfo("it-It", false)) : 0; - dailyClosingResponse.ReportDataJson = await DownloadJsonAsync("www/json_files/zrep.json"); - } - return dailyClosingResponse; - } - catch (Exception e) - { - var msg = e.Message; - if (e.InnerException != null) - { - msg = msg + " " + e.InnerException.Message; - } - if (IsConnectionException(e)) - { - return new DailyClosingResponse() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.Connection } }; - } - return new DailyClosingResponse() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.General } }; - } - finally - { - _semaphore.Release(); - } - } - - public async Task GetDeviceInfoAsync() - { - var content = _epsonXmlWriter.CreateQueryPrinterStatusRequestContent(); - var response = await _httpClient.PostAsync(_commandUrl, new StringContent(content, Encoding.UTF8, "application/xml")); - using var responseContent = await response.Content.ReadAsStreamAsync(); - var result = SoapSerializer.Deserialize(responseContent); - - _logger.LogInformation(JsonConvert.SerializeObject(result)); - if (string.IsNullOrEmpty(_serialnr) && result?.Printerstatus?.RtType != null) - { - _serialnr = await GetSerialNumberAsync(result.Printerstatus.RtType).ConfigureAwait(false); - } - - return new DeviceInfo - { - DailyOpen = result?.Printerstatus?.DailyOpen == "1", - DeviceStatus = ParseStatus(result?.Printerstatus?.MfStatus), // TODO Create enum - ExpireDeviceCertificateDate = result?.Printerstatus?.ExpiryCD, // TODO Use Datetime; this value seemingly can also be 20 - ExpireTACommunicationCertificateDate = result?.Printerstatus?.ExpiryCA, // TODO use DateTime? - SerialNumber = _serialnr - - }; - } - - public async Task NonFiscalReceiptAsync(NonFiscalRequest request) - { - try - { - _semaphore.Wait(_configuration.LockTimeoutMs); - - var content = _epsonXmlWriter.CreateNonFiscalReceipt(request); - var httpResponse = await SendRequestAsync(content); - - using var responseContent = await httpResponse.Content.ReadAsStreamAsync(); - var result = SoapSerializer.Deserialize(responseContent); - var response = new Response() - { - Success = result?.Success ?? false - }; - - if (!response.Success) - { - response.SSCDErrorInfo = GetErrorInfo(result?.Code, result?.Status, null); - } - return response; - } - catch (Exception e) - { - var msg = e.Message; - if (e.InnerException != null) - { - msg = msg + " " + e.InnerException.Message; - } - if (IsConnectionException(e)) - { - return new Response() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.Connection } }; - } - return new Response() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.General } }; - } - finally - { - _semaphore.Release(); - } - } - - private async Task SetReceiptResponse(List? payments, ReceiptResponse? result, FiscalReceiptResponse fiscalReceiptResponse) - { - if (result?.Success == false) - { - fiscalReceiptResponse.SSCDErrorInfo = GetErrorInfo(result.Code, result.Status, result?.Receipt?.PrinterStatus); - await ResetPrinter(); - } - else - { - await SetResponseAsync(payments, result, fiscalReceiptResponse); - } - } - - private async Task SetResponseAsync(List? payments, ReceiptResponse? result, FiscalReceiptResponse fiscalReceiptResponse) - { - decimal.TryParse(result?.Receipt?.FiscalReceiptAmount, NumberStyles.Any, new CultureInfo("it-It", false), out var amount); - if (result?.Success == true && amount == 0) - { - amount = payments?.Sum(x => x.Amount) ?? 0; - } - fiscalReceiptResponse.Amount = amount; - fiscalReceiptResponse.ReceiptNumber = result?.Receipt?.FiscalReceiptNumber != null ? long.Parse(result.Receipt.FiscalReceiptNumber) : 0; - fiscalReceiptResponse.ZRepNumber = result?.Receipt?.ZRepNumber != null ? long.Parse(result.Receipt.ZRepNumber) : 0; - fiscalReceiptResponse.ReceiptDataJson = await DownloadJsonAsync("www/json_files/rec.json"); - - if (result?.Receipt?.FiscalReceiptDate != null && result?.Receipt?.FiscalReceiptTime != null) - { - fiscalReceiptResponse.ReceiptDateTime = DateTime.ParseExact(result.Receipt.FiscalReceiptDate, "d/M/yyyy", CultureInfo.InvariantCulture); - var time = TimeSpan.Parse(result.Receipt.FiscalReceiptTime); - fiscalReceiptResponse.ReceiptDateTime = fiscalReceiptResponse.ReceiptDateTime + time; - } - else - { - fiscalReceiptResponse.ReceiptDateTime = DateTime.Now; - } - } - - private string? GetPrinterStatus(string? printerStatus) - { - var pst = printerStatus?.ToCharArray(); - if (pst != null) - { - var printerstatus = new DeviceStatus(Array.ConvertAll(pst, c => (int) char.GetNumericValue(c))); - return JsonConvert.SerializeObject(printerstatus); - } - - return null; - } - - private string ParseStatus(string? mfStatus) - { - return mfStatus switch - { - "01" => "Not in service", - "02" => "In service", - _ => "Undefined" - }; - } - - private async Task ResetPrinter() - { - var resetCommand = new PrinterCommand() { ResetPrinter = new ResetPrinter() { Operator = "" } }; - var xml = SoapSerializer.Serialize(resetCommand); - await SendRequestAsync(xml); - } - - private async Task SendRequestAsync(string content) - { - var response = await _httpClient.PostAsync(_commandUrl, new StringContent(content, Encoding.UTF8, "application/xml")); - - if (!response.IsSuccessStatusCode) - { - throw new HttpRequestException($"An error occured while sending a request to the Epson device (StatusCode: {response.StatusCode}, Content: {await response.Content.ReadAsStringAsync()})"); - } - - return response; - } - - private async Task DownloadJsonAsync(string path) - { - var response = await _httpClient.GetAsync(path); - var content = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - _logger.LogError("Could not download JSON file from device (URL: {Url}, Path: {Path}, Response content: {Content}", _httpClient.BaseAddress?.ToString(), path, content); - return null; // TODO: Or better throw? - } - - return content; - } - - private bool IsConnectionException(Exception e) - { - if (e.GetType().IsAssignableFrom(typeof(EndpointNotFoundException)) || - e.GetType().IsAssignableFrom(typeof(WebException)) || - e.GetType().IsAssignableFrom(typeof(CommunicationException)) || - e.GetType().IsAssignableFrom(typeof(TaskCanceledException)) || - e.GetType().IsAssignableFrom(typeof(HttpRequestException))) - { - return true; - } - return false; - } - - private FiscalReceiptResponse ExceptionInfo(Exception e) - { - var msg = e.Message; - if (e.InnerException != null) - { - msg += " " + e.InnerException.Message; - } - if (IsConnectionException(e)) - { - return new FiscalReceiptResponse() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.Connection } }; - } - return new FiscalReceiptResponse() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.General } }; - } - - private SSCDErrorInfo GetErrorInfo(string? code, string? status, string? printerStatus) - { - var errorInf = string.Empty; - if (code != null) - { - errorInf += $"\n Error Code {code}: {_errorCodeFactory.GetCodeInfo(code)} "; - } - if (status != null) - { - errorInf += $"\n Status {status}: {_errorCodeFactory.GetStatusInfo(int.Parse(status))}"; - } - var state = GetPrinterStatus(printerStatus); - if (state != null) - { - errorInf += $"\n Printer state {state}"; - } - _logger.LogError(errorInf); - return new SSCDErrorInfo() { Info = errorInf, Type = SSCDErrorType.Device }; - } - -} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/EpsonScuConfiguration.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/EpsonScuConfiguration.cs deleted file mode 100644 index 314706a91..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/EpsonScuConfiguration.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace fiskaltrust.Middleware.SCU.IT.Epson -{ - public class EpsonScuConfiguration - { - /// - /// The URL or IP address of the RT Printer or Server, e.g. http://192.168.0.100 - /// - public string? DeviceUrl { get; set; } - - /// - /// The HTTP client timeout used when communicating with the RT Printer or Server - /// - public int ClientTimeoutMs { get; set; } = 15000; - - /// - /// The server/printer timeout for executing commands - /// - public int ServerTimeoutMs { get; set; } = 10000; - - /// - /// The timeout used for locking the SCU during requests. Should be greater than ClientTimeoutMs. - /// - public int LockTimeoutMs { get; set; } = 16000; - - /// - /// This value defines the starting position from the left margin (range 0 to 511). - /// - /// - /// Three special values can also be used: - /// - 900 = Left aligned - /// - 901 = Centred - /// - 902 = Right aligned - /// - public int BarCodePosition { get; set; } = 10; - - /// - /// Indicates the print dot width of each distinct bar (range 1 to 6). Please note that not all readers are able to read barcodes with a 1 dot width - /// - public int BarCodeWidth { get; set; } = 2; - - /// - /// Indicates the height of the bar code measured in print dots (range 1 to 255). - /// - public int BarCodeHeight { get; set; } = 66; - - /// - /// Selects one of three ways to print the alphanumeric representation of the barcode or to disable it altogether. - /// - /// - /// The options are as follows: - /// o 0 = Disabled - /// o 1 = Above the barcode - /// o 2 = Below the barcode - /// o 3 = Below and above the barcode - /// - public int BarCodeHRIPosition { get; set; } = 1; - - /// - /// Indicates the font to be used for the HRI string. - /// - /// - /// The options are as follows: - /// - A - /// - B - /// - C - /// - public char BarCodeHRIFont { get; set; } = 'C'; - - /// - /// Indicates the barcode or QR code standard. - /// - /// - /// Choose from one of the following: - /// - UPC-A => 65 - /// - UPC-E / 66 - /// - EAN13 / 67 - /// - EAN8 / 68 - /// - CODE39 / 69 - /// - ITF / 70 - /// - CODABAR / 71 - /// - CODE93 / 72 - /// - CODE128 / 73 - /// - 74 to 78 * - /// - QRCODE1 / 91 - /// - QRCODE2 / 92 - /// - public string CodeType { get; set; } = "CODE39"; - } -} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/FiscalReceiptInvoiceExtension.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/FiscalReceiptInvoiceExtension.cs deleted file mode 100644 index 4fbc752c5..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/FiscalReceiptInvoiceExtension.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; - -namespace fiskaltrust.Middleware.SCU.IT.Epson.Extensions -{ - public static class FiscalReceiptInvoiceExtension - { - public static List GetAdjustmentAndMessages(this FiscalReceiptInvoice request) - { - var adjustmentAndMessages = new List(); - if (request.PaymentAdjustments != null) - { - foreach (var adj in request.PaymentAdjustments) - { - var printRecItemAdjustment = new PrintRecItemAdjustment - { - Description = adj.Description, - AdjustmentType = adj.PaymentAdjustmentType.GetAdjustmentType( adj.Amount), - Amount = Math.Abs(adj.Amount), - Department = adj.VatGroup ?? 0, - }; - PrintRecMessage? printRecMessage = null; - if (!string.IsNullOrEmpty(adj.AdditionalInformation)) - { - printRecMessage = new PrintRecMessage() - { - Message = adj.AdditionalInformation, - MessageType = 4 - }; - } - adjustmentAndMessages.Add(new() - { - PrintRecItemAdjustment = printRecItemAdjustment, - PrintRecMessage = printRecMessage - }); - } - } - return adjustmentAndMessages; - } - - public static List GetItemAndMessages(this FiscalReceiptInvoice request) - { - var itemAndMessages = new List(); - foreach (var i in request.Items) - { - var printRecItem = new PrintRecItem - { - Description = i.Description, - Quantity = i.Quantity, - UnitPrice = i.UnitPrice, - Department = i.VatGroup - }; - PrintRecMessage? printRecMessage = null; - if (!string.IsNullOrEmpty(i.AdditionalInformation)) - { - printRecMessage = new PrintRecMessage() - { - Message = i.AdditionalInformation, - MessageType = 4 - }; - } - itemAndMessages.Add(new() { PrintRecItem = printRecItem, PrintRecMessage = printRecMessage }); - } - return itemAndMessages; - } - } -} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentAdjustmentTypeExtension.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentAdjustmentTypeExtension.cs deleted file mode 100644 index a77e37caa..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentAdjustmentTypeExtension.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using fiskaltrust.ifPOS.v1.it; - -namespace fiskaltrust.Middleware.SCU.IT.Epson.Extensions -{ - public static class PaymentAdjustmentTypeExtension - { - public static int GetAdjustmentType(this PaymentAdjustmentType paymentAdjustmentType, decimal amount) - { - switch (paymentAdjustmentType) - { - case PaymentAdjustmentType.Adjustment: - return amount < 0 ? 3 : 8; - case PaymentAdjustmentType.SingleUseVoucher: - return 12; - case PaymentAdjustmentType.FreeOfCharge: - return 11; - case PaymentAdjustmentType.Acconto: - return 10; - default: - return 0; - } - } - } -} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentExtension.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentExtension.cs deleted file mode 100644 index c8c81fe42..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentExtension.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text; -using fiskaltrust.ifPOS.v1.it; - -namespace fiskaltrust.Middleware.SCU.IT.Epson.Extensions -{ - public struct EpsonPaymentType - { - public int PaymentType; - public int Index; - } - - public static class PaymentExtension - { - public static EpsonPaymentType GetEpsonPaymentType(this PaymentType paymentType) - { - switch (paymentType) - { - case PaymentType.Cash: - default: - return new EpsonPaymentType() { PaymentType = 0, Index = 0}; - case PaymentType.Cheque: - return new EpsonPaymentType() { PaymentType = 1, Index = 0 }; - case PaymentType.CreditCard: - return new EpsonPaymentType() { PaymentType = 2, Index = 0 }; - case PaymentType.Voucher: - return new EpsonPaymentType() { PaymentType = 6, Index = 1 }; - case PaymentType.NotPaid: - return new EpsonPaymentType() { PaymentType = 5, Index = 0 }; - } - } - } -} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentsExtension.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentsExtension.cs deleted file mode 100644 index 9843fdacc..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/PaymentsExtension.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; - -namespace fiskaltrust.Middleware.SCU.IT.Epson.Extensions -{ - public static class PaymentsExtension - { - - public static List GetTotalAndMessages(this List payments) - { - var totalAndMessages = new List(); - if (payments != null) - { - foreach (var pay in payments) - { - var printRecTotal = new PrintRecTotal - { - Description = pay.Description, - PaymentType = pay.PaymentType.GetEpsonPaymentType().PaymentType, - Index = pay.PaymentType.GetEpsonPaymentType().Index, - Payment = pay.Amount - }; - PrintRecMessage? printRecMessage = null; - if (!string.IsNullOrEmpty(pay.AdditionalInformation)) - { - printRecMessage = new PrintRecMessage() - { - Message = pay.AdditionalInformation, - MessageType = 4 - }; - } - totalAndMessages.Add(new() - { - PrintRecTotal = printRecTotal, - PrintRecMessage = printRecMessage - }); - } - } - if (totalAndMessages.Count == 0) - { - totalAndMessages.Add(new() - { - PrintRecTotal = new PrintRecTotal() - { - Description = PaymentType.Cash.ToString(), - PaymentType = (int) PaymentType.Cash, - Payment = 0 - }, - PrintRecMessage = null - }); - } - return totalAndMessages; - } - } -} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/StringExtension.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/StringExtension.cs deleted file mode 100644 index afc5b14bc..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Extensions/StringExtension.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace fiskaltrust.Middleware.SCU.IT.Epson.Extensions -{ - public static class StringExtension - { - public static string RemoveListObjectsForEpsonXml(this string xml) - { - return xml.Replace("\r\n", "") - .Replace("\r\n", "") - .Replace("\r\n", "") - .Replace("\r\n", "") - .Replace("\r\n", "") - .Replace("\r\n", ""); - } - } -} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/EpsonCommandFactory.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/EpsonCommandFactory.cs deleted file mode 100644 index 91264c80f..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/EpsonCommandFactory.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Xml.Serialization; -using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; -using fiskaltrust.Middleware.SCU.IT.Epson.Extensions; - - -namespace fiskaltrust.Middleware.SCU.IT.Epson.Utilities -{ - public class EpsonCommandFactory - { - private readonly EpsonScuConfiguration _epsonScuConfiguration; - - public EpsonCommandFactory(EpsonScuConfiguration epsonScuConfiguration) - { - - _epsonScuConfiguration = epsonScuConfiguration; - } - - public string CreateInvoiceRequestContent(FiscalReceiptInvoice request) - { - var fiscalReceipt = CreateFiscalReceipt(request); - if (!string.IsNullOrEmpty(request.DisplayText)) - { - fiscalReceipt.DisplayText.Add(new DisplayText() { Data = request.DisplayText }); - } - fiscalReceipt.ItemAndMessages = request.GetItemAndMessages(); - fiscalReceipt.AdjustmentAndMessages = request.GetAdjustmentAndMessages(); - return SoapSerializer.Serialize(fiscalReceipt); - } - - - public string CreateRefundRequestContent(FiscalReceiptRefund request) - { - var fiscalReceipt = CreateFiscalReceipt(request); - fiscalReceipt.PrintRecMessage = new PrintRecMessage() - { - Operator = "1", - Message = request.DisplayText, - MessageType = (int) Messagetype.AdditionalInfo - }; - fiscalReceipt.PrintRecRefund = request.Refunds.Select(GetPrintRecRefund).ToList(); - return SoapSerializer.Serialize(fiscalReceipt); - } - - public string CreateQueryPrinterStatusRequestContent() - { - var queryPrinterStatus = new QueryPrinterStatusCommand { QueryPrinterStatus = new QueryPrinterStatus { StatusType = 1 } }; - return SoapSerializer.Serialize(queryPrinterStatus); - } - - public string CreatePrintZReportRequestContent(DailyClosingRequest request) - { - var fiscalReport = new FiscalReport - { - ZReport = new ZReport { Operator = "1" }, - DisplayText = string.IsNullOrEmpty(request.DisplayText) ? null : new DisplayText() { Data = request.DisplayText } - }; - return SoapSerializer.Serialize(fiscalReport); - } - - public string CreateNonFiscalReceipt(NonFiscalRequest request) - { - var printerNonFiscal = new PrinterNonFiscal - { - PrintNormals = request.NonFiscalPrints.Select(x => new PrintNormal() { Data = x.Data, Font = x.Font }).ToList() - }; - return SoapSerializer.Serialize(printerNonFiscal); - } - - public static T? Deserialize(Stream stream) where T : class - { - var reader = new XmlSerializer(typeof(T)); - return reader.Deserialize(stream) as T; - } - - private PrintRecRefund GetPrintRecRefund(Refund recRefund) - { - if (recRefund.UnitPrice != 0 && recRefund.Quantity != 0) - { - return new PrintRecRefund - { - Description = recRefund.Description, - Quantity = recRefund.Quantity, - UnitPrice = recRefund.UnitPrice, - Department = recRefund.VatGroup - }; - } - else - { - throw new Exception("Refund properties not set properly!"); - } - } - - - private FiscalReceipt CreateFiscalReceipt(FiscalReceiptInvoice request) - { - var fiscalReceipt = new FiscalReceipt - { - LotteryID = !string.IsNullOrEmpty(request.LotteryID) ? new LotteryID() { Code = request.LotteryID} : null, - PrintBarCode = !string.IsNullOrEmpty(request.Barcode) ? new PrintBarCode() - { - Code = request.Barcode, - CodeType = _epsonScuConfiguration.CodeType, - Height = _epsonScuConfiguration.BarCodeHeight, - HRIFont = _epsonScuConfiguration.BarCodeHRIFont, - HRIPosition = _epsonScuConfiguration.BarCodeHRIPosition, - Position = _epsonScuConfiguration.BarCodePosition, - Width = _epsonScuConfiguration.BarCodeWidth - } : null - }; - fiscalReceipt.BeginFiscalReceipt.Operator = "1"; - fiscalReceipt.EndFiscalReceipt.Operator = "1"; - fiscalReceipt.RecTotalAndMessages = request.Payments.GetTotalAndMessages(); - return fiscalReceipt; - } - - private FiscalReceipt CreateFiscalReceipt(FiscalReceiptRefund request) - { - var fiscalReceipt = new FiscalReceipt - { - LotteryID = !string.IsNullOrEmpty(request.LotteryID) ? new LotteryID() { Code = request.LotteryID } : null, - PrintBarCode = !string.IsNullOrEmpty(request.Barcode) ? new PrintBarCode() - { - Code = request.Barcode, - CodeType = _epsonScuConfiguration.CodeType, - Height = _epsonScuConfiguration.BarCodeHeight, - HRIFont = _epsonScuConfiguration.BarCodeHRIFont, - HRIPosition = _epsonScuConfiguration.BarCodeHRIPosition, - Position = _epsonScuConfiguration.BarCodePosition, - Width = _epsonScuConfiguration.BarCodeWidth - } : null - }; - fiscalReceipt.BeginFiscalReceipt.Operator = "1"; - fiscalReceipt.EndFiscalReceipt.Operator = "1"; - fiscalReceipt.RecTotalAndMessages = request.Payments.GetTotalAndMessages(); - return fiscalReceipt; - } - - } -} diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/version.json b/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/version.json deleted file mode 100644 index 7c4f56080..000000000 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/version.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": "1.3.48", - "releaseBranches": [ - "^refs/tags/scu-it/epson/v\\d+(?:\\.\\d+)*(?:-.*)?$" - ] -} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Directory.Build.props b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Directory.Build.props new file mode 100644 index 000000000..e3a2a1b0e --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Directory.Build.props @@ -0,0 +1,5 @@ + + + + + diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/EpsonRTPrinterSCU.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/EpsonRTPrinterSCU.cs new file mode 100644 index 000000000..53df77218 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/EpsonRTPrinterSCU.cs @@ -0,0 +1,680 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.errors; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter; + +public sealed class EpsonRTPrinterSCU : LegacySCU +{ + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private readonly string _commandUrl; + private readonly EpsonRTPrinterSCUConfiguration _configuration; + private readonly ErrorInfoFactory _errorCodeFactory = new(); + private string _serialnr = ""; + + public EpsonRTPrinterSCU(ILogger logger, EpsonRTPrinterSCUConfiguration configuration) + { + _logger = logger; + if (string.IsNullOrEmpty(configuration.DeviceUrl)) + { + throw new NullReferenceException("EpsonScuConfiguration DeviceUrl not set."); + } + _httpClient = new HttpClient + { + BaseAddress = new Uri(configuration.DeviceUrl), + Timeout = TimeSpan.FromMilliseconds(configuration.ClientTimeoutMs) + }; + _commandUrl = $"cgi-bin/fpmate.cgi?timeout={configuration.ServerTimeoutMs}"; + _configuration = configuration; + } + + public override Task EchoAsync(ScuItEchoRequest request) => Task.FromResult(new ScuItEchoResponse { Message = request.Message }); + + public override async Task GetRTInfoAsync() + { + var result = await QueryPrinterStatusAsync(); + _logger.LogInformation(JsonConvert.SerializeObject(result)); + if (string.IsNullOrEmpty(_serialnr) && result?.Printerstatus?.RtType != null) + { + _serialnr = await GetSerialNumberAsync(result.Printerstatus.RtType).ConfigureAwait(false); + } + return new RTInfo + { + SerialNumber = _serialnr, + InfoData = JsonConvert.SerializeObject(new DeviceInfo + { + DailyOpen = result?.Printerstatus?.DailyOpen == "1", + DeviceStatus = Helpers.ParseStatus(result?.Printerstatus?.MfStatus), + ExpireDeviceCertificateDate = result?.Printerstatus?.ExpiryCD, + ExpireTACommunicationCertificateDate = result?.Printerstatus?.ExpiryCA, + SerialNumber = _serialnr + }) + }; + } + + private async Task QueryPrinterStatusAsync() + { + var queryPrinterStatus = new QueryPrinterStatusCommand { QueryPrinterStatus = new QueryPrinterStatus { StatusType = 1 } }; + var response = await _httpClient.PostAsync(_commandUrl, new StringContent(SoapSerializer.Serialize(queryPrinterStatus), Encoding.UTF8, "application/xml")); + using var responseContent = await response.Content.ReadAsStreamAsync(); + return SoapSerializer.DeserializeToSoapEnvelope(responseContent); + } + + public override async Task ProcessReceiptAsync(ProcessRequest request) + { + try + { + var receiptCase = request.ReceiptRequest.GetReceiptCase(); + if (string.IsNullOrEmpty(_serialnr)) + { + var result = await QueryPrinterStatusAsync(); + _logger.LogInformation(JsonConvert.SerializeObject(result)); + _serialnr = await GetSerialNumberAsync(result?.Printerstatus?.RtType ?? "").ConfigureAwait(false); + } + if (request.ReceiptRequest.IsInitialOperationReceipt()) + { + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, SignatureFactory.CreateInitialOperationSignatures().ToList()); + } + + if (request.ReceiptRequest.IsOutOfOperationReceipt()) + { + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, SignatureFactory.CreateOutOfOperationSignatures().ToList()); + } + + if (request.ReceiptRequest.IsZeroReceipt()) + { + (var signatures, var stateData) = await PerformZeroReceiptOperationAsync(); + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, stateData, signatures); + } + + if (request.ReceiptRequest.IsVoid()) + { + return await ProcessVoidReceipt(request); + } + + if (request.ReceiptRequest.IsRefund()) + { + return await ProcessRefundReceipt(request); + } + + if (request.ReceiptRequest.IsDailyClosing()) + { + return Helpers.CreateResponse(await PerformDailyCosing(request.ReceiptResponse)); + } + + if (request.ReceiptRequest.IsReprint()) + { + return await ProcessPerformReprint(request); + } + + if (receiptCase == (long) ITReceiptCases.Protocol0x0005) + { + return Helpers.CreateResponse(await PerformProtocolReceiptAsync(request.ReceiptRequest, request.ReceiptResponse)); + } + + switch (receiptCase) + { + case (long) ITReceiptCases.UnknownReceipt0x0000: + case (long) ITReceiptCases.PointOfSaleReceipt0x0001: + return Helpers.CreateResponse(await PerformClassicReceiptAsync(request.ReceiptRequest, request.ReceiptResponse)); + } + request.ReceiptResponse.SetReceiptResponseErrored($"The given receiptcase 0x{receiptCase.ToString("X")} is not supported by Epson RT Printer."); + return Helpers.CreateResponse(request.ReceiptResponse); + } + catch (Exception ex) + { + var signatures = new List + { + new SignaturItem + { + Caption = "epson-printer-generic-error", + Data = $"{ex}", + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = 0x4954_2000_0000_3000 + } + }; + request.ReceiptResponse.ftState |= 0xEEEE_EEEE; + return ProcessResponseHelpers.CreateResponse(request.ReceiptResponse, signatures); + } + } + + private async Task SetReceiptResponse(PrinterResponse? result) + { + var fiscalReceiptResponse = new FiscalReceiptResponse + { + Success = result?.Success ?? false + }; + if (result?.Success == false) + { + fiscalReceiptResponse.SSCDErrorInfo = GetErrorInfo(result.Code, result.Status, result?.Receipt?.PrinterStatus); + await ResetPrinter(); + } + else + { + fiscalReceiptResponse.ReceiptNumber = result?.Receipt?.FiscalReceiptNumber != null ? long.Parse(result.Receipt.FiscalReceiptNumber) : 0; + fiscalReceiptResponse.ZRepNumber = result?.Receipt?.ZRepNumber != null ? long.Parse(result.Receipt.ZRepNumber) : 0; + if (result?.Receipt?.FiscalReceiptDate != null && result?.Receipt?.FiscalReceiptTime != null) + { + fiscalReceiptResponse.ReceiptDateTime = DateTime.ParseExact(result.Receipt.FiscalReceiptDate, "d/M/yyyy", CultureInfo.InvariantCulture); + var time = TimeSpan.Parse(result.Receipt.FiscalReceiptTime); + fiscalReceiptResponse.ReceiptDateTime = fiscalReceiptResponse.ReceiptDateTime + time; + } + else + { + fiscalReceiptResponse.ReceiptDateTime = DateTime.Now; // ??????? + } + } + return fiscalReceiptResponse; + } + + public async Task PerformProtocolReceiptAsync(ReceiptRequest receiptRequest, ReceiptResponse receiptResponse) + { + try + { + var content = EpsonCommandFactory.CreateInvoiceRequestContent(_configuration, receiptRequest); + var customerData = receiptRequest.GetCustomer(); + if (customerData != null) + { + if (content.PrintRecMessageType3 == null) + { + content.PrintRecMessageType3 = new List(); + } + content.PrintRecMessageType3?.Add(new PrintRecMessage + { + MessageType = 2, + Index = "1", + Message = customerData.CustomerName ?? "" + }); + content.PrintRecMessageType3?.Add(new PrintRecMessage + { + MessageType = 2, + Index = "2", + Message = customerData.CustomerStreet ?? "" + }); + content.PrintRecMessageType3?.Add(new PrintRecMessage + { + MessageType = 2, + Index = "3", + Message = string.Format("{0} {1} {2}", customerData.CustomerCountry ?? "", customerData.CustomerZip ?? "", customerData.CustomerCity ?? "") + }); + } + + var data = SoapSerializer.Serialize(content); + _logger.LogDebug("Request content ({receiptreference}): {content}", receiptRequest.cbReceiptReference, SoapSerializer.Serialize(data)); + var response = await SendRequestAsync(data); + + using var responseContent = await response.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + if (result != null) + { + _logger.LogDebug("Response content ({receiptreference}): {content}", receiptRequest.cbReceiptReference, SoapSerializer.Serialize(result)); + } + + var fiscalReceiptResponse = await SetReceiptResponse(result); + if (!fiscalReceiptResponse.Success) + { + receiptResponse.SetReceiptResponseErrored(fiscalReceiptResponse.SSCDErrorInfo?.Info ?? ""); + return receiptResponse; + } + var posReceiptSignatur = new POSReceiptSignatureData + { + RTSerialNumber = _serialnr, + RTZNumber = fiscalReceiptResponse.ZRepNumber, + RTDocNumber = fiscalReceiptResponse.ReceiptNumber, + RTDocMoment = fiscalReceiptResponse.ReceiptDateTime, + RTDocType = "POSRECEIPT", + RTCodiceLotteria = "", + RTCustomerID = "", // Todo dread customerid from data + }; + receiptResponse.ftSignatures = SignatureFactory.CreateDocumentoCommercialeSignatures(posReceiptSignatur).ToArray(); + return receiptResponse; + } + catch (Exception e) + { + var response = Helpers.ExceptionInfo(e); + receiptResponse.SetReceiptResponseErrored(response.SSCDErrorInfo?.Info ?? ""); + return receiptResponse; + } + } + + public async Task PerformClassicReceiptAsync(ReceiptRequest receiptRequest, ReceiptResponse receiptResponse) + { + try + { + var content = EpsonCommandFactory.CreateInvoiceRequestContent(_configuration, receiptRequest); + var data = SoapSerializer.Serialize(content); + _logger.LogDebug("Request content ({receiptreference}): {content}", receiptRequest.cbReceiptReference, data); + var response = await SendRequestAsync(data); + + using var responseContent = await response.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + if (result != null) + { + _logger.LogDebug("Response content ({receiptreference}): {content}", receiptRequest.cbReceiptReference, SoapSerializer.Serialize(result)); + } + + var fiscalReceiptResponse = await SetReceiptResponse(result); + if (!fiscalReceiptResponse.Success) + { + receiptResponse.SetReceiptResponseErrored(fiscalReceiptResponse.SSCDErrorInfo?.Info ?? ""); + return receiptResponse; + } + var posReceiptSignatur = new POSReceiptSignatureData + { + RTSerialNumber = _serialnr, + RTZNumber = fiscalReceiptResponse.ZRepNumber, + RTDocNumber = fiscalReceiptResponse.ReceiptNumber, + RTDocMoment = fiscalReceiptResponse.ReceiptDateTime, + RTDocType = "POSRECEIPT", + RTCodiceLotteria = "", + RTCustomerID = "", // Todo dread customerid from data + }; + receiptResponse.ftSignatures = SignatureFactory.CreateDocumentoCommercialeSignatures(posReceiptSignatur).ToArray(); + return receiptResponse; + } + catch (Exception e) + { + var response = Helpers.ExceptionInfo(e); + receiptResponse.SetReceiptResponseErrored(response.SSCDErrorInfo?.Info ?? ""); + return receiptResponse; + } + } + + private async Task ProcessPerformReprint(ProcessRequest request) + { + var referenceZNumber = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceZNumber)?.Data; + var referenceDocNumber = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentNumber)?.Data; + var referenceDateTime = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentMoment)?.Data; + if (string.IsNullOrEmpty(referenceZNumber) || string.IsNullOrEmpty(referenceDocNumber) || string.IsNullOrEmpty(referenceDateTime)) + { + request.ReceiptResponse.SetReceiptResponseErrored("Cannot refund receipt without references."); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + + FiscalReceiptResponse fiscalResponse; + try + { + if (!string.IsNullOrEmpty(_configuration.Password)) + { + var loginResult = await LoginAsync(); + if (!loginResult.IsSuccessStatusCode) + { + throw new HttpRequestException($"An error occured while sending a request to the Epson device (StatusCode: {loginResult.StatusCode}, Content: {await loginResult.Content.ReadAsStringAsync()})"); + } + using var loginResultresponseContent = await loginResult.Content.ReadAsStreamAsync(); + var loginprinterresult = SoapSerializer.DeserializeToSoapEnvelope(loginResultresponseContent); + var loginReceiptResponse = await SetReceiptResponse(loginprinterresult); + if (!loginReceiptResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored($"Unable to login to the Printer. Please check the configured password. (Details: {loginReceiptResponse.SSCDErrorInfo?.Info ?? ""})"); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + } + + var date = DateTime.Parse(referenceDateTime); + var response = await PerformReprint(date.ToString("dd"), date.ToString("MM"), date.ToString("yy"), long.Parse(referenceDocNumber)); + using var responseContent = await response.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + var fiscalReceiptResponse = await SetReceiptResponse(result); + if (!fiscalReceiptResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored(fiscalReceiptResponse.SSCDErrorInfo?.Info ?? ""); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + fiscalResponse = fiscalReceiptResponse; + await ResetPrinter(); + } + catch (Exception e) + { + fiscalResponse = Helpers.ExceptionInfo(e); + } + + if (!fiscalResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored(fiscalResponse.SSCDErrorInfo?.Info ?? ""); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + else + { + var posReceiptSignatur = new POSReceiptSignatureData + { + RTSerialNumber = _serialnr, + RTZNumber = fiscalResponse.ZRepNumber, + RTDocNumber = fiscalResponse.ReceiptNumber, + RTDocMoment = fiscalResponse.ReceiptDateTime, + RTDocType = "Documente Gestionale", + RTCodiceLotteria = "", + RTCustomerID = "", // Todo dread customerid from data + RTReferenceZNumber = long.Parse(referenceZNumber), + RTReferenceDocNumber = long.Parse(referenceDocNumber), + RTReferenceDocMoment = DateTime.Parse(referenceDateTime) + }; + request.ReceiptResponse.ftSignatures = SignatureFactory.CreateDocumentoCommercialeSignatures(posReceiptSignatur).ToArray(); + } + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + + private async Task ProcessRefundReceipt(ProcessRequest request) + { + var referenceZNumber = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceZNumber)?.Data; + var referenceDocNumber = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentNumber)?.Data; + var referenceDateTime = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentMoment)?.Data; + if (string.IsNullOrEmpty(referenceZNumber) || string.IsNullOrEmpty(referenceDocNumber) || string.IsNullOrEmpty(referenceDateTime)) + { + request.ReceiptResponse.SetReceiptResponseErrored("Cannot refund receipt without references."); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + + FiscalReceiptResponse fiscalResponse; + try + { + + if (string.IsNullOrEmpty(_serialnr)) + { + var rtinfo = await GetRTInfoAsync(); + _serialnr = rtinfo.SerialNumber; + } + var content = EpsonCommandFactory.CreateRefundRequestContent(_configuration, request.ReceiptRequest, long.Parse(referenceDocNumber), long.Parse(referenceZNumber), DateTime.Parse(referenceDateTime), _serialnr!); + var data = SoapSerializer.Serialize(content); + _logger.LogDebug("Request content ({receiptreference}): {content}", request.ReceiptRequest.cbReceiptReference, SoapSerializer.Serialize(data)); + var response = await SendRequestAsync(data); + + using var responseContent = await response.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + if (result != null) + { + _logger.LogDebug("Response content ({receiptreference}): {content}", request.ReceiptRequest.cbReceiptReference, SoapSerializer.Serialize(result)); + } + + var fiscalReceiptResponse = await SetReceiptResponse(result); + if (!fiscalReceiptResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored(fiscalReceiptResponse.SSCDErrorInfo?.Info ?? ""); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + fiscalResponse = fiscalReceiptResponse; + } + catch (Exception e) + { + fiscalResponse = Helpers.ExceptionInfo(e); + } + + if (!fiscalResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored(fiscalResponse.SSCDErrorInfo?.Info ?? ""); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + else + { + var posReceiptSignatur = new POSReceiptSignatureData + { + RTSerialNumber = _serialnr, + RTZNumber = fiscalResponse.ZRepNumber, + RTDocNumber = fiscalResponse.ReceiptNumber, + RTDocMoment = fiscalResponse.ReceiptDateTime, + RTDocType = "REFUND", + RTCodiceLotteria = "", + RTCustomerID = "", // Todo dread customerid from data + RTReferenceZNumber = long.Parse(referenceZNumber), + RTReferenceDocNumber = long.Parse(referenceDocNumber), + RTReferenceDocMoment = DateTime.Parse(referenceDateTime) + }; + request.ReceiptResponse.ftSignatures = SignatureFactory.CreateDocumentoCommercialeSignatures(posReceiptSignatur).ToArray(); + } + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + + private async Task ProcessVoidReceipt(ProcessRequest request) + { + var referenceZNumber = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceZNumber)?.Data; + var referenceDocNumber = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentNumber)?.Data; + var referenceDateTime = request.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTReferenceDocumentMoment)?.Data; + if (string.IsNullOrEmpty(referenceZNumber) || string.IsNullOrEmpty(referenceDocNumber) || string.IsNullOrEmpty(referenceDateTime)) + { + request.ReceiptResponse.SetReceiptResponseErrored("Cannot void receipt without references."); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + FiscalReceiptResponse fiscalResponse; + try + { + + if (string.IsNullOrEmpty(_serialnr)) + { + var rtinfo = await GetRTInfoAsync(); + _serialnr = rtinfo.SerialNumber; + } + var content = EpsonCommandFactory.CreateVoidRequestContent(_configuration, request.ReceiptRequest, long.Parse(referenceDocNumber), long.Parse(referenceZNumber), DateTime.Parse(referenceDateTime), _serialnr!); + var data = SoapSerializer.Serialize(content); + _logger.LogDebug("Request content ({receiptreference}): {content}", request.ReceiptRequest.cbReceiptReference, SoapSerializer.Serialize(data)); + var response = await SendRequestAsync(data); + + using var responseContent = await response.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + if (result != null) + { + _logger.LogDebug("Response content ({receiptreference}): {content}", request.ReceiptRequest.cbReceiptReference, SoapSerializer.Serialize(result)); + } + var fiscalReceiptResponse = await SetReceiptResponse(result); + if (!fiscalReceiptResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored(fiscalReceiptResponse.SSCDErrorInfo?.Info ?? ""); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + fiscalResponse = fiscalReceiptResponse; + } + catch (Exception e) + { + fiscalResponse = Helpers.ExceptionInfo(e); + } + + if (!fiscalResponse.Success) + { + request.ReceiptResponse.SetReceiptResponseErrored(fiscalResponse.SSCDErrorInfo?.Info ?? ""); + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + else + { + var posReceiptSignatur = new POSReceiptSignatureData + { + RTSerialNumber = _serialnr, + RTZNumber = fiscalResponse.ZRepNumber, + RTDocNumber = fiscalResponse.ReceiptNumber, + RTDocMoment = fiscalResponse.ReceiptDateTime, + RTDocType = "VOID", + RTCodiceLotteria = "", + RTCustomerID = "", // Todo dread customerid from data + RTReferenceZNumber = long.Parse(referenceZNumber), + RTReferenceDocNumber = long.Parse(referenceDocNumber), + RTReferenceDocMoment = DateTime.Parse(referenceDateTime) + }; + request.ReceiptResponse.ftSignatures = SignatureFactory.CreateDocumentoCommercialeSignatures(posReceiptSignatur).ToArray(); + } + return new ProcessResponse + { + ReceiptResponse = request.ReceiptResponse + }; + } + + private async Task GetSerialNumberAsync(string rtType) + { + var serialQuery = new PrinterCommand() { DirectIO = DirectIO.GetSerialNrCommand() }; + var content = SoapSerializer.Serialize(serialQuery); + var responseSerialnr = await SendRequestAsync(content); + + using var responseContent = await responseSerialnr.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + + var serialnr = result?.CommandResponse?.ResponseData; + return serialnr?.Substring(10, 2) + rtType + serialnr?.Substring(8, 2) + serialnr?.Substring(2, 6); + } + + private async Task ResetPrinter() + { + var resetCommand = new PrinterCommand() { ResetPrinter = new ResetPrinter() { Operator = "" } }; + var xml = SoapSerializer.Serialize(resetCommand); + await SendRequestAsync(xml); + } + + private async Task PerformDailyCosing(ReceiptResponse receiptResponse) + { + try + { + var fiscalReport = new FiscalReport + { + ZReport = new ZReport() + }; + var response = await SendRequestAsync(SoapSerializer.Serialize(fiscalReport)); + using var responseContent = await response.Content.ReadAsStreamAsync(); + var result = SoapSerializer.DeserializeToSoapEnvelope(responseContent); + if (!result?.Success ?? false) + { + var errorInfo = GetErrorInfo(result?.Code, result?.Status, null); + await ResetPrinter(); + receiptResponse.SetReceiptResponseErrored(errorInfo.Info); + return receiptResponse; + } + + var zRepNumber = result?.ReportInfo?.ZRepNumber != null ? long.Parse(result.ReportInfo.ZRepNumber) : 0; + receiptResponse.ftSignatures = SignatureFactory.CreateDailyClosingReceiptSignatures(zRepNumber); + return receiptResponse; + } + catch (Exception e) + { + receiptResponse.SetReceiptResponseErrored(e.Message); + return receiptResponse; + } + } + + private async Task<(List signaturItems, string ftStateData)> PerformZeroReceiptOperationAsync() + { + await ResetPrinter(); + var result = await QueryPrinterStatusAsync(); + var signatures = SignatureFactory.CreateZeroReceiptSignatures().ToList(); + var stateData = JsonConvert.SerializeObject(new + { + PrinterStatus = result + }); + return (signatures, stateData); + } + + private async Task LoginAsync() + { + var password = (_configuration.Password ?? "").PadRight(100, ' ').PadRight(32, ' '); + var data = $""" + + + + + + + + +"""; + return await SendRequestAsync(data); + } + + private async Task PerformReprint(string day, string month, string year, long receiptNumber) + { + var data = $""" + + + + + + + + +"""; + return await SendRequestAsync(data); + } + + private async Task SendRequestAsync(string content) + { + var response = await _httpClient.PostAsync(_commandUrl, new StringContent(content, Encoding.UTF8, "application/xml")); + if (!response.IsSuccessStatusCode) + { + throw new HttpRequestException($"An error occured while sending a request to the Epson device (StatusCode: {response.StatusCode}, Content: {await response.Content.ReadAsStringAsync()})"); + } + return response; + } + + public SSCDErrorInfo GetErrorInfo(string? code, string? status, string? printerStatus) + { + var errorInf = string.Empty; + if (code != null) + { + errorInf += $"\n Error Code {code}: {_errorCodeFactory.GetCodeInfo(code)} "; + } + if (status != null) + { + errorInf += $"\n Status {status}: {_errorCodeFactory.GetStatusInfo(int.Parse(status))}"; + } + var state = Helpers.GetPrinterStatus(printerStatus); + if (state != null) + { + errorInf += $"\n Printer state {state}"; + } + _logger.LogError(errorInf); + return new SSCDErrorInfo() { Info = errorInf, Type = SSCDErrorType.Device }; + } +} + + + +public class FiscalReceiptResponse +{ + public bool Success { get; set; } + public SSCDErrorInfo? SSCDErrorInfo { get; set; } + public DateTime ReceiptDateTime { get; set; } + public long ReceiptNumber { get; set; } + public long ZRepNumber { get; set; } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/EpsonRTPrinterSCUConfiguration.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/EpsonRTPrinterSCUConfiguration.cs new file mode 100644 index 000000000..84afb5cb8 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/EpsonRTPrinterSCUConfiguration.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter +{ + public class EpsonRTPrinterSCUConfiguration + { + /// + /// The URL or IP address of the RT Printer or Server, e.g. http://192.168.0.100 + /// + public string? DeviceUrl { get; set; } + + /// + /// The HTTP client timeout used when communicating with the RT Printer or Server + /// + public int ClientTimeoutMs { get; set; } = 15000; + + /// + /// The server/printer timeout for executing commands + /// + public int ServerTimeoutMs { get; set; } = 10000; + + public string? Password { get; set; } + + public List AdditionalTrailerLines { get; set;} = new List(); + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Helpers.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Helpers.cs new file mode 100644 index 000000000..17b9c91bc --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Helpers.cs @@ -0,0 +1,72 @@ +using System; +using System.Net; +using System.Net.Http; +using System.ServiceModel; +using System.Threading.Tasks; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.errors; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter; + +public class Helpers +{ + public static ProcessResponse CreateResponse(ReceiptResponse receiptResponse) + { + return new ProcessResponse + { + ReceiptResponse = receiptResponse + }; + } + + public static FiscalReceiptResponse ExceptionInfo(Exception e) + { + var msg = e.Message; + if (e.InnerException != null) + { + msg += " " + e.InnerException.Message; + } + if (IsConnectionException(e)) + { + return new FiscalReceiptResponse() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.Connection } }; + } + return new FiscalReceiptResponse() { Success = false, SSCDErrorInfo = new SSCDErrorInfo() { Info = msg, Type = SSCDErrorType.General } }; + } + + public static bool IsConnectionException(Exception e) + { + if (e.GetType().IsAssignableFrom(typeof(EndpointNotFoundException)) || + e.GetType().IsAssignableFrom(typeof(WebException)) || + e.GetType().IsAssignableFrom(typeof(CommunicationException)) || + e.GetType().IsAssignableFrom(typeof(TaskCanceledException)) || + e.GetType().IsAssignableFrom(typeof(HttpRequestException))) + { + return true; + } + return false; + } + + public static string? GetPrinterStatus(string? printerStatus) + { + var pst = printerStatus?.ToCharArray(); + if (pst != null) + { + var printerstatus = new DeviceStatus(Array.ConvertAll(pst, c => (int) char.GetNumericValue(c))); + return JsonConvert.SerializeObject(printerstatus); + } + + return null; + } + + public static string ParseStatus(string? mfStatus) + { + return mfStatus switch + { + "01" => "Not in service", + "02" => "In service", + _ => "Undefined" + }; + } +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/DeviceStatus.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/DeviceStatus.cs similarity index 99% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/DeviceStatus.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/DeviceStatus.cs index f2177e7d2..de8d74b00 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/DeviceStatus.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/DeviceStatus.cs @@ -2,7 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { /// /// Byte 1: DeviceStatus, from STATUS given by the 5 bytes Alphanumeric diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ErrorInfoFactory.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/ErrorInfoFactory.cs similarity index 94% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ErrorInfoFactory.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/ErrorInfoFactory.cs index dfddfa239..f57bd2c1f 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ErrorInfoFactory.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/ErrorInfoFactory.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { public class ErrorInfoFactory { @@ -65,14 +65,8 @@ public class ErrorInfoFactory { 42, "TIPO NON VALIDO (DOC di RESO) - Reference document cannot be a refund document. It must a commercial document." }, }; - public string GetCodeInfo(string code) - { - return _epsonErrorCodes.ContainsKey(code) ? _epsonErrorCodes[code] : string.Empty; - } + public string GetCodeInfo(string code) => _epsonErrorCodes.ContainsKey(code) ? _epsonErrorCodes[code] : string.Empty; - public string GetStatusInfo(int status) - { - return _epsonErrorStatus.ContainsKey(status) ? _epsonErrorStatus[status] : string.Empty; - } + public string GetStatusInfo(int status) => _epsonErrorStatus.ContainsKey(status) ? _epsonErrorStatus[status] : string.Empty; } } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/FiscalReceipt.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/FiscalReceipt.cs similarity index 62% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/FiscalReceipt.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/FiscalReceipt.cs index 405253a79..44f0bd205 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/FiscalReceipt.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/FiscalReceipt.cs @@ -1,8 +1,8 @@ using System.Xml.Serialization; using System.Collections.Generic; -using fiskaltrust.Middleware.SCU.IT.Epson.Utilities; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { public enum Messagetype { @@ -16,29 +16,18 @@ public enum Messagetype public class LotteryID { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "code")] public string? Code { get; set; } public static LotteryID FromString(string code) => new() { Code = code }; } - [XmlType("displayText")] - public class DisplayText - { - [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } - [XmlAttribute(AttributeName = "data")] - public string? Data { get; set; } - - public static DisplayText FromString(string data) => new() { Data = data }; - } - [XmlType("printRecMessage")] public class PrintRecMessage { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "messageType")] public int MessageType { get; set; } [XmlAttribute(AttributeName = "index")] @@ -47,17 +36,15 @@ public class PrintRecMessage public string? Font { get; set; } [XmlAttribute(AttributeName = "message")] public string? Message { get; set; } - [XmlAttribute(AttributeName = "comment")] - public string? Comment { get; set; } } [XmlRoot(ElementName = "beginFiscalReceipt")] public class BeginFiscalReceipt { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; } - + public class TotalAndMessage { [XmlElement(ElementName = "printRecMessage")] @@ -74,6 +61,12 @@ public class ItemAndMessage [XmlElement(ElementName = "printRecItem")] public PrintRecItem? PrintRecItem { get; set; } + + [XmlElement(ElementName = "printRecItemAdjustment")] + public PrintRecItemAdjustment? PrintRecItemAdjustment { get; set; } + + [XmlElement(ElementName = "printRecVoidItem")] + public PrintRecVoidItem? PrintRecVoidItem { get; set; } } public class AdjustmentAndMessage @@ -89,7 +82,7 @@ public class AdjustmentAndMessage public class PrintRecItem { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "description")] public string? Description { get; set; } [XmlIgnore] @@ -132,7 +125,141 @@ public string UnitPriceStr public class PrintRecRefund { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; set; } = "1"; + [XmlAttribute(AttributeName = "description")] + public string? Description { get; set; } + [XmlIgnore] + public decimal Quantity { get; set; } + [XmlAttribute(AttributeName = "quantity")] + public string QuantityStr + { + get => Quantity.ToString(EpsonFormatters.QuantityFormatter); + + set + { + if (decimal.TryParse(value, out var quantity)) + { + Quantity = quantity; + } + } + } + [XmlIgnore] + public decimal UnitPrice { get; set; } + [XmlAttribute(AttributeName = "unitPrice")] + public string UnitPriceStr + { + get => UnitPrice.ToString(EpsonFormatters.CurrencyFormatter); + set + { + if (decimal.TryParse(value, out var unitPrice)) + { + UnitPrice = unitPrice; + } + } + } + [XmlIgnore] + public decimal? Amount { get; set; } + [XmlAttribute(AttributeName = "amount")] + public string? AmountStr + { + get => Amount.HasValue ? Amount.Value.ToString(EpsonFormatters.CurrencyFormatter) : null; + + set + { + if (decimal.TryParse(value, out var amount)) + { + Amount = amount; + } + } + } + [XmlIgnore] + public int? OperationType { get; set; } + + [XmlAttribute(AttributeName = "operationType")] + public string? OperationTypeStr + { + get => OperationType.HasValue ? OperationType.ToString() : null; + + set + { + if (int.TryParse(value, out var operationType)) + { + OperationType = operationType; + } + } + } + [XmlAttribute(AttributeName = "department")] + public int Department { get; set; } + [XmlAttribute(AttributeName = "justification")] + public int Justification { get; set; } = 1; + } + + + [XmlRoot(ElementName = "printRecVoidItem")] + public class PrintRecVoidItem + { + [XmlAttribute(AttributeName = "operator")] + public string? Operator { get; } = "1"; + [XmlAttribute(AttributeName = "description")] + public string? Description { get; set; } + [XmlIgnore] + public decimal Quantity { get; set; } + [XmlAttribute(AttributeName = "quantity")] + public string QuantityStr + { + get => Quantity.ToString(EpsonFormatters.QuantityFormatter); + + set + { + if (decimal.TryParse(value, out var quantity)) + { + Quantity = quantity; + } + } + } + [XmlIgnore] + public decimal UnitPrice { get; set; } + [XmlAttribute(AttributeName = "unitPrice")] + public string UnitPriceStr + { + get => UnitPrice.ToString(EpsonFormatters.CurrencyFormatter); + set + { + if (decimal.TryParse(value, out var unitPrice)) + { + UnitPrice = unitPrice; + } + } + } + + [XmlIgnore] + public int? OperationType { get; set; } + + [XmlAttribute(AttributeName = "operationType")] + public string? OperationTypeStr + { + get => OperationType.HasValue ? OperationType.ToString() : null; + + set + { + if (int.TryParse(value, out var operationType)) + { + OperationType = operationType; + } + } + } + [XmlAttribute(AttributeName = "department")] + public int Department { get; set; } + [XmlAttribute(AttributeName = "justification")] + public int Justification { get; set; } = 1; + } + + + [XmlRoot(ElementName = "printRecVoid")] + public class PrintRecVoid + { + [XmlAttribute(AttributeName = "operator")] + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "description")] public string? Description { get; set; } [XmlIgnore] @@ -205,7 +332,7 @@ public string? OperationTypeStr public class PrintRecItemAdjustment { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "description")] public string? Description { get; set; } [XmlAttribute(AttributeName = "adjustmentType")] @@ -227,15 +354,13 @@ public string? AmountStr } [XmlAttribute(AttributeName = "department")] public int Department { get; set; } - [XmlAttribute(AttributeName = "justification")] - public int Justification { get; set; } = 1; } [XmlRoot(ElementName = "printRecSubtotalAdjustment")] public class PrintRecSubtotalAdjustment { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "description")] public string? Description { get; set; } @@ -271,37 +396,25 @@ public string AmountStr public class PrintRecSubtotal { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "option")] public int Option { get; set; } = 0; } - [XmlRoot(ElementName = "printBarCode")] - public class PrintBarCode + [XmlRoot(ElementName = "directIO")] + public class DirectIOCommand { - [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } - [XmlAttribute(AttributeName = "position")] - public int Position { get; set; } - [XmlAttribute(AttributeName = "width")] - public int Width { get; set; } - [XmlAttribute(AttributeName = "height")] - public int Height { get; set; } - [XmlAttribute(AttributeName = "hRIPosition")] - public int HRIPosition { get; set; } - [XmlAttribute(AttributeName = "hRIFont")] - public char HRIFont { get; set; } - [XmlAttribute(AttributeName = "codeType")] - public string? CodeType { get; set; } - [XmlAttribute(AttributeName = "code")] - public string? Code { get; set; } + [XmlAttribute(AttributeName = "command")] + public string? Command { get; set; } + [XmlAttribute(AttributeName = "data")] + public string? Data { get; set; } } [XmlRoot(ElementName = "printRecTotal")] public class PrintRecTotal { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlAttribute(AttributeName = "description")] public string? Description { get; set; } @@ -335,47 +448,49 @@ public string PaymentStr public class EndFiscalReceipt { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; } [XmlRoot(ElementName = "printerFiscalReceipt")] public class FiscalReceipt { - [XmlElement(ElementName = "displayText")] - public List DisplayText { get; set; } = new List(); + [XmlElement(ElementName = "printRecMessage", Order = 1)] + public List? PrintRecMessageType4 { get; set; } - [XmlElement(ElementName = "printRecMessage")] - public PrintRecMessage? PrintRecMessage { get; set; } - - [XmlElement(ElementName = "beginFiscalReceipt")] + [XmlElement(ElementName = "beginFiscalReceipt", Order = 2)] public BeginFiscalReceipt BeginFiscalReceipt { get; set; } = new BeginFiscalReceipt(); - [XmlElement(ElementName = "NotExistingOnEpsonItemMsg")] + [XmlElement(ElementName = "printRecMessage", Order = 3)] + public List? PrintRecMessageType3 { get; set; } = new List(); + + [XmlElement(ElementName = "NotExistingOnEpsonItemMsg", Order = 4)] public List ItemAndMessages { get; set; } = new List(); - [XmlElement(ElementName = "printRecRefund")] + [XmlElement(ElementName = "printRecRefund", Order = 5)] public List PrintRecRefund { get; set; } = new List(); - [XmlElement(ElementName = "NotExistingOnEpsonAdjMsg")] + [XmlElement(ElementName = "printRecVoid", Order = 6)] + public List PrintRecVoid { get; set; } = new List(); + + [XmlElement(ElementName = "NotExistingOnEpsonAdjMsg", Order = 7)] public List AdjustmentAndMessages { get; set; } = new List(); - [XmlElement(ElementName = "printRecSubtotalAdjustment")] + [XmlElement(ElementName = "printRecSubtotalAdjustment", Order = 8 )] public List? PrintRecSubtotalAdjustment { get; set; } - [XmlElement(ElementName = "printRecSubtotal")] + [XmlElement(ElementName = "printRecSubtotal", Order = 9)] public PrintRecSubtotal? PrintRecSubtotal { get; set; } - [XmlElement(ElementName = "printBarCode")] - public PrintBarCode? PrintBarCode { get; set; } - - [XmlElement(ElementName = "printRecLotteryID")] + [XmlElement(ElementName = "printRecLotteryID", Order = 10)] public LotteryID? LotteryID { get; set; } - [XmlElement(ElementName = "NotExistingOnEpsonTotalMsg")] + [XmlElement(ElementName = "NotExistingOnEpsonTotalMsg", Order = 11)] public List RecTotalAndMessages { get; set; } = new List(); - [XmlElement(ElementName = "endFiscalReceipt")] - public EndFiscalReceipt EndFiscalReceipt { get; set; }= new EndFiscalReceipt(); - } + [XmlElement(ElementName = "directIO", Order = 12)] + public List DirectIOCommands { get; set; } = new List(); + [XmlElement(ElementName = "endFiscalReceipt", Order = 13)] + public EndFiscalReceipt EndFiscalReceipt { get; set; } = new EndFiscalReceipt(); + } } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/FiscalReport.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/FiscalReport.cs similarity index 82% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/FiscalReport.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/FiscalReport.cs index a8aa14618..928d09d9e 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/FiscalReport.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/FiscalReport.cs @@ -1,24 +1,20 @@ using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("printerFiscalReport")] public class FiscalReport { - [XmlElement(ElementName = "displayText")] - public DisplayText? DisplayText { get; set; } - [XmlElement(ElementName = "printZReport")] public ZReport? ZReport { get; set; } - } [XmlType("printZReport")] public class ZReport { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlIgnore] public int? Timeout { get; set; } @@ -42,14 +38,14 @@ public string? TimeoutStr public class XReport { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; } [XmlType("printXZReport")] public class XZReport { [XmlAttribute(AttributeName = "operator")] - public string? Operator { get; set; } + public string? Operator { get; } = "1"; [XmlIgnore] public int? Timeout { get; set; } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/NonFiscal.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/NonFiscal.cs similarity index 95% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/NonFiscal.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/NonFiscal.cs index 044069bc4..4462e7948 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/NonFiscal.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/NonFiscal.cs @@ -3,7 +3,7 @@ using System.Text; using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("beginNonFiscal")] public class BeginNonFiscal diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/PrinterCommand.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/PrinterCommand.cs similarity index 96% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/PrinterCommand.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/PrinterCommand.cs index 8d415688e..2e7029c80 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/PrinterCommand.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/PrinterCommand.cs @@ -1,6 +1,6 @@ using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("printerCommand")] public class PrinterCommand diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ReceiptResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/PrinterResponse.cs similarity index 92% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ReceiptResponse.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/PrinterResponse.cs index e536fd7fb..ceac83ddf 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ReceiptResponse.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/PrinterResponse.cs @@ -1,9 +1,9 @@ using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("response")] - public class ReceiptResponse + public class PrinterResponse { [XmlAttribute(AttributeName = "success")] public bool Success { get; set; } diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/QueryPrinterStatusCommand.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/QueryPrinterStatusCommand.cs similarity index 89% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/QueryPrinterStatusCommand.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/QueryPrinterStatusCommand.cs index f6c2ebdf1..cb02c1934 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/QueryPrinterStatusCommand.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/QueryPrinterStatusCommand.cs @@ -1,6 +1,6 @@ using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("printerCommand")] public class QueryPrinterStatusCommand diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ReportResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/ReportResponse.cs similarity index 93% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ReportResponse.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/ReportResponse.cs index 0aab09ee3..51c040a9a 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/ReportResponse.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/ReportResponse.cs @@ -1,6 +1,6 @@ using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("response")] public class ReportResponse diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/SoapEnvelope.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/SoapEnvelope.cs similarity index 73% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/SoapEnvelope.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/SoapEnvelope.cs index 0a0373f2e..a8f25c5c0 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/SoapEnvelope.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/SoapEnvelope.cs @@ -5,7 +5,7 @@ using System.Xml.Schema; using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public class SoapEnvelope where T : class @@ -22,12 +22,7 @@ public class SoapBody : IXmlSerializable where T : class public void ReadXml(XmlReader reader) { - var innerTypeName = typeof(T).GetCustomAttribute()?.TypeName; - if(innerTypeName == null) - { - throw new InvalidOperationException("Could not deserialize the device's response, because the given type does not have the XmlType attribute specified."); - } - + var innerTypeName = (typeof(T).GetCustomAttribute()?.TypeName) ?? throw new InvalidOperationException("Could not deserialize the device's response, because the given type does not have the XmlType attribute specified."); reader.ReadToDescendant(innerTypeName); var serializer = new XmlSerializer(typeof(T)); Value = serializer.Deserialize(reader) as T; diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/StatusResponse.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/StatusResponse.cs similarity index 97% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/StatusResponse.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/StatusResponse.cs index 5302fe387..b27dfb8d3 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Models/StatusResponse.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Models/StatusResponse.cs @@ -1,6 +1,6 @@ using System.Xml.Serialization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Models +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models { [XmlType("response")] public class StatusResponse diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/ScuBootstrapper.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/ScuBootstrapper.cs similarity index 70% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/ScuBootstrapper.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/ScuBootstrapper.cs index 78c8779e3..412373d5d 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/ScuBootstrapper.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/ScuBootstrapper.cs @@ -2,11 +2,10 @@ using System.Collections.Generic; using fiskaltrust.ifPOS.v1.it; using fiskaltrust.Middleware.Abstractions; -using fiskaltrust.Middleware.SCU.IT.Epson.Utilities; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; -namespace fiskaltrust.Middleware.SCU.IT.Epson +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter { public class ScuBootstrapper : IMiddlewareBootstrapper { @@ -15,12 +14,11 @@ public class ScuBootstrapper : IMiddlewareBootstrapper public void ConfigureServices(IServiceCollection serviceCollection) { - var epsonScuConfig = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(Configuration)); + var epsonScuConfig = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(Configuration)); _ = serviceCollection .AddSingleton(epsonScuConfig) - .AddScoped() - .AddScoped(); + .AddScoped(); } } } \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/EpsonCommandFactory.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/EpsonCommandFactory.cs new file mode 100644 index 000000000..e9c61fda7 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/EpsonCommandFactory.cs @@ -0,0 +1,461 @@ +using System; +using System.Linq; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using System.Collections.Generic; + +#pragma warning disable + +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities +{ + public static class EpsonCommandFactory + { + public static FiscalReceipt CreateInvoiceRequestContent(EpsonRTPrinterSCUConfiguration configuration, ReceiptRequest receiptRequest) + { + // TODO check for lottery ID + var fiscalReceipt = new FiscalReceipt(); + fiscalReceipt.ItemAndMessages = GetItemAndMessages(receiptRequest); + fiscalReceipt.AdjustmentAndMessages = new List(); + fiscalReceipt.RecTotalAndMessages = GetTotalAndMessages(receiptRequest); + var customerData = receiptRequest.GetCustomer(); + if (customerData != null) + { + if (!string.IsNullOrEmpty(customerData.CustomerVATId)) + { + var vat = customerData.CustomerVATId!; + if (vat.ToUpper().StartsWith("IT")) + { + vat = vat.Substring(2); + } + if (vat.Length == 11) + { + fiscalReceipt.DirectIOCommands.Add(new DirectIO + { + Command = "1060", + Data = "01" + vat, + }); + } + } + } + AddTrailerLines(configuration, receiptRequest, fiscalReceipt); + return fiscalReceipt; + } + + private static void AddTrailerLines(EpsonRTPrinterSCUConfiguration configuration, ReceiptRequest receiptRequest, FiscalReceipt fiscalReceipt) + { + var index = 1; + foreach (var trailerLine in configuration.AdditionalTrailerLines) + { + var data = trailerLine.Replace("{cbArea}", receiptRequest.cbArea).Replace("{cbUser}", receiptRequest.cbUser); + fiscalReceipt.PrintRecMessageType3?.Add(new PrintRecMessage + { + MessageType = 3, + Index = index.ToString(), + Font = "1", + Message = data + }); + index++; + } + } + + public static FiscalReceipt CreateRefundRequestContent(EpsonRTPrinterSCUConfiguration configuration, ReceiptRequest receiptRequest, long referenceDocNumber, long referenceZNumber, DateTime referenceDateTime, string serialNr) + { + var fiscalReceipt = new FiscalReceipt + { + PrintRecMessageType4 = new List + { + new PrintRecMessage() + { + Message = $"REFUND {referenceZNumber:D4} {referenceDocNumber:D4} {referenceDateTime:ddMMyyyy} {serialNr}", + MessageType = (int) Messagetype.AdditionalInfo + } + }, + PrintRecRefund = GetRecRefunds(receiptRequest), + AdjustmentAndMessages = new List(), + RecTotalAndMessages = GetTotalAndMessages(receiptRequest) + }; + var customerData = receiptRequest.GetCustomer(); + if (customerData != null) + { + if (!string.IsNullOrEmpty(customerData.CustomerVATId)) + { + var vat = customerData.CustomerVATId!; + if (vat.ToUpper().StartsWith("IT")) + { + vat = vat.Substring(2); + } + if (vat.Length == 11) + { + fiscalReceipt.DirectIOCommands.Add(new DirectIO + { + Command = "1060", + Data = "01" + vat, + }); + } + } + } + AddTrailerLines(configuration, receiptRequest, fiscalReceipt); + return fiscalReceipt; + } + + public static FiscalReceipt CreateVoidRequestContent(EpsonRTPrinterSCUConfiguration configuration, ReceiptRequest receiptRequest, long referenceDocNumber, long referenceZNumber, DateTime referenceDateTime, string serialNr) + { + var fiscalReceipt = new FiscalReceipt + { + PrintRecMessageType4 = new List + { + new PrintRecMessage() + { + Message = $"VOID {referenceZNumber:D4} {referenceDocNumber:D4} {referenceDateTime:ddMMyyyy} {serialNr}", + MessageType = (int) Messagetype.AdditionalInfo + } + }, + PrintRecVoid = GetRecvoids(receiptRequest), + AdjustmentAndMessages = new List(), + RecTotalAndMessages = GetTotalAndMessages(receiptRequest) + }; + var customerData = receiptRequest.GetCustomer(); + if (customerData != null) + { + if (!string.IsNullOrEmpty(customerData.CustomerVATId)) + { + var vat = customerData.CustomerVATId!; + if (vat.ToUpper().StartsWith("IT")) + { + vat = vat.Substring(2); + } + if (vat.Length == 11) + { + fiscalReceipt.DirectIOCommands.Add(new DirectIO + { + Command = "1060", + Data = "01" + vat, + }); + } + } + } + AddTrailerLines(configuration, receiptRequest, fiscalReceipt); + return fiscalReceipt; + } + + public static List GetRecRefunds(ReceiptRequest receiptRequest) + { + return receiptRequest.cbChargeItems?.Select(p => new PrintRecRefund + { + Description = p.Description, + Quantity = Math.Abs(p.Quantity), + UnitPrice = p.Quantity == 0 || p.Amount == 0 ? 0 : Math.Abs(p.Amount) / Math.Abs(p.Quantity), + Amount = Math.Abs(p.Amount), + Department = p.GetVatGroup() + }).ToList(); + } + + public static List GetRecvoids(ReceiptRequest receiptRequest) + { + return receiptRequest.cbChargeItems?.Select(p => new PrintRecVoid + { + Description = p.Description, + Quantity = Math.Abs(p.Quantity), + UnitPrice = p.Quantity == 0 || p.Amount == 0 ? 0 : Math.Abs(p.Amount) / Math.Abs(p.Quantity), + Amount = Math.Abs(p.Amount), + Department = p.GetVatGroup() + }).ToList(); + } + + public static List GetItemAndMessages(ReceiptRequest receiptRequest) + { + var itemAndMessages = new List(); + if (receiptRequest.IsGroupingRequest()) + { + var chargeItemGroups = receiptRequest.cbChargeItems.GroupBy(x => x.Position / 100); + foreach (var chargeItemGroup in chargeItemGroups) + { + var mainItem = chargeItemGroup.FirstOrDefault(x => x.Position % 100 == 0); + if (mainItem.Quantity == 0 || mainItem.Amount == 0) + { + itemAndMessages.Add(new() + { + PrintRecMessage = new PrintRecMessage() + { + Message = mainItem.Description, + MessageType = 4 + } + }); + + foreach (var chargeItem in chargeItemGroup.Where(x => x != mainItem)) + { + if (chargeItem.Amount == 0 || chargeItem.Quantity == 0) + { + itemAndMessages.Add(new() + { + PrintRecMessage = new PrintRecMessage() + { + Message = chargeItem.Description, + MessageType = 4 + } + }); + } + else + { + if (chargeItem.Amount < 0) + { + itemAndMessages.Add(new() + { + PrintRecVoidItem = new PrintRecVoidItem() + { + Description = chargeItem.Description, + Quantity = Math.Abs(chargeItem.Quantity), + UnitPrice = chargeItem.Quantity == 0 || chargeItem.Amount == 0 ? 0 : Math.Abs(chargeItem.Amount) / Math.Abs(chargeItem.Quantity), + Department = chargeItem.GetVatGroup() + } + }); + } + else + { + GenerateItems(itemAndMessages, chargeItem); + } + } + } + } + else + { + GenerateItems(itemAndMessages, mainItem); + foreach (var chargeItem in chargeItemGroup.Where(x => x != mainItem)) + { + if (chargeItem.Amount == 0 || chargeItem.Quantity == 0) + { + itemAndMessages.Add(new() + { + PrintRecMessage = new PrintRecMessage() + { + Message = chargeItem.Description, + MessageType = 4 + } + }); + } + else + { + if (chargeItem.Amount < 0) + { + itemAndMessages.Add(new() + { + PrintRecVoidItem = new PrintRecVoidItem() + { + Description = chargeItem.Description, + Quantity = Math.Abs(chargeItem.Quantity), + UnitPrice = chargeItem.Quantity == 0 || chargeItem.Amount == 0 ? 0 : Math.Abs(chargeItem.Amount) / Math.Abs(chargeItem.Quantity), + Department = chargeItem.GetVatGroup() + } + }); + + + //itemAndMessages.Add(new() + //{ + // PrintRecItemAdjustment = new PrintRecItemAdjustment() + // { + // AdjustmentType = 0, + // Amount = Math.Abs(chargeItem.Amount), + // Department = chargeItem.GetVatGroup(), + // Description = chargeItem.Description + // } + //}); + } + else + { + itemAndMessages.Add(new() + { + PrintRecItemAdjustment = new PrintRecItemAdjustment() + { + AdjustmentType = 5, + Amount = chargeItem.Amount, + Department = chargeItem.GetVatGroup(), + Description = chargeItem.Description + } + }); + } + } + } + } + } + } + else + { + // Todo handle payment adjustments / discounts + foreach (var i in receiptRequest.cbChargeItems) + { + GenerateItems(itemAndMessages, i); + } + } + return itemAndMessages; + } + + private static void GenerateItems(List itemAndMessages, ChargeItem? i) + { + if (i.Amount == 0 || i.Quantity == 0) + { + itemAndMessages.Add(new() + { + PrintRecMessage = new PrintRecMessage() + { + Message = i.Description, + MessageType = 4 + } + }); + } + else + { + if (i.IsTip()) + { + var printRecItem = new PrintRecItem + { + Description = i.Description, + Quantity = i.Quantity, + UnitPrice = i.Quantity == 0 || i.Amount == 0 ? 0 : i.Amount / i.Quantity, + Department = 11, + }; + PrintRecMessage? printRecMessage = null; + if (!string.IsNullOrEmpty(i.ftChargeItemCaseData)) + { + printRecMessage = new PrintRecMessage() + { + Message = i.ftChargeItemCaseData, + MessageType = 4 + }; + } + itemAndMessages.Add(new() { PrintRecItem = printRecItem, PrintRecMessage = printRecMessage }); + } + else + { + var printRecItem = new PrintRecItem + { + Description = i.Description, + Quantity = i.Quantity, + UnitPrice = i.Quantity == 0 || i.Amount == 0 ? 0 : i.Amount / i.Quantity, + Department = i.GetVatGroup(), + }; + PrintRecMessage? printRecMessage = null; + if (!string.IsNullOrEmpty(i.ftChargeItemCaseData)) + { + printRecMessage = new PrintRecMessage() + { + Message = i.ftChargeItemCaseData, + MessageType = 4 + }; + } + itemAndMessages.Add(new() { PrintRecItem = printRecItem, PrintRecMessage = printRecMessage }); + } + } + } + + public static List GetTotalAndMessages(ReceiptRequest request) + { + var totalAndMessages = new List(); + foreach (var pay in request.cbPayItems) + { + var paymentType = GetEpsonPaymentType(pay); + var printRecTotal = new PrintRecTotal + { + Description = pay.Description, + PaymentType = paymentType.PaymentType, + Index = paymentType.Index, + Payment = (request.IsRefund() || request.IsVoid() || pay.IsRefund() || pay.IsVoid()) ? Math.Abs(pay.Amount) : pay.Amount, + }; + PrintRecMessage? printRecMessage = null; + if (!string.IsNullOrEmpty(pay.ftPayItemCaseData)) + { + printRecMessage = new PrintRecMessage() + { + Message = pay.ftPayItemCaseData, + MessageType = 4 + }; + } + totalAndMessages.Add(new() + { + PrintRecTotal = printRecTotal, + PrintRecMessage = printRecMessage + }); + } + return totalAndMessages; + } + + public struct EpsonPaymentType + { + public int PaymentType; + public int Index; + } + + public static EpsonPaymentType GetEpsonPaymentType(PayItem payItem) + { + return (payItem.ftPayItemCase & 0xFF) switch + { + 0x00 => new EpsonPaymentType() { PaymentType = 0, Index = 0 }, + 0x01 => new EpsonPaymentType() { PaymentType = 0, Index = 0 }, + 0x02 => new EpsonPaymentType() { PaymentType = 0, Index = 0 }, + 0x03 => new EpsonPaymentType() { PaymentType = 1, Index = 0 }, + 0x04 => new EpsonPaymentType() { PaymentType = 2, Index = 1 }, + 0x05 => new EpsonPaymentType() { PaymentType = 2, Index = 1 }, + 0x06 => new EpsonPaymentType() { PaymentType = 3, Index = 1 }, + 0x07 => new EpsonPaymentType() { PaymentType = 5, Index = 0 }, + 0x08 => new EpsonPaymentType() { PaymentType = 5, Index = 0 }, + 0x09 => new EpsonPaymentType() { PaymentType = 5, Index = 0 }, + 0x0A => new EpsonPaymentType() { PaymentType = 2, Index = 1 }, + 0x0B => new EpsonPaymentType() { PaymentType = 2, Index = 1 }, + 0x0C => new EpsonPaymentType() { PaymentType = 0, Index = 0 }, + 0x0D => new EpsonPaymentType() { PaymentType = 5, Index = 0 }, + 0x0E => new EpsonPaymentType() { PaymentType = 5, Index = 0 }, + _ => throw new NotSupportedException($"The payitemcase {payItem.ftPayItemCase} is not supported") + }; + } + + // TODO: check VAT rate table on printer at the moment according to xml example + private static readonly int _vatRateBasic = 1; + private static readonly int _vatRateDeduction1 = 2; + private static readonly int _vatRateDeduction2 = 3; + private static readonly int _vatRateSuperReduced1 = 4; + private static readonly int _vatRateZero = 0; + private static readonly int _vatRateUnknown = -1; + private static readonly int _notTaxable = 0; + private static int _vatRateSuperReduced2; + private static int _vatRateParking; + + public static int GetVatGroup(this ChargeItem chargeItem) + { + return (chargeItem.ftChargeItemCase & 0xF) switch + { + 0x0 => _vatRateUnknown, // 0 ??? + 0x1 => _vatRateDeduction1, // 10% + 0x2 => _vatRateDeduction2, // 4% + 0x3 => _vatRateBasic, // 22% + 0x4 => _vatRateSuperReduced1, // ? + 0x5 => _vatRateSuperReduced2, // ? + 0x6 => _vatRateParking, // ? + 0x7 => _vatRateZero, // ? + 0x8 => _notTaxable, // ? + _ => _vatRateUnknown // ? + }; + } + } +} + +public class EpsonPrinterDepartmentConfiguration +{ + public Dictionary DepartmentMapping { get; set; } = new Dictionary(); + + + public static EpsonPrinterDepartmentConfiguration Default => new EpsonPrinterDepartmentConfiguration + { + DepartmentMapping = new Dictionary + { + { "0", 8 }, // unknown + { "1", 2 }, // reduced1 => 10% + { "2", 3 }, // reduced 2 => 5% + { "3", 1 }, // basic => 22% + { "4", -1 }, // superreduced 1 + { "5", -1 }, // superreduced 2 + { "6", -1 }, // parking rate + { "7", 7 }, // zero rate => 0% + { "8", 8 }, // not taxable => 0% + } + }; +} \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/EpsonFormatters.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/EpsonFormatters.cs similarity index 89% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/EpsonFormatters.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/EpsonFormatters.cs index 7f318e921..a6da49a3a 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/EpsonFormatters.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/EpsonFormatters.cs @@ -1,6 +1,6 @@ using System.Globalization; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Utilities +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities { public class EpsonFormatters { diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/SoapSerializer.cs b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/SoapSerializer.cs similarity index 54% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/SoapSerializer.cs rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/SoapSerializer.cs index 87613db7b..b661b5123 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/Utilities/SoapSerializer.cs +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/Utilities/SoapSerializer.cs @@ -1,10 +1,9 @@ using System.IO; using System.Text; using System.Xml.Serialization; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; -using fiskaltrust.Middleware.SCU.IT.Epson.Extensions; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models; -namespace fiskaltrust.Middleware.SCU.IT.Epson.Utilities +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities { public static class SoapSerializer { @@ -19,16 +18,27 @@ public static string Serialize(T body) where T : class var serializer = new XmlSerializer(typeof(SoapEnvelope)); using var textWriter = new Utf8StringWriter(); serializer.Serialize(textWriter, envelope, ns); - - return textWriter.ToString().RemoveListObjectsForEpsonXml(); + + return textWriter.ToString().Replace("\r\n", "") + .Replace("\r\n", "") + .Replace("\r\n", "") + .Replace("\r\n", "") + .Replace("\r\n", "") + .Replace("\r\n", ""); } - public static T? Deserialize(Stream content) where T : class + public static T? DeserializeToSoapEnvelope(Stream content) where T : class { var serializer = new XmlSerializer(typeof(SoapEnvelope)); var envelope = serializer.Deserialize(content) as SoapEnvelope; return envelope?.Body?.Value; } + + public static T? Deserialize(Stream stream) where T : class + { + var reader = new XmlSerializer(typeof(T)); + return reader.Deserialize(stream) as T; + } } internal class Utf8StringWriter : StringWriter diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/fiskaltrust.Middleware.SCU.IT.Epson.csproj b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.csproj similarity index 84% rename from scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/fiskaltrust.Middleware.SCU.IT.Epson.csproj rename to scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.csproj index b7b316104..5ac0f6442 100644 --- a/scu-it/src/fiskaltrust.Middleware.SCU.IT.Epson/fiskaltrust.Middleware.SCU.IT.Epson.csproj +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.csproj @@ -8,10 +8,8 @@ - - - - + + @@ -28,4 +26,8 @@ true + + + + \ No newline at end of file diff --git a/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/version.json b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/version.json new file mode 100644 index 000000000..e8d20a8b5 --- /dev/null +++ b/scu-it/src/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter/version.json @@ -0,0 +1,6 @@ +{ + "version": "1.3.50-rc1", + "releaseBranches": [ + "^refs/tags/scu-it/epsonrtprinter/v\\d+(?:\\.\\d+)*(?:-.*)?$" + ] +} \ No newline at end of file diff --git a/scu-it/test/TestLauncher/Program.cs b/scu-it/test/TestLauncher/Program.cs index e1d24443c..93ac91e3a 100644 --- a/scu-it/test/TestLauncher/Program.cs +++ b/scu-it/test/TestLauncher/Program.cs @@ -1,14 +1,10 @@ using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using fiskaltrust.ifPOS.v1.it; -using fiskaltrust.Middleware.SCU.IT.Epson; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; using fiskaltrust.Middleware.SCU.IT.Test.Launcher.Helpers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter; namespace TestLauncher { diff --git a/scu-it/test/TestLauncher/fiskaltrust.Middleware.SCU.IT.TestLauncher.csproj b/scu-it/test/TestLauncher/fiskaltrust.Middleware.SCU.IT.TestLauncher.csproj index a2740c727..03f99a875 100644 --- a/scu-it/test/TestLauncher/fiskaltrust.Middleware.SCU.IT.TestLauncher.csproj +++ b/scu-it/test/TestLauncher/fiskaltrust.Middleware.SCU.IT.TestLauncher.csproj @@ -19,14 +19,11 @@ + - - - - - + diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/CustomRTServerTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/CustomRTServerTests.cs new file mode 100644 index 000000000..48551d1dd --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/CustomRTServerTests.cs @@ -0,0 +1,184 @@ +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using fiskaltrust.Middleware.SCU.IT.CustomRTServer; +using FluentAssertions; +using FluentAssertions.Execution; +using FluentAssertions.Extensions; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.AcceptanceTests +{ + public class CustomRTServerTests : ITSSCDTests + { + private static readonly Guid _accountid = Guid.Parse("4b95ea47-dbf7-4ba6-bcab-ae46030bc0e9"); + private static readonly Guid _scuId = Guid.Parse("5b95ea47-dbf7-4ba6-bcab-ae46030bc0e9"); + + //private static readonly Uri _serverUri = new Uri("https://f51f-88-116-45-202.ngrok-free.app/"); + private static readonly Uri _serverUri = new Uri("https://at13-custom-rt-it.fiskaltrust.services/"); + private readonly CustomRTServerConfiguration _config = new CustomRTServerConfiguration + { + ServerUrl = _serverUri.ToString(), + Username = "0001ab05", + Password = "admin", + AccountMasterData = JsonConvert.SerializeObject(new AccountMasterData + { + AccountId = _accountid, + VatId = "MTLFNC75A16E783N" + }), + SendReceiptsSync = true, + IgnoreRTServerErrors = false, + DisabelSSLValidation = true + }; + + protected override string SerialNumber => "96SRT001239"; + + protected override IMiddlewareBootstrapper GetMiddlewareBootstrapper(Guid queueId) => new ScuBootstrapper + { + Id = queueId, + Configuration = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(_config)) + }; + + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_MultipleResults() + { + var config = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(_config)))); + config.SendReceiptsSync = false; + config.IgnoreRTServerErrors = false; + config.RTServerHttpTimeoutInMs = 10; + var itsscd = GetSUT(new ScuBootstrapper + { + Id = _scuId, + Configuration = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(config)) + }); + using var scope = new AssertionScope(); + + var lastZNumber = 0L; + var lastReceiptNumber = 0L; + + var dailyClosingResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetDailyClosing(), + ReceiptResponse = _receiptResponse + }); + lastZNumber = long.Parse(dailyClosingResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)).Subject.Data); + + for (var i = 0; i < 100; i++) + { + var request = ReceiptExamples.GetTakeAway_Delivery_Cash(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = request, + ReceiptResponse = _receiptResponse + }); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)).Subject.Data.Should().Be(SerialNumber); + + var zNumber = long.Parse(result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)).Subject.Data); + zNumber.Should().Be(lastZNumber + 1); + var docNumber = long.Parse(result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)).Subject.Data); + docNumber.Should().Be(lastReceiptNumber + 1); + lastReceiptNumber = docNumber; + DateTime.Parse(result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)).Subject.Data).Should().BeCloseTo(request.cbReceiptMoment, TimeSpan.FromSeconds(1)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)).Subject.Data.Should().Be("POSRECEIPT"); + } + await Task.Delay(TimeSpan.FromSeconds(30)); + dailyClosingResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetDailyClosing(), + ReceiptResponse = _receiptResponse + }); + var nextZNumber = long.Parse(dailyClosingResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)).Subject.Data); + nextZNumber.Should().Be(lastZNumber + 1); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_Refund_WithoutReferencesfs() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + + var refundResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Refund(), + ReceiptResponse = response + }); + using var scope = new AssertionScope(); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_Discount() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + + var refundResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.FoodBeverage_CashAndVoucher_Discount(), + ReceiptResponse = response + }); + using var scope = new AssertionScope(); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + + [Fact] + public async Task BrokenConnectionTest_ZeroReceipt() + { + var response = _receiptResponse; + var config = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(_config)))); + config.ServerUrl = "https://10.23.10.222/"; + config.RTServerHttpTimeoutInMs = 1000; + var itsscd = GetSUT(new ScuBootstrapper + { + Id = _scuId, + Configuration = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(config)) + }); + + Func> method = async () => await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetZeroReceipt(), + ReceiptResponse = response + }); + var rsult = await method.Should().CompleteWithinAsync(1010.Milliseconds()); + rsult.Subject.ReceiptResponse.ftState.Should().Be(0x4954_2001_0000_0000); + } + + [Fact] + public async Task BrokenConnectionTest_DailyClosing() + { + var response = _receiptResponse; + var config = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(_config)))); + config.RTServerHttpTimeoutInMs = 1000; + config.ServerUrl = "https://at14-custom-rt-it.fiskaltrust.services/"; + var itsscd = GetSUT(new ScuBootstrapper + { + Id = _scuId, + Configuration = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(config)) + }); + + Func> method = async () => await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetDailyClosing(), + ReceiptResponse = response + }); + var result = await method(); + //var rsult = await method.Should().CompleteWithinAsync(1100.Milliseconds()); + //rsult.Subject.ReceiptResponse.ftState.Should().Be(0x4954_2001_EEEE_EEEE); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/EpsonRTPrinterTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/EpsonRTPrinterTests.cs new file mode 100644 index 000000000..d0f29ec17 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/EpsonRTPrinterTests.cs @@ -0,0 +1,39 @@ +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.AcceptanceTests +{ + public class EpsonRTPrinterTests : ITSSCDTests + { + private static readonly Uri _serverUri = new Uri("http://192.168.0.14/"); + private readonly EpsonRTPrinterSCUConfiguration _config = new EpsonRTPrinterSCUConfiguration + { + DeviceUrl = _serverUri.ToString(), + Password = "21719", + AdditionalTrailerLines = new List { + "T.{cbArea} K.{cbUser}", + "" + } + }; + + protected override string SerialNumber => "99IEC018305"; + + protected override IMiddlewareBootstrapper GetMiddlewareBootstrapper(Guid queueId) => new ScuBootstrapper + { + Id = queueId, + Configuration = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(_config)) + }; + + [Fact] + public void Deserialize() + { + var json = JsonConvert.SerializeObject(_config); + + var data = """ + {"DeviceUrl":"http://10.1.16.110","AdditionalTrailerLines":"[\\\"T.{cbArea} K.{cbUser}\\\",\\\"\\\"]"} + """; + var config = JsonConvert.DeserializeObject(data); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ITSSCDTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ITSSCDTests.cs new file mode 100644 index 000000000..75e95713f --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ITSSCDTests.cs @@ -0,0 +1,514 @@ +using fiskaltrust.ifPOS.v1; +using fiskaltrust.ifPOS.v1.it; +using fiskaltrust.Middleware.Abstractions; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using FluentAssertions; +using FluentAssertions.Execution; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.AcceptanceTests +{ + public abstract class ITSSCDTests + { + private static readonly Guid _queueId = Guid.Parse("da8147d6-a0c2-42c6-8091-4ea7adbe4afc"); + + protected static ReceiptResponse _receiptResponse => new ReceiptResponse + { + ftCashBoxIdentification = "ACPT0001", + ftQueueID = _queueId.ToString() + }; + + protected abstract IMiddlewareBootstrapper GetMiddlewareBootstrapper(Guid queueId); + + protected abstract string SerialNumber { get; } + + protected IITSSCD GetSUT() + { + // Disable SSL checks for the test server + System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate + { return true; }; + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + + var sut = GetMiddlewareBootstrapper(_queueId); + sut.ConfigureServices(serviceCollection); + return serviceCollection.BuildServiceProvider().GetRequiredService(); + } + + protected IITSSCD GetSUT(IMiddlewareBootstrapper sut) + { + // Disable SSL checks for the test server + System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate + { return true; }; + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + + sut.ConfigureServices(serviceCollection); + return serviceCollection.BuildServiceProvider().GetRequiredService(); + } + + [Fact] + public async Task GetRTInfoAsync_ShouldReturn_Serialnumber() + { + var itsscd = GetSUT(); + + var result = await itsscd.GetRTInfoAsync(); + result.SerialNumber.Should().Be(SerialNumber); + } + + [Fact] + public async Task ProcessPosReceipt_InitialOperation_0x4954_2000_0000_4001() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetInitialOperation(), + ReceiptResponse = _receiptResponse + }); + result.ReceiptResponse.ftSignatures.Should().BeEmpty(); + } + + [Fact] + public async Task ProcessPosReceipt_OutOfOperation_0x4954_2000_0000_4002() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetOutOOperation(), + ReceiptResponse = _receiptResponse + }); + result.ReceiptResponse.ftSignatures.Should().BeEmpty(); + } + + [Fact] + public async Task ProcessPosReceipt_Daily_Closing0x4954_2000_0000_2011() + { + + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetDailyClosing(), + ReceiptResponse = _receiptResponse + }); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + } + + [Fact] + public async Task ProcessPosReceipt_ZeroReceipt0x4954_2000_0000_2000() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetZeroReceipt(), + ReceiptResponse = _receiptResponse + }); + var dictioanry = JsonConvert.DeserializeObject>(result.ReceiptResponse.ftStateData); + dictioanry.Should().ContainKey("DeviceMemStatus"); + dictioanry.Should().ContainKey("DeviceDailyStatus"); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Cash(), + ReceiptResponse = _receiptResponse + }); + + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_Refund() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + var request = ReceiptExamples.GetTakeAway_Delivery_Cash(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = request, + ReceiptResponse = _receiptResponse + }); + + + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber)?.Data; + var rtdocNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber)?.Data; + var rtDocumentMoment = DateTime.Parse(result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentMoment)?.Data ?? DateTime.MinValue.ToString()); + + var signatures = new List(); + signatures.AddRange(new List + { + new SignaturItem + { + Caption = "", + Data = zNumber?.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }, + new SignaturItem + { + Caption = "", + Data = rtdocNumber?.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = rtDocumentMoment.ToString("yyyy-MM-dd HH:mm:ss"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }, + }); + response.ftSignatures = signatures.ToArray(); + + var refundResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Refund(), + ReceiptResponse = response + }); + using var scope = new AssertionScope(); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_Refund_WithoutReferencess() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + + var refundResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Refund(), + ReceiptResponse = response + }); + using var scope = new AssertionScope(); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_Void() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + var request = ReceiptExamples.GetTakeAway_Delivery_Cash(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = request, + ReceiptResponse = _receiptResponse + }); + + + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber)?.Data; + var rtdocNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber)?.Data; + var rtDocumentMoment = DateTime.Parse(result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentMoment)?.Data ?? DateTime.MinValue.ToString()); + var signatures = new List(); + signatures.AddRange(new List + { + new SignaturItem + { + Caption = "", + Data = zNumber?.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }, + new SignaturItem + { + Caption = "", + Data = rtdocNumber?.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = rtDocumentMoment.ToString("yyyy-MM-dd HH:mm:ss"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }, + }); + response.ftSignatures = signatures.ToArray(); + + var refundResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Void(), + ReceiptResponse = response + }); + using var scope = new AssertionScope(); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Cash_Void_WithoutReferences() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + var refundResult = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Void(), + ReceiptResponse = response + }); + using var scope = new AssertionScope(); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().NotContain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + refundResult.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Card() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Card(), + ReceiptResponse = _receiptResponse + }); + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Card_WithCustomerIVA() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Card_WithCustomerIva(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTCustomerID)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Card_WithInvalidCustomerIVA() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Card_WithInvalidCustomerIva(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_TakeAway_Delivery_Card_WithInvalidCustomerIVA_ShouldReturnError() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetTakeAway_Delivery_Card_WithInvalidCustomerIva(), + ReceiptResponse = _receiptResponse + }); + result.ReceiptResponse.HasFailed().Should().BeTrue(); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_CashAndVoucher() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.FoodBeverage_CashAndVoucher(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_CashReceiptWithSubItems() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetCashWithSubItems(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_Cash_withSubItemReduction() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.Cash_withSubItemReduction(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0001_CashReceiptWithTip() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetCashReceiptWithTip(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ProcessPosReceipt_0x4954_2000_0000_0005_ProtocolWithCustomerData() + { + var itsscd = GetSUT(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetDeliveryNoteWithCustomerData(), + ReceiptResponse = _receiptResponse + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + } + + [Fact] + public async Task ReprintReceipt() + { + var response = _receiptResponse; + var itsscd = GetSUT(); + + var request = ReceiptExamples.GetTakeAway_Delivery_Cash(); + var result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = request, + ReceiptResponse = response + }); + + + var zNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTZNumber)?.Data; + var rtdocNumber = result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentNumber)?.Data; + var rtDocumentMoment = DateTime.Parse(result.ReceiptResponse.GetSignaturItem(SignatureTypesIT.RTDocumentMoment)?.Data ?? DateTime.MinValue.ToString()); + var signatures = new List(); + signatures.AddRange(new List + { + new SignaturItem + { + Caption = "", + Data = zNumber?.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber + }, + new SignaturItem + { + Caption = "", + Data = rtdocNumber?.ToString(), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber + }, + new SignaturItem + { + Caption = "", + Data = rtDocumentMoment.ToString("yyyy-MM-dd HH:mm:ss"), + ftSignatureFormat = (long) SignaturItem.Formats.Text, + ftSignatureType = ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment + }, + }); + response.ftSignatures = signatures.ToArray(); + result = await itsscd.ProcessReceiptAsync(new ProcessRequest + { + ReceiptRequest = ReceiptExamples.GetReprintReceipt(), + ReceiptResponse = response + }); + + using var scope = new AssertionScope(); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTSerialNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentMoment)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTDocumentType)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceZNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentNumber)); + result.ReceiptResponse.ftSignatures.Should().Contain(x => x.ftSignatureType == (ITConstants.BASE_STATE | (long) SignatureTypesIT.RTReferenceDocumentMoment)); + } + } +} + +// TODO TEsts +// - Add test that sends wrong CUstomer IVA +// - Add test that sends customer data without iva \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptExamples.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptExamples.cs new file mode 100644 index 000000000..cf639331f --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptExamples.cs @@ -0,0 +1,706 @@ +using fiskaltrust.ifPOS.v1; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.AcceptanceTests +{ + public static class ReceiptExamples + { + public static ReceiptRequest GetInitialOperation() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "0x4001_InitialOperation.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetOutOOperation() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "0x4002_OutOfOperation.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetZeroReceipt() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "0x2011_ZeroReceipt.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetDeliveryNoteWithCustomerData() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "PosReceipts", "0x0005_Cash_cbCustomer.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetCashReceiptWithTip() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "PosReceipts", "0x0001_Cash_Tip.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetCashWithSubItems() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "PosReceipts", "0x0001_Cash_withSubItems.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest Cash_withSubItemReduction() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "PosReceipts", "0x0001_Cash_withSubItemReduction.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetDailyClosing() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "0x2011_DailyClosing.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetReprintReceipt() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = File.ReadAllText(Path.Combine("ReceiptRequests", "0x3010_Reprint.json")).Replace("{{current_moment}}", current_moment); + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Cash() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Refund() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0004", + "cbPreviousReceiptReference": "96SRT900126,00010001;0001-0002;20230830120101", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -2.0, + "Amount": -221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186751507, + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186751505, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186751506, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186751508, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186755604, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186759700, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186763796, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186767892, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186771988, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186784276, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -566 + } + ], + "ftReceiptCase": 5283883447201300481 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Void() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0004", + "cbPreviousReceiptReference": "96SRT900126,00010001;0001-0002;20230830120101", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -2.0, + "Amount": -221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186751507, + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186751505, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186751506, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186751508, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186755604, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186759700, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186763796, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186767892, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186771988, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186784276, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -566 + } + ], + "ftReceiptCase": 5283883447184785409 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Card() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "cbCustomer": "{\"CustomerVATId\": \"01606720215\"}", + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Card_WithCustomerIva() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 221 + } + ], + "cbCustomer": "{\"CustomerVATId\": \"IT01606720215\"}", + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Card_WithInvalidCustomerIva() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 221 + } + ], + "cbCustomer": "{\"CustomerVATId\": \"12345\"}", + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest FoodBeverage_CashAndVoucher() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0006", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Voucher", + "ftPayItemCase": 5283883447184523270, + "Moment": "{{current_moment}}", + "Amount": 10 + }, + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 97 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + + public static ReceiptRequest FoodBeverage_CashAndVoucher_Discount() + { + var current_moment = DateTime.UtcNow.ToString("o"); + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "VATAmount": 9.73, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "VATAmount": -9.73, + "ftChargeItemCase": 5283883447184785409, + "Description": "Discount/Free item - Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 0 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x2000_ZeroReceipt.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x2000_ZeroReceipt.json new file mode 100644 index 000000000..e0c40a0d1 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x2000_ZeroReceipt.json @@ -0,0 +1,11 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Zero", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184531456, + "cbUser": "Admin" +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x2011_DailyClosing.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x2011_DailyClosing.json new file mode 100644 index 000000000..5d027dfbf --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x2011_DailyClosing.json @@ -0,0 +1,11 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Daily-Closing", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184531473, + "cbUser": "Admin" +} diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x3010_Reprint.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x3010_Reprint.json new file mode 100644 index 000000000..43480e46d --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x3010_Reprint.json @@ -0,0 +1,28 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "T2", + "cbReceiptReference": "RT123823", + "cbUser": "Sepp", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1.0, + "Amount": 110.5, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TestChargeItem22vat", + "ftChargeItemCase": 5283883447184654339 + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184654337, + "Amount": 110.5 + } + ], + "cbPreviousReceiptReference": "{{receiptreference_of_receipt_to_reprint}}", + "ftReceiptCase": 5283883447184535568 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x4001_InitialOperation.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x4001_InitialOperation.json new file mode 100644 index 000000000..9a55dcca9 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x4001_InitialOperation.json @@ -0,0 +1,11 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "INIT", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184539649, + "cbUser": "Admin" +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x4002_OutOfOperation.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x4002_OutOfOperation.json new file mode 100644 index 000000000..e593dcae2 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/0x4002_OutOfOperation.json @@ -0,0 +1,12 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "OutOfOperation", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": 5283883447184539650, + "ftReceiptCaseData": "", + "cbUser": "Admin" +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash.json new file mode 100644 index 000000000..e83029b56 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash.json @@ -0,0 +1,28 @@ +{ + "ftCashBoxID": "{{cashbox_id}}", + "ftPosSystemId": "{{possystem_id}}", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 107 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_Tip.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_Tip.json new file mode 100644 index 000000000..179997519 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_Tip.json @@ -0,0 +1,37 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0006", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1.0, + "Amount": 100, + "UnitPrice": 100, + "VATRate": 22, + "Description": "", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 34, + "VATRate": 0, + "ftChargeItemCase": 5283883447184531512, + "Description": "Tip", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 134 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_withSubItemReduction.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_withSubItemReduction.json new file mode 100644 index 000000000..97e208dd9 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_withSubItemReduction.json @@ -0,0 +1,38 @@ +{ + "ftCashBoxID": "{{cashbox_id}}", + "ftPosSystemId": "{{possystem_id}}", + "cbTerminalID": "00010001", + "cbReceiptReference": "{{$guid}}", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Position": 100, + "Quantity": 1, + "Amount": 20, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "Subitem 1 - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Position": 101, + "Quantity": 1, + "Amount": -2, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "Kleine Portion 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 18 + } + ], + "ftReceiptCase": 5283883447318740993 // 4954200008000001 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_withSubItems.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_withSubItems.json new file mode 100644 index 000000000..a01c6c8b5 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0001_Cash_withSubItems.json @@ -0,0 +1,75 @@ +{ + "ftCashBoxID": "{{cashbox_id}}", + "ftPosSystemId": "{{possystem_id}}", + "cbTerminalID": "00010001", + "cbReceiptReference": "{{$guid}}", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Position": 100, + "Quantity": 0, + "Amount": 0, + "UnitPrice": 0, + "VATRate": 0, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Position": 101, + "Quantity": 1, + "Amount": 200, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "Subitem 1 - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Position": 102, + "Quantity": 1, + "Amount": 150, + "VATRate": 5, + "ftChargeItemCase": 5283883447186620434, + "Description": "Subitem 2 - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Position": 103, + "Quantity": 0, + "Amount": 0, + "VATRate": 0, + "ftChargeItemCase": 5283883447186620434, + "Description": "SubItem just text 1", + "Moment": "{{current_moment}}" + }, + { + "Position": 104, + "Quantity": 0, + "Amount": 0, + "VATRate": 0, + "ftChargeItemCase": 5283883447186620434, + "Description": "SubItem just text 2", + "Moment": "{{current_moment}}" + }, + { + "Position": 105, + "Quantity": 0, + "Amount": 0, + "VATRate": 0, + "ftChargeItemCase": 5283883447186620434, + "Description": "SubItem just text 3", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 350 + } + ], + "ftReceiptCase": 5283883447318740993 // 4954200008000001 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0005_Cash_cbCustomer.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0005_Cash_cbCustomer.json new file mode 100644 index 000000000..3a70a7275 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/ReceiptRequests/PosReceipts/0x0005_Cash_cbCustomer.json @@ -0,0 +1,29 @@ +{ + "ftCashBoxID": "{{cashbox_id}}", + "ftPosSystemId": "{{possystem_id}}", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 107 + } + ], + "cbCustomer": "{\r\n \"CustomerName\": \"fiskaltrust\",\r\n \"CustomerId\": \"0\",\r\n \"CustomerType\": \"\",\r\n \"CustomerStreet\": \"Alpenstra\u00DFe 99\",\r\n \"CustomerZip\": \"5020\",\r\n \"CustomerCity\": \"Salzburg\",\r\n \"CustomerCountry\": \"AT\" }", + "ftReceiptCase": 5283883447184523269 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/Usings.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/Usings.cs new file mode 100644 index 000000000..8c927eb74 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/fiskaltrust.Middleware.SCU.IT.AcceptanceTests.csproj b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/fiskaltrust.Middleware.SCU.IT.AcceptanceTests.csproj new file mode 100644 index 000000000..b47a9fc64 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/fiskaltrust.Middleware.SCU.IT.AcceptanceTests.csproj @@ -0,0 +1,46 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + PreserveNewest + + + + + + PreserveNewest + + + + diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/fiskaltrust.Middleware.SCU.IT.AcceptanceTests.sln b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/fiskaltrust.Middleware.SCU.IT.AcceptanceTests.sln new file mode 100644 index 000000000..639686e0c --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.AcceptanceTests/fiskaltrust.Middleware.SCU.IT.AcceptanceTests.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fiskaltrust.Middleware.SCU.IT.AcceptanceTests", "fiskaltrust.Middleware.SCU.IT.AcceptanceTests.csproj", "{E6B2FA00-38A7-49DA-9C03-63EE979A1D7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E6B2FA00-38A7-49DA-9C03-63EE979A1D7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6B2FA00-38A7-49DA-9C03-63EE979A1D7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6B2FA00-38A7-49DA-9C03-63EE979A1D7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6B2FA00-38A7-49DA-9C03-63EE979A1D7E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {64412135-E82B-4C17-943D-CD790D923FEC} + EndGlobalSection +EndGlobal diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/.DS_Store b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/.DS_Store new file mode 100644 index 000000000..6583b1f7f Binary files /dev/null and b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/.DS_Store differ diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/CustomRTMappingTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/CustomRTMappingTests.cs new file mode 100644 index 000000000..312f9eec0 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/CustomRTMappingTests.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; +using fiskaltrust.ifPOS.v1; +using FluentAssertions; +using FluentAssertions.Execution; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest +{ + public class CustomRTMappingTests + { + [Fact] + public void GenerateTaxDataForReceiptRequest_Should_Map_Correctly() + { + var receiptRequest = ReceiptExamples.GetTakeAway_Delivery_Cash(); + + var data = CustomRTServerMapping.GenerateTaxDataForReceiptRequest(receiptRequest); + + using (new AssertionScope()) + { + data.Should().ContainSingle(x => x.vatvalue == 2200) + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 2200, + tax = 3985, + vatcode = "", + gross = 22100 + }); + data.Should().ContainSingle(x => x.vatvalue == 1000) + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 1000, + tax = 973, + vatcode = "", + gross = 10700 + }); + data.Should().ContainSingle(x => x.vatvalue == 500) + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 500, + tax = 419, + vatcode = "", + gross = 8800 + }); + data.Should().ContainSingle(x => x.vatvalue == 400) + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 400, + tax = 346, + vatcode = "", + gross = 9000 + }); + data.Should().ContainSingle(x => x.vatcode == "N4") + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 0, + tax = 0, + vatcode = "N4", + gross = 1000 + }); + data.Should().ContainSingle(x => x.vatcode == "N3") + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 0, + tax = 0, + vatcode = "N3", + gross = 1000 + }); + data.Should().ContainSingle(x => x.vatcode == "N2") + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 0, + tax = 0, + vatcode = "N2", + gross = 1000 + }); + data.Should().ContainSingle(x => x.vatcode == "N1") + .Which.Should().BeEquivalentTo(new DocumentTaxData + { + vatvalue = 0, + tax = 0, + vatcode = "N1", + gross = 1000 + }); + // RM?? + // AL? + } + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/CustomRTServerClientTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/CustomRTServerClientTests.cs new file mode 100644 index 000000000..eef2cd9d8 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/CustomRTServerClientTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading.Tasks; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest +{ + public class CustomRTServerClientTests + { + private static readonly Uri _serverUri = new Uri("https://f51f-88-116-45-202.ngrok-free.app"); + private readonly CustomRTServerConfiguration _config = new CustomRTServerConfiguration { ServerUrl = _serverUri.ToString(), Username = "0001ab05", Password = "admin" }; + + [Fact(Skip = "Needs device")] + public async Task GetRTInfoAsync_ShouldReturn_SerialNumber() + { + var customRTServerClient = new CustomRTServerClient(_config, null); + + _ = await customRTServerClient.InsertCashRegisterAsync("demo", "1010", "1000", "admin", "cf"); + } + + + [Fact(Skip = "Needs device")] + public async Task GetDailyStatusAsync() + { + var customRTServerClient = new CustomRTServerClient(_config, null); + + _ = await customRTServerClient.GetDailyStatusAsync("0001ab05"); + } + + [Fact(Skip = "Needs device")] + public async Task GetDailyOpenAsync() + { + var customRTServerClient = new CustomRTServerClient(_config, null); + + var result = await customRTServerClient.InsertCashRegisterAsync("SKE_DEBUG_TEST", "ske0", "0003", "admin", "MTLFNC75A16E783N"); + + var dailyStatus = await customRTServerClient.GetDailyStatusAsync(result.cashUuid); + if (dailyStatus.cashStatus == "0") + { + _ = await customRTServerClient.GetDailyOpenAsync(result.cashUuid, DateTime.UtcNow); + //var insertZ = await customRTServerClient.InsertZDocumentAsync(result.cashUuid, DateTime.UtcNow, long.Parse(data.numberClosure) + 1, data.grandTotalDB); + } + else + { + + //await customRTServerClient.InsertFiscalDocumentAsync() + //var insertZ2 = await customRTServerClient.InsertZDocumentAsync(result.cashUuid, DateTime.UtcNow, long.Parse(dailyStatus.numberClosure) + 1, dailyStatus.grandTotalDB); + } + } + + [Fact(Skip = "Currently not working since we don't have a cert.")] + public async Task CancelCashRegister() + { + var customRTServerClient = new CustomRTServerClient(_config, null); + + _ = await customRTServerClient.CancelCashRegisterAsync("0002ab77", "12345688909"); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases.zip b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases.zip new file mode 100644 index 000000000..5cbd1354d Binary files /dev/null and b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases.zip differ diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/4.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/4.json new file mode 100644 index 000000000..54cb2b511 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/4.json @@ -0,0 +1,29 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0004", + "cbPreviousReceiptReference": "96SRT900126,00010001;0001-0002;20230830120101", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184654337, + "Description": "Return/Refund - Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -107 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/4_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/4_rec.json new file mode 100644 index 000000000..05bcf94a3 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/4_rec.json @@ -0,0 +1,197 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 3, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 10700, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": 0, + "referenceDocnumber": 0, + "referenceDtime": "2023-09-30 00:00:00", + "refSerialNum": null, + "referenceCashuuid": "ND", + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Return/Refund - Food 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 9,73", + "amount": "973", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO CONTANTE -107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "1", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Return/Refund Cash", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 10700, + "tax": 973, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/5.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/5.json new file mode 100644 index 000000000..03178dcb5 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/5.json @@ -0,0 +1,29 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0005", + "cbPreviousReceiptReference": "96SRT900126;00010001;0001-0003;20230830130202", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184654337, + "Description": "Return/Refund - Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Card", + "ftPayItemCase": 5283883447184654341, + "Moment": "{{current_moment}}", + "Amount": -107 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/5_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/5_rec.json new file mode 100644 index 000000000..0819a11b6 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Refund/5_rec.json @@ -0,0 +1,197 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 3, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 10700, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": 0, + "referenceDocnumber": 0, + "referenceDtime": "2023-09-30 00:00:00", + "refSerialNum": null, + "referenceCashuuid": "ND", + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Return/Refund - Food 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 9,73", + "amount": "973", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO ELETTRONICO -107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "2", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Return/Refund Card", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 10700, + "tax": 973, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/1.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/1.json new file mode 100644 index 000000000..fa6e8162f --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/1.json @@ -0,0 +1,28 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 107 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/1_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/1_rec.json new file mode 100644 index 000000000..7f32b938c --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/1_rec.json @@ -0,0 +1,197 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 1, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 10700, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": -1, + "referenceDocnumber": -1, + "referenceDtime": null, + "refSerialNum": null, + "referenceCashuuid": null, + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Food/Beverage - Item 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 9,73", + "amount": "973", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO CONTANTE 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "1", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Cash", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 10700, + "tax": 973, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/2.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/2.json new file mode 100644 index 000000000..341a98dbf --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/2.json @@ -0,0 +1,36 @@ +{ + "ftCashBoxID": "{{cashbox_id}}", + "ftPosSystemId": "{{possystem_id}}", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184785409, + "Description": "Discount/Free item - Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 0 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/2_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/2_rec.json new file mode 100644 index 000000000..da73e7883 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/2_rec.json @@ -0,0 +1,213 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 1, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 0, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": -1, + "referenceDocnumber": -1, + "referenceDtime": null, + "refSerialNum": null, + "referenceCashuuid": null, + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Food/Beverage - Item 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "1", + "description": "Discount/Free item - 10% -107,00", + "amount": "-10700", + "quantity": "1000", + "unitprice": "-10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO CONTANTE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "1", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Cash", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 0, + "tax": 0, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/3.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/3.json new file mode 100644 index 000000000..bc97d8667 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/3.json @@ -0,0 +1,28 @@ +{ + "ftCashBoxID": "{{cashbox_id}}", + "ftPosSystemId": "{{possystem_id}}", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 107 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/3_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/3_rec.json new file mode 100644 index 000000000..7908a5f47 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/3_rec.json @@ -0,0 +1,197 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 1, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 10700, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": -1, + "referenceDocnumber": -1, + "referenceDtime": null, + "refSerialNum": null, + "referenceCashuuid": null, + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Food/Beverage - Item 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 9,73", + "amount": "973", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO ELETTRONICO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "2", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Card", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 10700, + "tax": 973, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/6.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/6.json new file mode 100644 index 000000000..f3868573c --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/6.json @@ -0,0 +1,35 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0006", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Voucher", + "ftPayItemCase": 5283883447184523270, + "Moment": "{{current_moment}}", + "Amount": 10 + }, + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 97 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/6_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/6_rec.json new file mode 100644 index 000000000..177226638 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/6_rec.json @@ -0,0 +1,213 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 1, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 10700, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": -1, + "referenceDocnumber": -1, + "referenceDtime": null, + "refSerialNum": null, + "referenceCashuuid": null, + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Food/Beverage - Item 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 9,73", + "amount": "973", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 10,00", + "amount": "1000", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "8", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Voucher", + "amount": "1000", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO CONTANTE 97,00", + "amount": "9700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "1", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Cash", + "amount": "9700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 97,00", + "amount": "9700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 10700, + "tax": 973, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/7.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/7.json new file mode 100644 index 000000000..908a10b90 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/7.json @@ -0,0 +1,35 @@ +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0007", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Voucher", + "ftPayItemCase": 5283883447184523270, + "Moment": "{{current_moment}}", + "Amount": 10 + }, + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 97 + } + ], + "ftReceiptCase": 5283883447184523265 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/7_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/7_rec.json new file mode 100644 index 000000000..36fbd8121 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/7_rec.json @@ -0,0 +1,213 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 1, + "dtime": "2023-09-30 07:17:39", + "docnumber": 2, + "docznumber": 2, + "amount": 10700, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": -1, + "referenceDocnumber": -1, + "referenceDtime": null, + "refSerialNum": null, + "referenceCashuuid": null, + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Food/Beverage - Item 10% 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "10700", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 107,00", + "amount": "10700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 9,73", + "amount": "973", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 10,00", + "amount": "1000", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "8", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Voucher", + "amount": "1000", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO ELETTRONICO 97,00", + "amount": "9700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "2", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Card", + "amount": "9700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 97,00", + "amount": "9700", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "30/09/2023 07:17:39 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 10700, + "tax": 973, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/8.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/8.json new file mode 100644 index 000000000..e613e2e8d --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/8.json @@ -0,0 +1,56 @@ +{ + "ftCashBoxID": "7e250f35-890e-429a-96ed-34d78b6ff22b", + "ftPosSystemId": "bf2a1f54-cebf-4763-8cf6-58e349c037a3", + "cbTerminalID": "15", + "cbReceiptReference": "1500000067", + "cbReceiptMoment": "2023-09-19T13:55:06.336Z", + "cbChargeItems": [ + { + "Quantity": 1, + "Description": "Tea In Cup", + "Amount": 3.5, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "ftChargeItemCaseData": "{\"NetAmount\":3.18}", + "VATAmount": 0.32, + "AccountNumber": "", + "CostCenter": "", + "ProductGroup": "", + "ProductNumber": "3201", + "ProductBarcode": "", + "Unit": "PCS", + "UnitPrice": 3.5 + }, + { + "Quantity": 1, + "Description": "Hot Choc In Cup", + "Amount": 0.001, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "ftChargeItemCaseData": "{\"NetAmount\":0.0}", + "VATAmount": 0.001, + "AccountNumber": "", + "CostCenter": "", + "ProductGroup": "", + "ProductNumber": "3202", + "ProductBarcode": "", + "Unit": "PCS", + "UnitPrice": 0.001 + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Contanti", + "Amount": 3.5, + "ftPayItemCase": 5283883447184523269, + "ftPayItemCaseData": "", + "AccountNumber": "", + "CostCenter": "", + "MoneyGroup": "", + "MoneyNumber": "" + } + ], + "ftReceiptCase": 5283883447184523265, + "cbReceiptAmount": 0 +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/8_rec.json b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/8_rec.json new file mode 100644 index 000000000..28cd7e111 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptCases/Sales/8_rec.json @@ -0,0 +1,213 @@ +{ + "document": { + "cashuuid": "ske00003", + "doctype": 1, + "dtime": "2023-09-19 13:55:06", + "docnumber": 2, + "docznumber": 2, + "amount": 350, + "fiscalcode": "", + "vatcode": "", + "fiscaloperator": "", + "businessname": null, + "prevSignature": "asdf", + "type_signature_id": "1", + "grandTotal": 1, + "referenceClosurenumber": -1, + "referenceDocnumber": -1, + "referenceDtime": null, + "refSerialNum": null, + "referenceCashuuid": null, + "errSignature": null, + "err_number": null, + "err_znumber": null + }, + "items": [ + { + "type": "1", + "description": "Tea In Cup 10% 3,50", + "amount": "350", + "quantity": "1000", + "unitprice": "350", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "1", + "description": "Hot Choc In Cup 10% 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "0", + "vatvalue": "1000", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": "", + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "TOTALE COMPLESSIVO 3,50", + "amount": "350", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "DI CUI IVA 0,32", + "amount": "32", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "PAGAMENTO ELETTRONICO 3,50", + "amount": "350", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "2", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "Contanti", + "amount": "350", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "NON RISCOSSO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "RESTO 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "5", + "description": "SCONTO A PAGARE 0,00", + "amount": "0", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "IMPORTO PAGATO 3,50", + "amount": "350", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + }, + { + "type": "97", + "description": "19/09/2023 13:55:06 DOC.N.0002-0002", + "amount": "", + "quantity": "1000", + "unitprice": "", + "vatvalue": "", + "fiscalvoid": "0", + "signid": "1", + "paymentid": "", + "plu": "", + "department": "", + "vatcode": null, + "service": "0", + "businesscode": "" + } + ], + "taxs": [ + { + "gross": 350, + "tax": 32, + "vatvalue": 1000, + "vatcode": "", + "businesscode": null, + "additional_tax_data": [] + } + ] +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptExamples.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptExamples.cs new file mode 100644 index 000000000..787569a4c --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ReceiptExamples.cs @@ -0,0 +1,435 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1; +using fiskaltrust.Middleware.SCU.IT.Abstraction; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest +{ + public static class ReceiptExamples + { + public static ReceiptRequest GetInitialOperation() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "INIT", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000004001}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetOutOOperation() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "OutOfOperation", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000004002}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetZeroReceipt() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Zero", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000002000}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetDailyClosing() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Daily-Closing", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000002011}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Cash() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Refund() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0004", + "cbPreviousReceiptReference": "96SRT900126,00010001;0001-0002;20230830120101", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -2.0, + "Amount": -221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186751507, + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186751505, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186751506, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186751508, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186755604, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186759700, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186763796, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186767892, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186771988, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186784276, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -566 + } + ], + "ftReceiptCase": 5283883447201300481 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Card() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ScuBootstrapperTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ScuBootstrapperTests.cs new file mode 100644 index 000000000..5ab643757 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/ScuBootstrapperTests.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1.it; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest +{ + public class ScuBootstrapperTests + { + [Fact] + public void Test1() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + + var sut = new ScuBootstrapper + { + Id = Guid.NewGuid(), + Configuration = new Dictionary + { + { "ServerUrl", "https://localhost:8000" } + } + }; + sut.ConfigureServices(serviceCollection); + + + _ = serviceCollection.BuildServiceProvider().GetRequiredService(); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/Usings.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/Usings.cs new file mode 100644 index 000000000..8c927eb74 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest.csproj b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest.csproj new file mode 100644 index 000000000..d80a04cdd --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest/fiskaltrust.Middleware.SCU.IT.CustomRTServer.UnitTest.csproj @@ -0,0 +1,81 @@ + + + + net6 + false + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/ReceiptExamples.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/ReceiptExamples.cs new file mode 100644 index 000000000..e855cb83e --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/ReceiptExamples.cs @@ -0,0 +1,708 @@ +using System; +using fiskaltrust.ifPOS.v1; +using Newtonsoft.Json; + +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest +{ + public static class ReceiptExamples + { + public static ReceiptRequest GetInitialOperation() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "INIT", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000004001}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetOutOOperation() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "OutOfOperation", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000004002}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetZeroReceipt() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Zero", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000002000}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetDailyClosing() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "Daily-Closing", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [], + "cbPayItems": [], + "ftReceiptCase": {{0x4954200000002011}}, + "cbUser": "Admin" +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Cash() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0002", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Refund() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0004", + "cbPreviousReceiptReference": "96SRT900126,00010001;0001-0002;20230830120101", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -2.0, + "Amount": -221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186751507, + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186751505, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186751506, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186751508, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186755604, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186759700, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186763796, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186767892, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186771988, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186784276, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -566 + } + ], + "ftReceiptCase": 5283883447201300481 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Void() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0004", + "cbPreviousReceiptReference": "96SRT900126,00010001;0001-0002;20230830120101", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": -2.0, + "Amount": -221, + "UnitPrice": 110.5, + "VATRate": 22, + "VATAmount": 39.85, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186751507, + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -107, + "VATRate": 10, + "VATAmount": 9.73, + "ftChargeItemCase": 5283883447186751505, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -88, + "VATRate": 5, + "VATAmount": 4.19, + "ftChargeItemCase": 5283883447186751506, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -90, + "VATRate": 4, + "VATAmount": 3.46, + "ftChargeItemCase": 5283883447186751508, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186755604, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186759700, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186763796, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186767892, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186771988, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": -1, + "Amount": -10, + "VATRate": 0, + "VATAmount": 0, + "ftChargeItemCase": 5283883447186784276, + "Description": "Return/Refund - TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Return/Refund Cash", + "ftPayItemCase": 5283883447184654337, + "Moment": "{{current_moment}}", + "Amount": -566 + } + ], + "ftReceiptCase": 5283883447184785409 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + + public static ReceiptRequest GetTakeAway_Delivery_Card() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "cbCustomer": "{\"CustomerVATId\": \"01606720215\"}", + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest GetTakeAway_Delivery_Card_WithCustomerIva() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0003", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 2.0, + "Amount": 221, + "UnitPrice": 110.5, + "VATRate": 22, + "Description": "TakeAway - Delivery - Item VAT 22%", + "ftChargeItemCase": 5283883447186620435, + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447186620433, + "Description": "TakeAway - Delivery - Item VAT 10%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 88, + "VATRate": 5, + "ftChargeItemCase": 5283883447186620434, + "Description": "TakeAway - Delivery - Item VAT 5%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 90, + "VATRate": 4, + "ftChargeItemCase": 5283883447186620436, + "Description": "TakeAway - Delivery - Item VAT 4%", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186624532, + "Description": "TakeAway - Delivery - Item VAT NI", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186628628, + "Description": "TakeAway - Delivery - Item VAT NS", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186632724, + "Description": "TakeAway - Delivery - Item VAT ES", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186636820, + "Description": "TakeAway - Delivery - Item VAT RM", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186640916, + "Description": "TakeAway - Delivery - Item VAT AL", + "Moment": "{{current_moment}}" + }, + { + "Quantity": 1, + "Amount": 10, + "VATRate": 0, + "ftChargeItemCase": 5283883447186653204, + "Description": "TakeAway - Delivery - Item VAT EE", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Card", + "ftPayItemCase": 5283883447184523269, + "Moment": "{{current_moment}}", + "Amount": 566 + } + ], + "cbCustomer": "{\"CustomerVATId\": \"IT01606720215\"}", + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + + public static ReceiptRequest FoodBeverage_CashAndVoucher() + { + var current_moment = DateTime.UtcNow; + var receipt = $$""" +{ + "ftCashBoxID": "00000000-0000-0000-0000-000000000000", + "ftPosSystemId": "00000000-0000-0000-0000-000000000000", + "cbTerminalID": "00010001", + "cbReceiptReference": "0001-0006", + "cbUser": "user1234", + "cbReceiptMoment": "{{current_moment}}", + "cbChargeItems": [ + { + "Quantity": 1, + "Amount": 107, + "VATRate": 10, + "ftChargeItemCase": 5283883447184523265, + "Description": "Food/Beverage - Item VAT 10%", + "Moment": "{{current_moment}}" + } + ], + "cbPayItems": [ + { + "Quantity": 1, + "Description": "Voucher", + "ftPayItemCase": 5283883447184523270, + "Moment": "{{current_moment}}", + "Amount": 10 + }, + { + "Quantity": 1, + "Description": "Cash", + "ftPayItemCase": 5283883447184523265, + "Moment": "{{current_moment}}", + "Amount": 97 + } + ], + "ftReceiptCase": 5283883447184523265 +} +"""; + return JsonConvert.DeserializeObject(receipt); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/ScuBootstrapperTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/ScuBootstrapperTests.cs new file mode 100644 index 000000000..9875b5a95 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/ScuBootstrapperTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using fiskaltrust.ifPOS.v1.it; +using Microsoft.Extensions.DependencyInjection; + +namespace fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest +{ + public class ScuBootstrapperTests + { + [Fact] + public void Test1() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + + var sut = new ScuBootstrapper + { + Id = Guid.NewGuid(), + Configuration = new Dictionary + { + { "DeviceUrl", "https://localhost:8000" } + } + }; + sut.ConfigureServices(serviceCollection); + + + _ = serviceCollection.BuildServiceProvider().GetRequiredService(); + } + } +} \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/Usings.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/Usings.cs new file mode 100644 index 000000000..8c927eb74 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest.csproj b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest.csproj new file mode 100644 index 000000000..ef58ccfd2 --- /dev/null +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest/fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.UnitTest.csproj @@ -0,0 +1,30 @@ + + + + net6 + false + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/EpsonSCUTest.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/EpsonSCUTest.cs deleted file mode 100644 index db3f571f6..000000000 --- a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/EpsonSCUTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using fiskaltrust.Middleware.SCU.IT.Epson; -using Microsoft.Extensions.Logging; -using Xunit; -using Moq; -using FluentAssertions; -using System.Threading.Tasks; - -namespace fiskaltrust.Middleware.SCU.IT.UnitTest -{ - public class EpsonSCUTest - { - - [Fact(Skip = "Only with active Testprinter")] - public async Task GetSerialNumber_GetResult_11DigetSerialnrAsync() - { - var config = new EpsonScuConfiguration() - { - DeviceUrl = "https://469b-194-93-177-143.eu.ngrok.io" - }; - - var epsonScu = new EpsonSCU(new Mock>().Object, config, new Epson.Utilities.EpsonCommandFactory(config)); - - var serialnr = await epsonScu.GetSerialNumberAsync("I").ConfigureAwait(false); - serialnr.Should().Be("99IEC018305"); - } - } -} diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/FiscalReceiptTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/FiscalReceiptTests.cs index e325e4ce8..280cfc851 100644 --- a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/FiscalReceiptTests.cs +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/FiscalReceiptTests.cs @@ -1,144 +1,142 @@ -using fiskaltrust.Middleware.SCU.IT.Epson.Utilities; -using Xunit; -using fiskaltrust.ifPOS.v1.it; -using System.Collections.Generic; -using System.IO; -using fiskaltrust.Middleware.SCU.IT.Epson; -using System.Globalization; -using System; +//using Xunit; +//using fiskaltrust.ifPOS.v1.it; +//using System.Collections.Generic; +//using System.IO; +//using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter; +//using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities; -namespace fiskaltrust.Middleware.SCU.IT.UnitTest -{ - public class FiscalReceiptTests - { - [Fact] - public void CommercailDocument_SendInvoice_CreateValidXml() - { - var epsonScuConfiguration = new EpsonScuConfiguration (); - var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); +//namespace fiskaltrust.Middleware.SCU.IT.UnitTest +//{ +// public class FiscalReceiptTests +// { +// [Fact] +// public void CommercailDocument_SendInvoice_CreateValidXml() +// { +// var epsonScuConfiguration = new EpsonRTPrinterSCUConfiguration (); +// var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); - var fiscalReceiptRequest = new FiscalReceiptInvoice() - { - Barcode = "0123456789", - DisplayText = "Message on customer display", - Items = new List() - { - new Item() { Description = "PANINO", Quantity = 1, UnitPrice = 6.00m, VatGroup = 2 }, - new Item() { Description = "Selling Item 2 VAT 22%", Quantity = 1.234m, UnitPrice = 10.00m, VatGroup = 1 }, - new Item() { Description = "Selling Item 3 VAT 22%", Quantity = 2.5m, UnitPrice = 100.17m, VatGroup = 1 }, - new Item() { Description = "Selling Item 4 VAT 10%", Quantity = 12.13m, UnitPrice = 216.17m, VatGroup = 2 }, - new Item() { Description = "Selling Item 5 4%", Quantity = 12.13m, UnitPrice = 216.17m, VatGroup = 3 }, - }, - PaymentAdjustments = new List() - { - new PaymentAdjustment() - { - Description = "Discount", - Amount = -5.12m, - VatGroup = 1, - }, - new PaymentAdjustment() - { - Description = "Surcharge", - Amount = 3.12m, - VatGroup = 2, - }, - new PaymentAdjustment() - { - Description = "Discount applied to the subtotal", - Amount = -100.12m - } - }, - Payments = new List() - { - new Payment(){ Description = "Payment in cash", Amount = 0, PaymentType = PaymentType.Cash} - } +// var fiscalReceiptRequest = new FiscalReceiptInvoice() +// { +// Barcode = "0123456789", +// DisplayText = "Message on customer display", +// Items = new List() +// { +// new Item() { Description = "PANINO", Quantity = 1, UnitPrice = 6.00m, VatGroup = 2 }, +// new Item() { Description = "Selling Item 2 VAT 22%", Quantity = 1.234m, UnitPrice = 10.00m, VatGroup = 1 }, +// new Item() { Description = "Selling Item 3 VAT 22%", Quantity = 2.5m, UnitPrice = 100.17m, VatGroup = 1 }, +// new Item() { Description = "Selling Item 4 VAT 10%", Quantity = 12.13m, UnitPrice = 216.17m, VatGroup = 2 }, +// new Item() { Description = "Selling Item 5 4%", Quantity = 12.13m, UnitPrice = 216.17m, VatGroup = 3 }, +// }, +// PaymentAdjustments = new List() +// { +// new PaymentAdjustment() +// { +// Description = "Discount", +// Amount = -5.12m, +// VatGroup = 1, +// }, +// new PaymentAdjustment() +// { +// Description = "Surcharge", +// Amount = 3.12m, +// VatGroup = 2, +// }, +// new PaymentAdjustment() +// { +// Description = "Discount applied to the subtotal", +// Amount = -100.12m +// } +// }, +// Payments = new List() +// { +// new Payment(){ Description = "Payment in cash", Amount = 0, PaymentType = PaymentType.Cash} +// } - }; +// }; - var xml = epsonXmlWriter.CreateInvoiceRequestContent(fiscalReceiptRequest); - WriteFile(xml, "FiscalReceiptInvoice"); - } - [Fact] - public void CommercailDocument_SendRefundItem_CreateValidXml() - { - var epsonScuConfiguration = new EpsonScuConfiguration(); - var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); - var fiscalReceiptRequest = new FiscalReceiptRefund() - { - Operator = "1", - DisplayText = "REFUND 0279 0010 08012021 99MEY123456", - Refunds= new List() - { - new Refund(){ UnitPrice = 600, Quantity = 1, VatGroup = 1, Description = "TV" } - }, - Payments = new List() - { - new Payment(){ Description = "Payment in cash", Amount= 600, PaymentType = PaymentType.Cash} - } +// var xml = epsonXmlWriter.CreateInvoiceRequestContent(fiscalReceiptRequest); +// WriteFile(xml, "FiscalReceiptInvoice"); +// } +// [Fact] +// public void CommercailDocument_SendRefundItem_CreateValidXml() +// { +// var epsonScuConfiguration = new EpsonRTPrinterSCUConfiguration(); +// var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); +// var fiscalReceiptRequest = new FiscalReceiptRefund() +// { +// Operator = "1", +// DisplayText = "REFUND 0279 0010 08012021 99MEY123456", +// Refunds= new List() +// { +// new Refund(){ UnitPrice = 600, Quantity = 1, VatGroup = 1, Description = "TV" } +// }, +// Payments = new List() +// { +// new Payment(){ Description = "Payment in cash", Amount= 600, PaymentType = PaymentType.Cash} +// } - }; - var xml = epsonXmlWriter.CreateRefundRequestContent(fiscalReceiptRequest); - WriteFile(xml, "FiscalReceiptRefund"); - } +// }; +// var xml = epsonXmlWriter.CreateRefundRequestContent(fiscalReceiptRequest); +// WriteFile(xml, "FiscalReceiptRefund"); +// } - [Fact] - public void CommercailDocument_SendInvoiceWithLottery_CreateValidXml() - { - var epsonScuConfiguration = new EpsonScuConfiguration(); - var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); - var fiscalReceiptRequest = new FiscalReceiptInvoice() - { - Operator = "1", - DisplayText = "Message on customer display", - LotteryID= "ABCDEFGN", - Items = new List() - { - new Item(){ Quantity = 1, UnitPrice = 6, VatGroup = 1, Description = "PANINO" } - }, - Payments = new List() - { - new Payment(){ Description = "Payment in cash", Amount= 0, PaymentType = PaymentType.Cash} - } - }; - var xml = epsonXmlWriter.CreateInvoiceRequestContent(fiscalReceiptRequest); - WriteFile(xml, "FiscalReceiptLottery"); - } - [Fact] - public void CommercailDocument_SendInvoiceWithDepositAdjustment_CreateValidXml() - { - var epsonScuConfiguration = new EpsonScuConfiguration(); - var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); - var fiscalReceiptRequest = new FiscalReceiptInvoice() - { - Operator = "1", - DisplayText = "Message on customer display", - Items = new List() - { - new Item(){ Quantity = 1, UnitPrice = 650, VatGroup = 1, Description = "TELEVISION" } - }, - PaymentAdjustments = new List() - { - new PaymentAdjustment(){ Description = "DEPOSIT ADJUSTMENT", Amount = 100} - }, - Payments = new List() - { - new Payment(){ Description = "Payment in cash", Amount= 550, PaymentType = PaymentType.Cash} - } - }; - var xml = epsonXmlWriter.CreateInvoiceRequestContent(fiscalReceiptRequest); - WriteFile(xml, "FiscalReceiptInvoiceDepositAdjustment"); - } +// [Fact] +// public void CommercailDocument_SendInvoiceWithLottery_CreateValidXml() +// { +// var epsonScuConfiguration = new EpsonRTPrinterSCUConfiguration(); +// var epsonXmlWriter = new EpsonCommandFactory(epsonScuConfiguration); +// var fiscalReceiptRequest = new FiscalReceiptInvoice() +// { +// Operator = "1", +// DisplayText = "Message on customer display", +// LotteryID= "ABCDEFGN", +// Items = new List() +// { +// new Item(){ Quantity = 1, UnitPrice = 6, VatGroup = 1, Description = "PANINO" } +// }, +// Payments = new List() +// { +// new Payment(){ Description = "Payment in cash", Amount= 0, PaymentType = PaymentType.Cash} +// } +// }; +// var xml = epsonXmlWriter.CreateInvoiceRequestContent(fiscalReceiptRequest); +// WriteFile(xml, "FiscalReceiptLottery"); +// } +// [Fact] +// public void CommercailDocument_SendInvoiceWithDepositAdjustment_CreateValidXml() +// { +// var epsonScuConfiguration = new EpsonRTPrinterSCUConfiguration(); +// var epsonXmlWriter = new (epsonScuConfiguration); +// var fiscalReceiptRequest = new FiscalReceiptInvoice() +// { +// Operator = "1", +// DisplayText = "Message on customer display", +// Items = new List() +// { +// new Item(){ Quantity = 1, UnitPrice = 650, VatGroup = 1, Description = "TELEVISION" } +// }, +// PaymentAdjustments = new List() +// { +// new PaymentAdjustment(){ Description = "DEPOSIT ADJUSTMENT", Amount = 100} +// }, +// Payments = new List() +// { +// new Payment(){ Description = "Payment in cash", Amount= 550, PaymentType = PaymentType.Cash} +// } +// }; +// var xml = EpsonCommandFactory.CreateInvoiceRequestContent(fiscalReceiptRequest); +// WriteFile(xml, "FiscalReceiptInvoiceDepositAdjustment"); +// } - private static void WriteFile(string xml, string filename) - { - if (File.Exists(filename)) - { - File.Delete(filename); - } +// private static void WriteFile(string xml, string filename) +// { +// if (File.Exists(filename)) +// { +// File.Delete(filename); +// } - File.WriteAllText(filename, xml); - } - } -} +// File.WriteAllText(filename, xml); +// } +// } +//} diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/PrinterResponseTests.cs b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/PrinterResponseTests.cs index 963d9d267..29c506952 100644 --- a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/PrinterResponseTests.cs +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/PrinterResponseTests.cs @@ -1,8 +1,8 @@ -using fiskaltrust.Middleware.SCU.IT.Epson.Utilities; -using Xunit; +using Xunit; using System.IO; using FluentAssertions; -using fiskaltrust.Middleware.SCU.IT.Epson.Models; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Utilities; +using fiskaltrust.Middleware.SCU.IT.EpsonRTPrinter.Models; namespace fiskaltrust.Middleware.SCU.IT.UnitTest { @@ -26,7 +26,7 @@ public void GetPrinterResponse_PrinterStatusBasic_CreateObject() { var file = new StreamReader(Path.Combine("Testdata", "ResponsePrinterStatusBasic.xml")); file.BaseStream.Position = 0; - var response = EpsonCommandFactory.Deserialize(file.BaseStream); + var response = SoapSerializer.Deserialize(file.BaseStream); Assert.NotNull(response); response.Printerstatus.CpuRel.Should().Be("07.00"); response.Printerstatus.MfRel.Should().Be("04.3"); @@ -39,7 +39,7 @@ public void GetPrinterResponse_PrinterStatus_CreateObject() { var file = new StreamReader(Path.Combine("Testdata", "ResponsePrinterStatus.xml")); file.BaseStream.Position = 0; - var response = EpsonCommandFactory.Deserialize(file.BaseStream); + var response = SoapSerializer.Deserialize(file.BaseStream); Assert.NotNull(response); response.Printerstatus.RtType.Should().Be("12"); response.Printerstatus.MainStatus.Should().Be("23"); diff --git a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/fiskaltrust.Middleware.SCU.IT.UnitTest.csproj b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/fiskaltrust.Middleware.SCU.IT.UnitTest.csproj index d21948541..f086db1c6 100644 --- a/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/fiskaltrust.Middleware.SCU.IT.UnitTest.csproj +++ b/scu-it/test/fiskaltrust.Middleware.SCU.IT.UnitTest/fiskaltrust.Middleware.SCU.IT.UnitTest.csproj @@ -7,8 +7,9 @@ + - + @@ -24,7 +25,7 @@ - +