From 96a083ad775319f106cb8b7b475416047af3b18e Mon Sep 17 00:00:00 2001 From: giannipapetti <43778383+giannipapetti@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:16:11 +0200 Subject: [PATCH 1/5] Initial commit --- README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ebd8fcf --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# portale-fatturazione-be +Repo backend Portale Fatturazione From be4ee940ce1e37ebc1c7d6298c3c0d4b4f32c7b1 Mon Sep 17 00:00:00 2001 From: giannipapetti <43778383+giannipapetti@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:24:49 +0200 Subject: [PATCH 2/5] Create CODEOWNERS --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..a4ca715 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +@pagopa/portalefatturazione-admin From 554a73492f7101413e45d084ea4d7e49c0c2bc42 Mon Sep 17 00:00:00 2001 From: AntonioFrancucci <125978707+AntonioFrancucci@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:01:40 +0200 Subject: [PATCH 3/5] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index a4ca715..c2bb299 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -@pagopa/portalefatturazione-admin +@pagopa/portalefatturazione-admin @pagopa/portalefatturazione-externals From 95f94b7217c94807257b42b0832293c2fdbadf57 Mon Sep 17 00:00:00 2001 From: AntonioFrancucci <125978707+AntonioFrancucci@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:02:50 +0200 Subject: [PATCH 4/5] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index c2bb299..5d141bc 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -@pagopa/portalefatturazione-admin @pagopa/portalefatturazione-externals +* @pagopa/portalefatturazione-admin @pagopa/portalefatturazione-externals From b26a2dc222d62dfada72774d27da24cdd9fa3870 Mon Sep 17 00:00:00 2001 From: Tommaso Rossi <136076680+trossibip@users.noreply.github.com> Date: Thu, 18 Jul 2024 12:00:48 +0200 Subject: [PATCH 5/5] Import repository with Azure DevOps (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ++ init * Merged PR 2: Dati Configurazione Modulo commessa backend Related work items: #204 * ++ * ++ * ++ * ++ * fix config modulo commessa ++ * ++ * ++ * ++ * total ++ * self care ++ * ContrattoQueryHandler ++ * stato commessa ++ * ++ totale * ++ notifiche digitali * ++ * Auth Login transient token Related work items: #199 * Migrations 8 .net core Related work items: #227 * Auth Endpoints Related work items: #170 * Gestione dei segreti in Key Vault Related work items: #228 * Gestione attività lavorazione modulo commessa Related work items: #229 * Log dati su db Related work items: #172 * Bug fix mese anno modulo commessa Bug fix mese anno modulo commessa * Totali Pdf Totali Pdf * Gestione campi stringa in documento con valuta Related work items: #234 * Gestione multicontratto modulo commessa lista Related work items: #235 * Log dati ApplicationInsights Related work items: #174 * Dati Fatturazione Modifica Specifiche Related work items: #239 * Nonce + Dati Fatturazione Related work items: #231 * DatiFatturazioneContattoInvalid ++ * DateTime? ++ * Armonizzazione Token MS Related work items: #238 * Azure AD integration Related work items: #194 * Log extended Related work items: #251 * view vModuliCommessa Related work items: #257 * Excel caption Related work items: #258 * fix categoria digitale ++ * Notifiche Ente Related work items: #250 * PagoPA Notifiche Related work items: #247 * Fix Query Notifiche Related work items: #259 * Supporto Send Chiudi Send Related work items: #260 * Merged PR 63: Azure AD csv contestazioni Related work items: #261 * Recipient Id Missing Related work items: #262 * Notifiche Related work items: #263 * Scadenziario Contestazioni Related work items: #264 * Stato ricerca modulo commessa Related work items: #265 * Fix chiusa stimata Related work items: #266 * Excel campi Related work items: #275 * REL Related work items: #182 * Bug Fix visualizzazione Related work items: #291 * Aggiunta campi report notifiche Related work items: #299 * Institution type Related work items: #301 * Recap & Conso Related work items: #289 * Onere Recapitisti Consolidatori Related work items: #307 * Azure Ad Filtro rec e con Related work items: #309 * Filtro anonimizzazione Recapitisti e Consolidatori Related work items: #311 * Modifica Elaborazione dati REL righe Asseverazione Related work items: #298 * Notifiche Sospese Related work items: #302 * Ricerca API multipla ragione sociale Modulo Commessa/Dati Fatturazione Related work items: #315 * 404 Rel Enti Related work items: #329 * 404 Related work items: #330 * Asseverazione Comuni Related work items: #327 * Quadratura notifiche Related work items: #332 * Font pdf footer Related work items: #334 * Totale > 0 Rel testata email Related work items: #335 * REL --404 enti REL --404 enti * Output Azure Function detect error infra Related work items: #337 * Gestione lista fatture Related work items: #342 * Excel grid fatture Related work items: #345 * Indice Rel Righe Indice Rel Righe * Csv rel righe Related work items: #347 * Csv output Related work items: #350 * Report fatture Related work items: #351 * Reports Fatture Related work items: #352 * Id fattura in report Related work items: #357 * REL semestrale Related work items: #363 * Campi mancanti csv enti + azure/AD Related work items: #407 * ++ * Merged PR 123: chore: Pipeline for syncing GitHub public repo on tag chore: Pipeline for syncing GitHub public repo on tag --------- Co-authored-by: Mauro Ghiani --- .devops/sync-github.yml | 19 + .dockerignore | 30 + .editorconfig | 65 ++ .gitattributes | 11 + .gitignore | 534 ++++++++++++++ PortaleFatture.BE.Api.sln | 89 +++ .../PortaleFatture.BE.Core/Auth/AuthType.cs | 7 + .../Auth/AuthenticationInfo.cs | 16 + .../Auth/CustomClaim.cs | 22 + .../Auth/IAuthenticationInfo.cs | 16 + .../Auth/IIdentityUsersService.cs | 12 + .../Auth/IProfileService.cs | 9 + .../Auth/ITokenService.cs | 8 + .../Auth/JwtConfiguration.cs | 8 + .../Auth/PagoPA/GroupRoles.cs | 20 + .../Auth/PagoPA/PagoPADto.cs | 21 + .../PortaleFatture.BE.Core/Auth/Product.cs | 7 + .../Auth/ProfileInfo.cs | 19 + .../PortaleFatture.BE.Core/Auth/Profilo.cs | 20 + src/Core/PortaleFatture.BE.Core/Auth/Ruolo.cs | 16 + .../Auth/SelfCare/SelfCareDto.cs | 50 ++ .../Auth/SelfCare/SelfCareHeader.cs | 15 + .../Auth/SelfCare/SelfCareOrganizationDto.cs | 24 + .../Auth/SelfCare/SelfCareRoleDto.cs | 15 + .../PortaleFatture.BE.Core/Auth/UtenteInfo.cs | 19 + .../Common/AsyncHelper.cs | 26 + .../Common/IPortaleFattureOptions.cs | 19 + .../Common/PortaleFattureOptions.cs | 35 + .../DatiFatturazioni/DatiFatturazione.cs | 29 + .../DatiFatturazioneContatto.cs | 11 + .../DatiFatturazioneStorico.cs | 14 + ...tiConfigurazioneModuloCategoriaCommessa.cs | 22 + .../DatiConfigurazioneModuloCommessa.cs | 7 + .../DatiConfigurazioneModuloTipoCommessa.cs | 24 + .../DatiModuloCommesse/DatiModuloCommessa.cs | 39 + .../DatiModuloCommessaParzialiTotale.cs | 26 + .../DatiModuloCommessaTotale.cs | 27 + .../Dto/ModuloCommessaByAnnoDto.cs | 25 + .../Dto/ModuloCommessaDocumentoDto.cs | 68 ++ .../Dto/ModuloCommessaDto.cs | 11 + .../Dto/ModuloCommesseDateByAnnoDto.cs | 8 + .../DatiModuloCommesse/StatoModuloCommessa.cs | 10 + .../DatiRel/Dto/RelAzioneDocumento.cs | 10 + .../Entities/DatiRel/Dto/RelDocumentoDto.cs | 23 + .../Entities/DatiRel/Dto/RelEmail.cs | 19 + .../DatiRel/Dto/RelTestataDettaglioDto.cs | 83 +++ .../Entities/DatiRel/RelTestata.cs | 59 ++ .../Entities/DatiRel/RelTestataKey.cs | 37 + .../Entities/DatiRel/RelUpload.cs | 30 + .../Entities/DatiRel/TipologiaFattura.cs | 13 + .../Entities/Fattura/FatturaExtensions.cs | 8 + .../Entities/Notifiche/Contestazione.cs | 70 ++ .../Notifiche/Dto/AzioneNotificaDto.cs | 13 + .../Entities/Notifiche/FlagContestazione.cs | 15 + .../Entities/Notifiche/Notifica.cs | 110 +++ .../Entities/Notifiche/NotificaExtensions.cs | 31 + .../Notifiche/SoggettoContestazione.cs | 95 +++ .../Entities/Notifiche/StatoContestazione.cs | 13 + .../Entities/Notifiche/TipoContestazione.cs | 12 + .../Entities/Notifiche/TipoNotifica.cs | 11 + .../Scadenziari/CalendarioContestazione.cs | 26 + .../Entities/Scadenziari/Dto/Calendario.cs | 9 + .../Entities/Scadenziari/Scadenziario.cs | 11 + .../Entities/Scadenziari/TipoScadenziario.cs | 7 + .../Entities/SelfCare/Contratto.cs | 16 + .../Entities/SelfCare/Dto/EnteContrattoDto.cs | 19 + .../Entities/SelfCare/Ente.cs | 48 ++ .../Entities/Storici/Storico.cs | 13 + .../Entities/Storici/TipoStorico.cs | 8 + .../Entities/Tipologie/CategoriaSpedizione.cs | 13 + .../Entities/Tipologie/Prodotto.cs | 10 + .../Entities/Tipologie/StatoCommessa.cs | 10 + .../Entities/Tipologie/TipoCommessa.cs | 10 + .../Entities/Tipologie/TipoContratto.cs | 11 + .../Entities/Tipologie/TipoSpedizione.cs | 14 + .../Entities/Utenti/Utente.cs | 13 + .../Exceptions/ConfigurationException.cs | 16 + .../Exceptions/DomainException.cs | 12 + .../Exceptions/NotFoundException.cs | 16 + .../Exceptions/RoleException.cs | 12 + .../Exceptions/SessionException.cs | 16 + .../Exceptions/ValidationException.cs | 16 + .../Extensions/DocumentExtensions.cs | 283 ++++++++ .../Extensions/DomainExtensions.cs | 31 + .../Extensions/SerializationExtensions.cs | 25 + .../Extensions/ValidationExtensions.cs | 41 ++ .../PortaleFatture.BE.Core.csproj | 8 + .../Resources/Localization.cs | 5 + .../Resources/Localization.en.resx | 120 +++ .../Resources/Localization.it.resx | 270 +++++++ ...sserverazioneImportCreateCommandHandler.cs | 37 + .../EnteAsserverazioneImportCreateCommand.cs | 23 + ...verazioneImportCreateCommandPersistence.cs | 38 + .../Dto/EnteAsserverazioneDto.cs | 95 +++ .../Dto/EnteAsserverazioneImportDto.cs | 9 + .../Extensions/AsseverazioneExtensions.cs | 55 ++ .../Queries/AsseverazioneQueryGet.cs | 10 + .../AsseverazioneQueryGetPersistence.cs | 23 + .../Builder/AsseverazioneSQLBuilder.cs | 54 ++ .../AsseverazioneQueryGetHandler.cs | 29 + .../DatiFatturazioneCreateCommandHandler.cs | 95 +++ .../DatiFatturazioneUpdateCommandHandler.cs | 97 +++ .../DatiFatturazioneContattoCreateCommand.cs | 13 + ...tiFatturazioneContattoCreateListCommand.cs | 12 + .../DatiFatturazioneContattoDeleteCommand.cs | 11 + .../Commands/DatiFatturazioneCreateCommand.cs | 21 + .../Commands/DatiFatturazioneUpdateCommand.cs | 22 + ...oneContattoCreateListCommandPersistence.cs | 21 + ...razioneContattoDeleteCommandPersistence.cs | 17 + ...atiFatturazioneCreateCommandPersistence.cs | 54 ++ ...atiFatturazioneUpdateCommandPersistence.cs | 55 ++ .../DatiFatturazioneMapper.cs | 39 + .../DatiFatturazioneValidator.cs | 93 +++ .../Dto/DatiFatturazioneEnteDto.cs | 92 +++ .../DatiFatturazioneQueryGetByDescrizione.cs | 14 + .../Queries/DatiFatturazioneQueryGetById.cs | 11 + .../DatiFatturazioneQueryGetByIdEnte.cs | 14 + .../DatiFatturazioneContattoSQLBuilder.cs | 35 + .../Builder/DatiFatturazioneSQLBuilder.cs | 122 ++++ .../DatiFatturazioneStoricoSQLBuilder.cs | 39 + ...urazioneContattoQueryGetByIdPersistence.cs | 21 + ...razioneQueryGetByDescrizionePersistence.cs | 39 + ...FatturazioneQueryGetByIdEntePersistence.cs | 30 + ...DatiFatturazioneQueryGetByIdPersistence.cs | 30 + ...zioneStoricoQueryGetByIdEntePersistence.cs | 26 + ...ioneWithContattiQueryGetByIdPersistence.cs | 26 + ...atturazioneQueryGetByDescrizioneHandler.cs | 45 ++ ...DatiFatturazioneQueryGetByIdEnteHandler.cs | 37 + .../DatiFatturazioneQueryGetByIdHandler.cs | 36 + ...zioneModuloCommessaCreateCommandHandler.cs | 119 +++ .../DatiModuloCommessaCreateCommandHandler.cs | 174 +++++ ...nfigurazioneModuloCommessaCreateCommand.cs | 33 + ...nfigurazioneModuloCommessaUpdateCommand.cs | 31 + .../DatiModuloCommessaCreateCommand.cs | 26 + .../DatiModuloCommessaCreateListCommand.cs | 12 + .../DatiModuloCommessaTotaleCreateCommand.cs | 22 + ...tiModuloCommessaTotaleCreateListCommand.cs | 21 + ...eModuloCommessaCreateCommandPersistence.cs | 56 ++ ...eModuloCommessaUpdateCommandPersistence.cs | 36 + ...iModuloCommessaCreateCommandPersistence.cs | 91 +++ ...oCommessaCreateTotaleCommandPersistence.cs | 78 ++ ...tiConfigurazioneModuloCommessaValidator.cs | 83 +++ .../DatiModuloCommessaExtensions.cs | 121 +++ .../DatiModuloCommessaMapper.cs | 7 + .../DatiModuloCommessaValidator.cs | 46 ++ .../Dto/ModuloCommessaByRicercaDto.cs | 121 +++ ...atiConfigurazioneModuloCommessaQueryGet.cs | 12 + .../DatiModuloCommessaDocumentoQueryGet.cs | 11 + .../Queries/DatiModuloCommessaGetAnni.cs | 10 + ...atiModuloCommessaParzialiQueryGetByAnno.cs | 15 + .../Queries/DatiModuloCommessaQueryGet.cs | 16 + .../DatiModuloCommessaQueryGetByAnno.cs | 11 + ...DatiModuloCommessaQueryGetByDescrizione.cs | 13 + .../DatiModuloCommessaTotaleQueryGet.cs | 15 + ...iConfigurazioneModuloCommessaSQLBuilder.cs | 87 +++ .../DatiModuloCommessaAnniSQLBuilder.cs | 38 + .../Builder/DatiModuloCommessaSQLBuilder.cs | 128 ++++ .../DatiModuloCommessaTotaleSQLBuilder.cs | 80 ++ ...azioneModuloCommessaQueryGetPersistence.cs | 40 + ...duloCommessaDateQueryGetByIdPersistence.cs | 35 + ...saParzialiTotaleQueryGetByIdPersistence.cs | 73 ++ ...tiModuloCommessaQueryGetAnniPersistence.cs | 22 + ...ModuloCommessaQueryGetByAnnoPersistence.cs | 25 + ...ommessaQueryGetByDescrizionePersistence.cs | 34 + ...tiModuloCommessaQueryGetByIdPersistence.cs | 27 + ...loCommessaTotaleQueryGetByIdPersistence.cs | 34 + ...onfigurazioneModuloCommessaQueryHandler.cs | 33 + .../DatiModuloCommessaGetAnniHandler.cs | 35 + .../DatiModuloCommessaQueryByAnnoHandler.cs | 108 +++ ...ModuloCommessaQueryByDescrizioneHandler.cs | 31 + ...oduloCommessaQueryByParzialiAnnoHandler.cs | 46 ++ ...DatiModuloCommessaQueryDocumentoHandler.cs | 71 ++ .../DatiModuloCommessaQueryHandler.cs | 99 +++ .../RelBulkDownloadCommandHandler.cs | 32 + .../RelDownloadCommandHandler.cs | 33 + .../RelFatturabileByIdEntiCommandHandler.cs | 32 + .../RelUploadCreateCommandHandler.cs | 53 ++ .../RelBulkUploadCreateCommandPersistence.cs | 42 ++ ...elFatturabileByIdEntiCommandPersistence.cs | 26 + .../RelTestataUpdateCommandPersistence.cs | 29 + .../RelUploadCreateCommandPersistence.cs | 42 ++ .../Commands/RelBulkDownloadCommand.cs | 12 + .../DatiRel/Commands/RelDownloadCommand.cs | 20 + .../Commands/RelFatturabileByIdEnti.cs | 13 + .../Commands/RelUploadCreateCommand.cs | 20 + .../Commands/RelUploadStateCreateCommand.cs | 16 + .../Common/DatiRel/Dto/RelQuadraturaDto.cs | 169 +++++ .../Common/DatiRel/Dto/RelQueryDto.cs | 15 + .../Common/DatiRel/Dto/RelTestataDto.cs | 13 + .../DatiRel/Dto/RelTestataQuadraturaDto.cs | 13 + .../Common/DatiRel/Dto/RelVerificaDto.cs | 22 + .../Common/DatiRel/Dto/RigheRelDto.cs | 142 ++++ .../Common/DatiRel/Dto/SimpleRelTestata.cs | 199 +++++ .../Extensions/DatiRelInfraExtensions.cs | 84 +++ .../Persistence/Builder/RelRigheSQLBuilder.cs | 48 ++ .../Builder/RelTestataQuadraturaSQLBuilder.cs | 196 +++++ .../Builder/RelTestataSQLBuilder.cs | 152 ++++ .../Builder/RelUploadSQLBuilder.cs | 25 + .../RelRigheQueryGetByIdPersistence.cs | 70 ++ .../RelTestataQueryGetByIdEntePersistence.cs | 82 +++ .../RelTestataQueryGetByIdPersistence.cs | 66 ++ ...elTestataQueryGetByListaEntiPersistence.cs | 91 +++ ...ueryGetByListaEntiQuadraturaPersistence.cs | 93 +++ .../RelTipologieFattureByIdEntePersistence.cs | 43 ++ .../RelTipologieFattureByPagoPAPersistence.cs | 39 + .../RelUploadQueryGetByIdPersistence.cs | 52 ++ .../DatiRel/Queries/RelRigheQueryGetById.cs | 11 + .../DatiRel/Queries/RelTestataQueryGetById.cs | 11 + .../Queries/RelTestataQueryGetByIdEnte.cs | 18 + .../Queries/RelTestataQueryGetByListaEnti.cs | 18 + ...RelTestataQueryGetByListaEntiQuadratura.cs | 18 + .../Queries/RelTipologieFattureByIdEnte.cs | 11 + .../Queries/RelTipologieFattureByPagoPA.cs | 11 + .../DatiRel/Queries/RelUploadGetById.cs | 20 + .../DatiRel/Queries/RelVerificaByIdEnti.cs | 12 + .../RelRigheQueryGetByIdHandler.cs | 26 + .../RelTestataQueryGetByIdEnteHandler.cs | 56 ++ .../RelTestataQueryGetByIdHandler.cs | 25 + .../RelTestataQueryGetByListaEntiHandler.cs | 25 + ...ataQueryGetByListaEntiQuadraturaHandler.cs | 25 + ...RelTipologieFattureByIdEnteQueryHandler.cs | 23 + ...RelTipologieFattureByPagoPAQueryHandler.cs | 23 + .../RelUploadQueryGetByIdHandler.cs | 26 + .../RelVerificaByIdEntiQueryHandler.cs | 26 + .../DatiRel/Services/EmailRelService.cs | 118 +++ .../DatiRel/Services/IEmailRelService.cs | 10 + .../Common/Documenti/Common/CsvMapper.cs | 136 ++++ .../Documenti/Common/ExcelExtensions.cs | 537 ++++++++++++++ .../Documenti/Common/HeaderAttribute.cs | 34 + .../Documenti/Common/ReflectionExtensions.cs | 308 ++++++++ .../Common/Documenti/Common/Style.cs | 14 + .../Common/Documenti/Common/TypeFinder.cs | 38 + .../Common/Documenti/DocumentBuilder.cs | 129 ++++ .../Common/Documenti/IDocumentBuilder.cs | 14 + .../Fatture/Dto/DatiGeneraliDocumentoDto.cs | 30 + .../Common/Fatture/Dto/FatturaDto.cs | 7 + .../Fatture/Dto/FattureAccontoExcelDto.cs | 95 +++ .../Fatture/Dto/FattureCommessaExcelDto.cs | 146 ++++ .../Common/Fatture/Dto/FattureExcel.cs | 94 +++ .../Common/Fatture/Dto/FattureListaDto.cs | 6 + .../Common/Fatture/Dto/FattureRelExcelDto.cs | 137 ++++ .../Common/Fatture/Dto/PosizioniDto.cs | 24 + .../Common/Fatture/Dto/TitoloFatturaDto.cs | 63 ++ .../Queries/FattureAccontoExcelQuery.cs | 13 + .../Queries/FattureCommessaExcelQuery.cs | 13 + .../Fatture/Queries/FattureQueryRicerca.cs | 14 + .../Fatture/Queries/FattureRelExcelQuery.cs | 15 + .../FattureAccontoFatturaExcelBuilder.cs | 17 + .../FattureModuloCommessaExcelBuilder.cs | 37 + .../Builder/FattureQueryRicercaBuilder.cs | 74 ++ .../Builder/FattureRelExcelBuilder.cs | 111 +++ ...reAccontoFatturaExcelBuilderPersistence.cs | 37 + ...reModuloCommessaExcelBuilderPersistence.cs | 39 + ...FattureNotaNoRelExcelBuilderPersistence.cs | 67 ++ .../FattureQueryRicercaPersistence.cs | 62 ++ .../FattureRelExcelBuilderPersistence.cs | 71 ++ .../FattureUnionRelExcelBuilderPersistence.cs | 72 ++ .../FattureAccontoFatturaExcelHandler.cs | 25 + .../FattureModuloCommessaExcelHandler.cs | 31 + .../FattureQueryRicercaHandler.cs | 24 + .../QueryHandlers/FattureRelExcelHandler.cs | 32 + .../Common/Identity/DisplayNameRole.cs | 13 + .../Identity/Extensions/IdentityExtensions.cs | 13 + .../Common/Identity/IdentityExtensions.cs | 56 ++ .../Common/Identity/IdentityUsersService.cs | 77 ++ .../Common/Identity/JwtTokenService.cs | 72 ++ .../Common/Identity/ProfileService.cs | 183 +++++ .../Common/JsonTypeHandler.cs | 22 + .../ContestazioneCreateCommandHandler.cs | 107 +++ .../ContestazioneUpdateCommandHandler.cs | 140 ++++ ...azioneUpdateConsolidatoreCommandHandler.cs | 112 +++ ...ContestazioneUpdatePagoPaCommandHandler.cs | 134 ++++ ...stazioneUpdateRecapitistaCommandHandler.cs | 110 +++ .../Commands/ContestazioneCreateCommand.cs | 17 + .../Commands/ContestazioneUpdateCommand.cs | 18 + ...ContestazioneUpdateConsolidatoreCommand.cs | 18 + .../ContestazioneUpdatePagoPACommand.cs | 18 + .../ContestazioneUpdateRecapitistaCommand.cs | 18 + .../ContestazioneCreateCommandPersistence.cs | 51 ++ .../ContestazioneUpdateCommandPersistence.cs | 32 + ...neUpdateConsolidatoreCommandPersistence.cs | 30 + ...estazioneUpdatePagoPACommandPersistence.cs | 32 + ...ioneUpdateRecapitistaCommandPersistence.cs | 32 + .../Common/Notifiche/Dto/NotificaDto.cs | 20 + .../Common/Notifiche/Dto/QueryDto.cs | 23 + .../Common/Notifiche/Dto/RECCONNotificaDto.cs | 140 ++++ .../Common/Notifiche/Dto/SimpleNotificaDto.cs | 184 +++++ ...AzioneContestazioneQueryGetByIdNotifica.cs | 12 + .../ContestazioneQueryGetByIdNotifica.cs | 12 + .../NotificaQueryGetByConsolidatore.cs | 22 + .../Notifiche/Queries/NotificaQueryGetById.cs | 12 + .../Queries/NotificaQueryGetByIdEnte.cs | 22 + .../Queries/NotificaQueryGetByListaEnti.cs | 25 + .../Queries/NotificaQueryGetByRecapitista.cs | 22 + .../Builder/ContestazioneSQLBuilder.cs | 57 ++ .../Persistence/Builder/NotificaSQLBuilder.cs | 89 +++ ...stazioneQueryGetByIdNotificaPersistence.cs | 26 + ...ificaQueryGetByConsolidatorePersistence.cs | 125 ++++ .../NotificaQueryGetByIdEntePersistence.cs | 122 ++++ .../NotificaQueryGetByIdPersistence.cs | 28 + .../NotificaQueryGetByListEntiPersistence.cs | 141 ++++ ...otificaQueryGetByRecapitistaPersistence.cs | 124 ++++ ...ontestazioneQueryGetByIdNotificaHandler.cs | 225 ++++++ ...ontestazioneQueryGetByIdNotificaHandler.cs | 25 + .../NotificaQueryGetByConsolidatoreHandler.cs | 42 ++ .../NotificaQueryGetByIdEnteHandler.cs | 41 ++ .../NotificaQueryGetByIdHandlandler.cs | 25 + .../NotificaQueryGetByListEntiHandler.cs | 25 + .../NotificaQueryGetByRecapitistaHandler.cs | 39 + .../Common/Persistence/DapperBase.cs | 76 ++ .../Common/Persistence/DbContext.cs | 81 +++ .../Common/Persistence/DbContextFactory.cs | 25 + .../Common/Persistence/ICommand.cs | 14 + .../Common/Persistence/IDatabase.cs | 13 + .../Common/Persistence/IDbContext.cs | 13 + .../Common/Persistence/IDbContextFactory.cs | 8 + .../Common/Persistence/IQuery.cs | 6 + .../Schemas/IFattureDbContextFactory.cs | 5 + .../Schemas/ISelfCareDbContextFactory.cs | 6 + .../Common/Persistence/SqlExtensions.cs | 49 ++ .../Scadenziari/IScadenziarioService.cs | 9 + .../CalendarioContestazioneQueryGet.cs | 12 + .../CalendarioContestazioneQueryGetAll.cs | 10 + .../CalendarioContestazioneSQLBuilder.cs | 55 ++ ...arioContestazioneQueryGetAllPersistence.cs | 18 + ...endarioContestazioneQueryGetPersistence.cs | 28 + .../Queries/ScadenziarioQueryGetByTipo.cs | 13 + .../CalendarioContestazioneAllQueryHandler.cs | 27 + .../CalendarioContestazioneQueryHandler.cs | 55 ++ .../QueryHandlers/ScadenziarioQueryHandler.cs | 62 ++ .../Common/Scadenziari/ScadenziarioService.cs | 18 + .../SelfCare/Queries/ContrattoQueryGetById.cs | 14 + .../SelfCare/Queries/EnteQueryGetById.cs | 14 + .../Builder/ContrattoSQLBuilder.cs | 38 + .../Persistence/Builder/EnteSQLBuilder.cs | 44 ++ .../ContrattoQueryGetByIdPersistence.cs | 22 + .../EnteQueryGetByIdPersistence.cs | 22 + .../QueryHandlers/ContrattoQueryHandler.cs | 28 + .../QueryHandlers/EnteQueryHandler.cs | 33 + .../StoricoCreateCommandPersistence.cs | 39 + .../Storici/Commands/StoricoCreateCommand.cs | 15 + .../Queries/EnteQueryGetByDescrizione.cs | 11 + .../Queries/EnteQueryGetByRagioneSociale.cs | 12 + .../EnteQueryGetByRecapitistiConsolidatori.cs | 11 + .../Queries/FlagContestazioneQueryGetAll.cs | 10 + .../Builder/CategoriaSpedizioneSQLBuilder.cs | 26 + .../Persistence/Builder/EnteSQLBuilder.cs | 122 ++++ .../Builder/FlagContestazioneSQLBuilder.cs | 26 + .../Persistence/Builder/ProdottoSQLBuilder.cs | 25 + .../Persistence/Builder/ProfiloSQLBuilder.cs | 25 + .../Builder/StatoCommessaSQLBuilder.cs | 35 + .../Builder/TipoCommessaSQLBuilder.cs | 25 + .../Builder/TipoContestazioneSQLBuilder.cs | 25 + .../Builder/TipoContrattoSQLBuilder.cs | 27 + .../Builder/TipoFatturaSQLBuilder.cs | 21 + .../Builder/TipoSpedizioneSQLBuilder.cs | 26 + .../EnteQueryGetByDescrizionePersistence.cs | 22 + ...EnteQueryGetByRagioneSocialePersistence.cs | 25 + ...etByRecapitistiConsolidatoriPersistence.cs | 22 + ...FlagContestazioneQueryGetAllPersistence.cs | 16 + .../ProdottoQueryGetAllPersistence.cs | 18 + .../ProfiloQueryGetAllPersistence.cs | 15 + .../SpedizioneQueryGetAllPersistence.cs | 23 + ...atoCommessaQueryGetByDefaultPersistence.cs | 17 + .../TipoCommessaQueryGetAllPersistence.cs | 16 + ...TipoContestazioneQueryGetAllPersistence.cs | 16 + .../TipoContrattoQueryGetAllPersistence.cs | 16 + .../TipoFatturaQueryGetAllPersistence.cs | 20 + .../Tipologie/Queries/ProdottoQueryGetAll.cs | 10 + .../Tipologie/Queries/ProfiloQueryGetAll.cs | 9 + .../Queries/SpedizioneQueryGetAll.cs | 10 + .../Queries/StatoCommessaQueryGetByDefault.cs | 10 + .../Queries/TipoCommessaQueryGetAll.cs | 10 + .../Queries/TipoContestazioneGetAll.cs | 11 + .../Queries/TipoContrattoQueryGetAll.cs | 10 + .../Queries/TipoFatturaQueryGetAll.cs | 11 + ...eryGetByRecapitistiConsolidatoriHandler.cs | 35 + .../EntiQueryGetByDescrizioneHandler.cs | 35 + .../EntiQueryGetByRagioneSocialeHandler.cs | 34 + .../FlagContestazioneQueryHandler.cs | 26 + .../QueryHandlers/ProdottoQueryHandler.cs | 26 + .../QueryHandlers/ProfiloQueryHandler.cs | 32 + .../QueryHandlers/SpedizioneQueryHandler.cs | 33 + .../StatoCommessaQueryHandler.cs | 32 + .../QueryHandlers/TipoCommessaQueryHandler.cs | 32 + .../TipoContestazioneQueryHandler.cs | 27 + .../TipoContrattoQueryHandler.cs | 32 + .../QueryHandlers/TipoFatturaQueryHandler.cs | 32 + .../UtenteCreateCommandHandler.cs | 36 + .../UtenteCreateCommandPersistence.cs | 59 ++ .../Utenti/Commands/UtenteCreateCommand.cs | 16 + .../Persistence/Builder/UtenteSQLBuilder.cs | 39 + .../UtenteQueryGetByIdPersistence.cs | 24 + .../Utenti/Queries/UtenteQueryGetById.cs | 16 + .../QueryHandlers/UtenteQueryHandler.cs | 36 + .../ConfigurationExtensions.cs | 65 ++ .../Gateway/AesEncryption.cs | 59 ++ .../Gateway/CertificateContainer.cs | 9 + .../Gateway/CertificateKey.cs | 30 + .../Gateway/Email/EmailSender.cs | 42 ++ .../Gateway/Email/IEmailSender.cs | 7 + .../Gateway/IAesEncryption.cs | 8 + .../Gateway/IMicrosoftGraphHttpClient.cs | 8 + .../Gateway/IPagoPAHttpClient.cs | 11 + .../Gateway/IPagoPATokenService.cs | 11 + .../Gateway/ISelfCareHttpClient.cs | 11 + .../Gateway/ISelfCareTokenService.cs | 12 + .../Gateway/MicrosoftGraphGroups.cs | 23 + .../Gateway/MicrosoftGraphHttpClient.cs | 42 ++ .../Gateway/PagoPAHttpClient.cs | 70 ++ .../Gateway/PagoPATokenService.cs | 110 +++ .../Gateway/SelfCareHttpClient.cs | 78 ++ .../Gateway/SelfCareTokenService.cs | 103 +++ .../Gateway/Storage/IRelStorageService.cs | 13 + .../Gateway/Storage/RelStorage.cs | 154 ++++ .../Gateway/Storage/StorageExtensions.cs | 16 + .../PortaleFatture.BE.Infrastructure.csproj | 41 ++ .../RootInfrastructure.cs | 5 + .../PortaleFatture.BE.Api/Dockerfile | 28 + .../Infrastructure/ConfigurationExtensions.cs | 381 ++++++++++ .../Culture/CultureConfiguration.cs | 23 + .../Documenti/DisposableFileStreamResult.cs | 17 + .../Documenti/DocsExtensions.cs | 135 ++++ .../Documenti/PRIMO_SALDO_rel.html | 133 ++++ .../Documenti/SECONDO_SALDO_rel.html | 205 ++++++ .../Documenti/daticommessa.html | 273 +++++++ .../Infrastructure/IModule.cs | 5 + .../Infrastructure/IRegistrableModule.cs | 6 + .../Infrastructure/MapAttribute.cs | 24 + .../Infrastructure/Module.cs | 33 + .../Infrastructure/ModuleExtensions.cs | 158 ++++ .../Infrastructure/ModuleManager.cs | 62 ++ .../NonceMultiTabsMiddleware.cs | 38 + .../Asseverazione/AsseverazioneEndpoints.cs | 35 + .../Asseverazione/AsseverazioneModule.cs | 177 +++++ .../Extensions/AsseverazioneExtensions.cs | 22 + .../Response/AsseverazionExportResponse.cs | 45 ++ .../Modules/Auth/AuthEndpoints.cs | 28 + .../Modules/Auth/AuthModule.cs | 91 +++ .../Modules/Auth/Extensions/AuthExtensions.cs | 133 ++++ .../Modules/Auth/Extensions/NonceDto.cs | 8 + .../Auth/Payload/PagoPaLoginRequest.cs | 30 + ...tiConfigurazioneModuloCommessaEndpoints.cs | 25 + .../DatiConfigurazioneModuloCommessaModule.cs | 64 ++ ...iConfigurazioneModuloCommessaExtensions.cs | 71 ++ ...nfigurazioneModuloCommessaCreateRequest.cs | 36 + ...atiConfigurazioneModuloCommessaResponse.cs | 22 + .../DatiFatturazioneEndpoints.cs | 61 ++ .../DatiFatturazioneModule.cs | 193 +++++ .../Extensions/DatiFatturazioneExtensions.cs | 194 +++++ .../DatiFatturazioneContattoCreateRequest.cs | 9 + .../Request/DatiFatturazioneCreateRequest.cs | 24 + .../DatiFatturazionePagoPACreateRequest.cs | 29 + .../DatiFatturazionePagoPAUpdateRequest.cs | 33 + .../Request/DatiFatturazioneUpdateRequest.cs | 27 + .../Payload/Request/DocumentDto.cs | 6 + .../Response/CategoriaSpedizioneResponse.cs | 10 + .../Response/DatiCommessaContattoResponse.cs | 6 + .../Payload/Response/DatiCommessaResponse.cs | 20 + .../Payload/Response/ProdottoResponse.cs | 6 + .../Payload/Response/TipoCommessaResponse.cs | 7 + .../Payload/Response/TipoContrattoResponse.cs | 6 + .../Response/TipoSpedizioneResponse.cs | 10 + .../DatiModuloCommessaEndpoints.cs | 103 +++ .../DatiModuloCommessaModule.cs | 480 ++++++++++++ .../DatiModuloCommessaViewModelExtensions.cs | 150 ++++ .../DatiModuloCommessaCreateRequest.cs | 31 + ...cercaModuloCommessaByDescrizioneRequest.cs | 16 + .../DatiModuloCommessaByAnnoResponse.cs | 25 + ...atiModuloCommessaParzialiTotaleResponse.cs | 26 + .../Response/DatiModuloCommessaResponse.cs | 35 + .../DatiRel/Extensions/RelExtensions.cs | 129 ++++ .../Request/RelFatturabileByIdEntiRequest.cs | 9 + .../Payload/Request/RelRigheByIdRequest.cs | 6 + .../Payload/Request/RelTestataByIdRequest.cs | 6 + .../Request/RelTestataRicercaRequest.cs | 10 + .../Request/RelTestataRicercaRequestPagoPA.cs | 19 + .../RelTipologiaFatturaPagoPARequest.cs | 7 + .../Request/RelTipologiaFatturaRequest.cs | 7 + .../Payload/Request/RelUploadByIdRequest.cs | 10 + .../Modules/DatiRel/RelEndpoints.cs | 136 ++++ .../Modules/DatiRel/RelModule.cs | 686 ++++++++++++++++++ .../Fatture/Extensions/FattureExtensions.cs | 191 +++++ .../Modules/Fatture/FattureEndpoints.cs | 34 + .../Modules/Fatture/FattureModule.cs | 158 ++++ .../Payload/Request/FatturaRicercaRequest.cs | 22 + .../Request/TipologiaFattureRequest.cs | 7 + .../Extensions/NotificaExtensions.cs | 82 +++ .../Modules/Notifiche/NotificaEndpoints.cs | 119 +++ .../Modules/Notifiche/NotificaModule.cs | 578 +++++++++++++++ .../Request/ContestazioneConsolidatori.cs | 10 + .../Request/ContestazioneCreateRequest.cs | 8 + .../ContestazionePagoPAUpdateRequest.cs | 11 + .../Request/ContestazioneRecapitisti.cs | 10 + .../Request/ContestazioneUpdateRequest.cs | 10 + .../Request/NotificheRicercaRequest.cs | 15 + .../Request/NotificheRicercaRequestPagoPA.cs | 38 + .../Payload/Response/ContestazioneResponse.cs | 18 + .../Extensions/TipologieExtensions.cs | 26 + .../EnteRicercaByDescrizioneProfiloRequest.cs | 23 + .../EnteRicercaByDescrizioneRequest.cs | 6 + ...icercaByRecapitistiConsolidatoriRequest.cs | 6 + .../CalendarioContestazioniResponse.cs | 13 + .../Payload/Payload/Response/EnteResponse.cs | 7 + .../Modules/Tipologie/TipologieEndpoints.cs | 88 +++ .../Modules/Tipologie/TipologieExtensions.cs | 16 + .../Modules/Tipologie/TipologieModule.cs | 253 +++++++ .../PortaleFatture.BE.Api.csproj | 46 ++ .../PortaleFatture.BE.Api/Program.cs | 17 + .../appsettings.Development.json | 30 + .../PortaleFatture.BE.Api/appsettings.json | 30 + .../PortaleFatture.BE.Api/libman.json | 5 + .../Infrastructure/Documenti/primo_saldo.html | 11 + .../Models/Configurazione.cs | 11 + .../Models/Risposta.cs | 12 + .../PortaleFatture.BE.EmailSender.csproj | 28 + .../PortaleFatture.BE.EmailSender/Program.cs | 119 +++ .../.gitignore | 264 +++++++ .../Infrastructure/Documenti/primo_saldo.html | 11 + .../Models/Configurazione.cs | 11 + .../Models/Risposta.cs | 12 + ...PortaleFatture_BE_SendEmailFunction.csproj | 37 + .../Program.cs | 7 + .../SendEmail.cs | 126 ++++ .../host.json | 12 + tests/.env | 1 + tests/Data/Dockerfile | 10 + tests/Data/entrypoint.sh | 22 + tests/Data/setup.sql | 282 +++++++ .../GlobalUsings.cs | 1 + .../PortaleFatture.BE.IntegrationTest.csproj | 43 ++ .../SelfCareHttpClientTests.cs | 36 + .../SelfCareTokenServiceTests.cs | 46 ++ .../ServiceProvider.cs | 64 ++ .../appsettings.Development.json | 20 + .../appsettings.json | 20 + .../Common/CommonFactory.cs | 73 ++ .../Common/TestExtensions.cs | 33 + ...razioneModuloCommessaCreateCommandTests.cs | 45 ++ .../DatiFatturazioneCreateCommandTests.cs | 162 +++++ .../DatiFatturazioneGetByIdQueryTests.cs | 151 ++++ .../DatiFatturazioneUpdateCommandTests .cs | 347 +++++++++ .../DatiModuloCommessaCreateTests.cs | 108 +++ .../GlobalUsings.cs | 1 + .../PortaleFatture.BE.UnitTest.csproj | 43 ++ .../ServiceProvider.cs | 62 ++ .../appsettings.Development.json | 20 + .../appsettings.json | 20 + tests/docker-compose.yml | 20 + 549 files changed, 27140 insertions(+) create mode 100644 .devops/sync-github.yml create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 PortaleFatture.BE.Api.sln create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/AuthType.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/AuthenticationInfo.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/CustomClaim.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/IAuthenticationInfo.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/IIdentityUsersService.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/IProfileService.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/ITokenService.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/JwtConfiguration.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/PagoPA/GroupRoles.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/PagoPA/PagoPADto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/Product.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/ProfileInfo.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/Profilo.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/Ruolo.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareHeader.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareOrganizationDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareRoleDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Auth/UtenteInfo.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Common/AsyncHelper.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Common/IPortaleFattureOptions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Common/PortaleFattureOptions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneContatto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneStorico.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCategoriaCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloTipoCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaParzialiTotale.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaTotale.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaByAnnoDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDocumentoDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommesseDateByAnnoDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/StatoModuloCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelAzioneDocumento.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelDocumentoDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelEmail.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelTestataDettaglioDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestata.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestataKey.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelUpload.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/DatiRel/TipologiaFattura.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Fattura/FatturaExtensions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Contestazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Dto/AzioneNotificaDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/FlagContestazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Notifica.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/NotificaExtensions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/SoggettoContestazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/StatoContestazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoContestazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoNotifica.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/CalendarioContestazione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Dto/Calendario.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Scadenziario.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/TipoScadenziario.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Contratto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Dto/EnteContrattoDto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Ente.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Storici/Storico.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Storici/TipoStorico.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Tipologie/CategoriaSpedizione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Tipologie/Prodotto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Tipologie/StatoCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoCommessa.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoContratto.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoSpedizione.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Entities/Utenti/Utente.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Exceptions/ConfigurationException.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Exceptions/DomainException.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Exceptions/NotFoundException.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Exceptions/RoleException.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Exceptions/SessionException.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Exceptions/ValidationException.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Extensions/DocumentExtensions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Extensions/DomainExtensions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Extensions/SerializationExtensions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Extensions/ValidationExtensions.cs create mode 100644 src/Core/PortaleFatture.BE.Core/PortaleFatture.BE.Core.csproj create mode 100644 src/Core/PortaleFatture.BE.Core/Resources/Localization.cs create mode 100644 src/Core/PortaleFatture.BE.Core/Resources/Localization.en.resx create mode 100644 src/Core/PortaleFatture.BE.Core/Resources/Localization.it.resx create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/CommandHandlers/EnteAsserverazioneImportCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/EnteAsserverazioneImportCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/Persistence/EnteAsserverazioneImportCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneImportDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Extensions/AsseverazioneExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/AsseverazioneQueryGet.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/AsseverazioneQueryGetPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/Builder/AsseverazioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/QueryHandlers/AsseverazioneQueryGetHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneUpdateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateListCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoDeleteCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneUpdateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoCreateListCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoDeleteCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneUpdateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneMapper.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneValidator.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Dto/DatiFatturazioneEnteDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByDescrizione.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByIdEnte.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneContattoSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneStoricoSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneContattoQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByDescrizionePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdEntePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneStoricoQueryGetByIdEntePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneWithContattiQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByDescrizioneHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdEnteHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiConfigurazioneModuloCommessaCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiModuloCommessaCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaUpdateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateListCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateListCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaUpdateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateTotaleCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiConfigurazioneModuloCommessaValidator.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaMapper.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaValidator.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Dto/ModuloCommessaByRicercaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiConfigurazioneModuloCommessaQueryGet.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaDocumentoQueryGet.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaGetAnni.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaParzialiQueryGetByAnno.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGet.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByAnno.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByDescrizione.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaTotaleQueryGet.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiConfigurazioneModuloCommessaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaAnniSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaTotaleSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiConfigurazioneModuloCommessaQueryGetPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaDateQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetAnniPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByAnnoPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByDescrizionePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaTotaleQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiConfigurazioneModuloCommessaQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaGetAnniHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByAnnoHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByDescrizioneHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByParzialiAnnoHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryDocumentoHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelBulkDownloadCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelDownloadCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelFatturabileByIdEntiCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelUploadCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelBulkUploadCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelFatturabileByIdEntiCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelTestataUpdateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelUploadCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelBulkDownloadCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelDownloadCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelFatturabileByIdEnti.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadStateCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQuadraturaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQueryDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataQuadraturaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelVerificaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RigheRelDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/SimpleRelTestata.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Extensions/DatiRelInfraExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelRigheSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataQuadraturaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelUploadSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelRigheQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdEntePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiQuadraturaPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByIdEntePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByPagoPAPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelUploadQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelRigheQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByIdEnte.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEnti.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEntiQuadratura.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByIdEnte.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByPagoPA.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelUploadGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelVerificaByIdEnti.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelRigheQueryGetByIdHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdEnteHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiQuadraturaHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByIdEnteQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByPagoPAQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelUploadQueryGetByIdHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelVerificaByIdEntiQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/EmailRelService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/IEmailRelService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/CsvMapper.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ExcelExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/HeaderAttribute.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ReflectionExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/Style.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/TypeFinder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/DocumentBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/IDocumentBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/DatiGeneraliDocumentoDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FatturaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureAccontoExcelDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureCommessaExcelDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureExcel.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureListaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureRelExcelDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/PosizioniDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/TitoloFatturaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureAccontoExcelQuery.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureCommessaExcelQuery.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureQueryRicerca.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureRelExcelQuery.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureAccontoFatturaExcelBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureModuloCommessaExcelBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureQueryRicercaBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureRelExcelBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelBuilderPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureModuloCommessaExcelBuilderPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureNotaNoRelExcelBuilderPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureQueryRicercaPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureRelExcelBuilderPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureUnionRelExcelBuilderPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureAccontoFatturaExcelHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureModuloCommessaExcelHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureQueryRicercaHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureRelExcelHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/DisplayNameRole.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/Extensions/IdentityExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityUsersService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/JwtTokenService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/ProfileService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/JsonTypeHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateConsolidatoreCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdatePagoPaCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateRecapitistaCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateConsolidatoreCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdatePagoPACommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateRecapitistaCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateConsolidatoreCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdatePagoPACommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateRecapitistaCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/NotificaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/QueryDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/RECCONNotificaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/SimpleNotificaDto.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/AzioneContestazioneQueryGetByIdNotifica.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/ContestazioneQueryGetByIdNotifica.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByConsolidatore.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByIdEnte.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByListaEnti.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByRecapitista.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/ContestazioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/NotificaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/ContestazioneQueryGetByIdNotificaPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByConsolidatorePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdEntePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByListEntiPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByRecapitistaPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/AzioneContestazioneQueryGetByIdNotificaHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/ContestazioneQueryGetByIdNotificaHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByConsolidatoreHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdEnteHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdHandlandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByListEntiHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByRecapitistaHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DapperBase.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContext.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContextFactory.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/ICommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDatabase.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContext.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContextFactory.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IQuery.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/IFattureDbContextFactory.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/ISelfCareDbContextFactory.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/SqlExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/IScadenziarioService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGet.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/Builder/CalendarioContestazioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/ScadenziarioQueryGetByTipo.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneAllQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/ScadenziarioQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/ScadenziarioService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/ContrattoQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/EnteQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/ContrattoSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/EnteSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/ContrattoQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/EnteQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/ContrattoQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/EnteQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/Persistence/StoricoCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/StoricoCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByDescrizione.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRagioneSociale.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRecapitistiConsolidatori.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/FlagContestazioneQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/CategoriaSpedizioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/EnteSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/FlagContestazioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProdottoSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProfiloSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/StatoCommessaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoCommessaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContestazioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContrattoSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoFatturaSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoSpedizioneSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByDescrizionePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRagioneSocialePersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRecapitistiConsolidatoriPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/FlagContestazioneQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProdottoQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProfiloQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/SpedizioneQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/StatoCommessaQueryGetByDefaultPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoCommessaQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContestazioneQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContrattoQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoFatturaQueryGetAllPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProdottoQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProfiloQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/SpedizioneQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/StatoCommessaQueryGetByDefault.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoCommessaQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContestazioneGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContrattoQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoFatturaQueryGetAll.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EnteQueryGetByRecapitistiConsolidatoriHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByDescrizioneHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByRagioneSocialeHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/FlagContestazioneQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProdottoQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProfiloQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/SpedizioneQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/StatoCommessaQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoCommessaQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContestazioneQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContrattoQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoFatturaQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/CommandHandlers/UtenteCreateCommandHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/Persistence/UtenteCreateCommandPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/UtenteCreateCommand.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/Builder/UtenteSQLBuilder.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/UtenteQueryGetByIdPersistence.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/UtenteQueryGetById.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/QueryHandlers/UtenteQueryHandler.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/ConfigurationExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/AesEncryption.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateContainer.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateKey.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/EmailSender.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/IEmailSender.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IAesEncryption.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IMicrosoftGraphHttpClient.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPAHttpClient.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPATokenService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareHttpClient.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareTokenService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphGroups.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphHttpClient.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPAHttpClient.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPATokenService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareHttpClient.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareTokenService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/IRelStorageService.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/RelStorage.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/StorageExtensions.cs create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/PortaleFatture.BE.Infrastructure.csproj create mode 100644 src/Infrastructure/PortaleFatture.BE.Infrastructure/RootInfrastructure.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Dockerfile create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Culture/CultureConfiguration.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DisposableFileStreamResult.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DocsExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/PRIMO_SALDO_rel.html create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/SECONDO_SALDO_rel.html create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/daticommessa.html create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/IModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/IRegistrableModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/MapAttribute.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/Module.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleManager.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Infrastructure/NonceMultiTabsMiddleware.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Extensions/AsseverazioneExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Payload/Response/AsseverazionExportResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/AuthExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/NonceDto.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Payload/PagoPaLoginRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Extensions/DatiConfigurazioneModuloCommessaExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Request/DatiConfigurazioneModuloCommessaCreateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Response/DatiConfigurazioneModuloCommessaResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Extensions/DatiFatturazioneExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneContattoCreateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneCreateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPACreateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPAUpdateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneUpdateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DocumentDto.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/CategoriaSpedizioneResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaContattoResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/ProdottoResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoCommessaResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoContrattoResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoSpedizioneResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Extensions/DatiModuloCommessaViewModelExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/DatiModuloCommessaCreateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/EnteRicercaModuloCommessaByDescrizioneRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaByAnnoResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaParzialiTotaleResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Extensions/RelExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelFatturabileByIdEntiRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelRigheByIdRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataByIdRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequestPagoPA.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaPagoPARequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelUploadByIdRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Extensions/FattureExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/FatturaRicercaRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/TipologiaFattureRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneConsolidatori.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneCreateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazionePagoPAUpdateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneRecapitisti.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneUpdateRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequestPagoPA.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Response/ContestazioneResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Extensions/TipologieExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneProfiloRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByRecapitistiConsolidatoriRequest.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/CalendarioContestazioniResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/EnteResponse.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieEndpoints.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieExtensions.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieModule.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/PortaleFatture.BE.Api.csproj create mode 100644 src/Presentation/PortaleFatture.BE.Api/Program.cs create mode 100644 src/Presentation/PortaleFatture.BE.Api/appsettings.Development.json create mode 100644 src/Presentation/PortaleFatture.BE.Api/appsettings.json create mode 100644 src/Presentation/PortaleFatture.BE.Api/libman.json create mode 100644 src/Presentation/PortaleFatture.BE.EmailSender/Infrastructure/Documenti/primo_saldo.html create mode 100644 src/Presentation/PortaleFatture.BE.EmailSender/Models/Configurazione.cs create mode 100644 src/Presentation/PortaleFatture.BE.EmailSender/Models/Risposta.cs create mode 100644 src/Presentation/PortaleFatture.BE.EmailSender/PortaleFatture.BE.EmailSender.csproj create mode 100644 src/Presentation/PortaleFatture.BE.EmailSender/Program.cs create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/.gitignore create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/Infrastructure/Documenti/primo_saldo.html create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Configurazione.cs create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Risposta.cs create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/PortaleFatture_BE_SendEmailFunction.csproj create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/Program.cs create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/SendEmail.cs create mode 100644 src/Presentation/PortaleFatture.BE.SendEmailFunction/host.json create mode 100644 tests/.env create mode 100644 tests/Data/Dockerfile create mode 100644 tests/Data/entrypoint.sh create mode 100644 tests/Data/setup.sql create mode 100644 tests/PortaleFatture.BE.IntegrationTest/GlobalUsings.cs create mode 100644 tests/PortaleFatture.BE.IntegrationTest/PortaleFatture.BE.IntegrationTest.csproj create mode 100644 tests/PortaleFatture.BE.IntegrationTest/SelfCareHttpClientTests.cs create mode 100644 tests/PortaleFatture.BE.IntegrationTest/SelfCareTokenServiceTests.cs create mode 100644 tests/PortaleFatture.BE.IntegrationTest/ServiceProvider.cs create mode 100644 tests/PortaleFatture.BE.IntegrationTest/appsettings.Development.json create mode 100644 tests/PortaleFatture.BE.IntegrationTest/appsettings.json create mode 100644 tests/PortaleFatture.BE.UnitTest/Common/CommonFactory.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/Common/TestExtensions.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/DatiConfigurazioneModuloCommessaCreateCommandTests.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/DatiFatturazioneCreateCommandTests.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/DatiFatturazioneGetByIdQueryTests.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/DatiFatturazioneUpdateCommandTests .cs create mode 100644 tests/PortaleFatture.BE.UnitTest/DatiModuloCommessaCreateTests.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/GlobalUsings.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/PortaleFatture.BE.UnitTest.csproj create mode 100644 tests/PortaleFatture.BE.UnitTest/ServiceProvider.cs create mode 100644 tests/PortaleFatture.BE.UnitTest/appsettings.Development.json create mode 100644 tests/PortaleFatture.BE.UnitTest/appsettings.json create mode 100644 tests/docker-compose.yml diff --git a/.devops/sync-github.yml b/.devops/sync-github.yml new file mode 100644 index 0000000..d5fdd72 --- /dev/null +++ b/.devops/sync-github.yml @@ -0,0 +1,19 @@ +# Automatically sync main branch to GitHub on tag + +trigger: + tags: + include: + - '*' + +pool: + vmImage: 'ubuntu-22.04' + +steps: + - checkout: self + fetchTags: true + + - script: | + git remote add github 'https://$(GITHUB_PAT)@$(GITHUB_URL)' + git push github main + git push github $(Build.SourceBranchName) + displayName: 'Sync repository with GitHub' diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..81af4ce --- /dev/null +++ b/.editorconfig @@ -0,0 +1,65 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Don't use tabs for indentation. +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +[*.cs] +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style +dotnet_naming_symbols.instance_fields.applicable_kinds = field +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# IDE0055: Fix formatting +dotnet_diagnostic.IDE0055.severity = none + +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false +dotnet_organize_imports = true + +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:refactoring +dotnet_style_qualification_for_property = false:refactoring +dotnet_style_qualification_for_method = false:refactoring +dotnet_style_qualification_for_event = false:refactoring + +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Suggest more modern language features when available +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# CA1822: Make member static +dotnet_diagnostic.CA1822.severity = none + +# IDE0058: Remove unnecessary expression value +dotnet_diagnostic.IDE0058.severity = none + +# IDE0059: Unnecessary assignment to a value +dotnet_diagnostic.IDE0059.severity = error + +# IDE0035: Remove unreachable code +dotnet_diagnostic.IDE0035.severity = error + +# IDE0043: Format string contains invalid placeholder +dotnet_diagnostic.IDE0043.severity = error + +dotnet_code_quality.enable_platform_analyzer_on_pre_net5_target = true + +# Omnisharp's formatter breaks with unix-style endings +[*.razor] +end_of_line = crlf \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d5030a5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Auto detect text files and perform LF normalization +* text=auto eol=lf + +*.cs text diff=csharp +*.cshtml text diff=html +*.csx text diff=csharp +*.sln text merge=union +*.csproj text merge=union +*.sh text diff=bash +*.env text +*ockerfile text \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..195f551 --- /dev/null +++ b/.gitignore @@ -0,0 +1,534 @@ +# Created by https://www.toptal.com/developers/gitignore/api/windows,macos,visualstudio,visualstudiocode,rider +# Edit at https://www.toptal.com/developers/gitignore?templates=windows,macos,visualstudio,visualstudiocode,rider + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Rider ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# Jetbrains Rider stuff +.idea/ + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +*.code-workspace + +# Local History for Visual Studio Code + +# Windows Installer files from build outputs + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/windows,macos,visualstudio,visualstudiocode,rider +/secrets/ +src/Presentation/PortaleFatture.BE.Api/Properties +.vscode +src/Presentation/PortaleFatture.BE.SendEmailFunction/Properties +src/Presentation/PortaleFatture.BE.SendEmailFunction/PortaleFatture.BE.SendEmailFunction.sln +src/Presentation/PortaleFatture.BE.EmailSender/Infrastructure/Documenti/enti.csv diff --git a/PortaleFatture.BE.Api.sln b/PortaleFatture.BE.Api.sln new file mode 100644 index 0000000..ebb3997 --- /dev/null +++ b/PortaleFatture.BE.Api.sln @@ -0,0 +1,89 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34202.233 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortaleFatture.BE.Api", "src\Presentation\PortaleFatture.BE.Api\PortaleFatture.BE.Api.csproj", "{C8CE530F-EBE0-4DD3-9B86-F8933954EAD0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{8FB8E64F-3732-4F00-BD01-D273BDFE6D89}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{1AA0FDE8-4058-470D-AB8B-2B87751ADB51}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{FCE0D4DD-5884-4A2A-814E-F58B18092F76}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{87AF21A4-2A47-446B-BFE7-579089AB73A3}" + ProjectSection(SolutionItems) = preProject + tests\docker-compose.yml = tests\docker-compose.yml + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortaleFatture.BE.Core", "src\Core\PortaleFatture.BE.Core\PortaleFatture.BE.Core.csproj", "{AE0C591F-F9CA-49C3-874A-2B8B5025E312}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortaleFatture.BE.Infrastructure", "src\Infrastructure\PortaleFatture.BE.Infrastructure\PortaleFatture.BE.Infrastructure.csproj", "{46103B4A-ACCD-4B3B-993A-0610A695A41E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortaleFatture.BE.UnitTest", "tests\PortaleFatture.BE.UnitTest\PortaleFatture.BE.UnitTest.csproj", "{73668C16-F9F9-42EB-9C7C-B7A92E63FA60}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortaleFatture.BE.IntegrationTest", "tests\PortaleFatture.BE.IntegrationTest\PortaleFatture.BE.IntegrationTest.csproj", "{492D9219-1B59-4E5D-B8BE-6BD302DEBC53}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{CE716F1B-83D8-416D-B757-3BFAC2031AE8}" + ProjectSection(SolutionItems) = preProject + tests\Data\Dockerfile = tests\Data\Dockerfile + tests\Data\entrypoint.sh = tests\Data\entrypoint.sh + tests\Data\setup.sql = tests\Data\setup.sql + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortaleFatture_BE_SendEmailFunction", "src\Presentation\PortaleFatture.BE.SendEmailFunction\PortaleFatture_BE_SendEmailFunction.csproj", "{C57A92B5-0A9B-43EB-807F-D35F46977F65}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortaleFatture.BE.EmailSender", "src\Presentation\PortaleFatture.BE.EmailSender\PortaleFatture.BE.EmailSender.csproj", "{8D455F55-BD96-4385-AA34-0F7EEFCFC106}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C8CE530F-EBE0-4DD3-9B86-F8933954EAD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8CE530F-EBE0-4DD3-9B86-F8933954EAD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8CE530F-EBE0-4DD3-9B86-F8933954EAD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8CE530F-EBE0-4DD3-9B86-F8933954EAD0}.Release|Any CPU.Build.0 = Release|Any CPU + {AE0C591F-F9CA-49C3-874A-2B8B5025E312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE0C591F-F9CA-49C3-874A-2B8B5025E312}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE0C591F-F9CA-49C3-874A-2B8B5025E312}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE0C591F-F9CA-49C3-874A-2B8B5025E312}.Release|Any CPU.Build.0 = Release|Any CPU + {46103B4A-ACCD-4B3B-993A-0610A695A41E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46103B4A-ACCD-4B3B-993A-0610A695A41E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46103B4A-ACCD-4B3B-993A-0610A695A41E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46103B4A-ACCD-4B3B-993A-0610A695A41E}.Release|Any CPU.Build.0 = Release|Any CPU + {73668C16-F9F9-42EB-9C7C-B7A92E63FA60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73668C16-F9F9-42EB-9C7C-B7A92E63FA60}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73668C16-F9F9-42EB-9C7C-B7A92E63FA60}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73668C16-F9F9-42EB-9C7C-B7A92E63FA60}.Release|Any CPU.Build.0 = Release|Any CPU + {492D9219-1B59-4E5D-B8BE-6BD302DEBC53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {492D9219-1B59-4E5D-B8BE-6BD302DEBC53}.Debug|Any CPU.Build.0 = Debug|Any CPU + {492D9219-1B59-4E5D-B8BE-6BD302DEBC53}.Release|Any CPU.ActiveCfg = Release|Any CPU + {492D9219-1B59-4E5D-B8BE-6BD302DEBC53}.Release|Any CPU.Build.0 = Release|Any CPU + {C57A92B5-0A9B-43EB-807F-D35F46977F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C57A92B5-0A9B-43EB-807F-D35F46977F65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C57A92B5-0A9B-43EB-807F-D35F46977F65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C57A92B5-0A9B-43EB-807F-D35F46977F65}.Release|Any CPU.Build.0 = Release|Any CPU + {8D455F55-BD96-4385-AA34-0F7EEFCFC106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D455F55-BD96-4385-AA34-0F7EEFCFC106}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D455F55-BD96-4385-AA34-0F7EEFCFC106}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D455F55-BD96-4385-AA34-0F7EEFCFC106}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C8CE530F-EBE0-4DD3-9B86-F8933954EAD0} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76} + {AE0C591F-F9CA-49C3-874A-2B8B5025E312} = {8FB8E64F-3732-4F00-BD01-D273BDFE6D89} + {46103B4A-ACCD-4B3B-993A-0610A695A41E} = {1AA0FDE8-4058-470D-AB8B-2B87751ADB51} + {73668C16-F9F9-42EB-9C7C-B7A92E63FA60} = {87AF21A4-2A47-446B-BFE7-579089AB73A3} + {492D9219-1B59-4E5D-B8BE-6BD302DEBC53} = {87AF21A4-2A47-446B-BFE7-579089AB73A3} + {CE716F1B-83D8-416D-B757-3BFAC2031AE8} = {87AF21A4-2A47-446B-BFE7-579089AB73A3} + {C57A92B5-0A9B-43EB-807F-D35F46977F65} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76} + {8D455F55-BD96-4385-AA34-0F7EEFCFC106} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E21864C8-BAF8-4D8B-957E-726DB3040371} + EndGlobalSection +EndGlobal diff --git a/src/Core/PortaleFatture.BE.Core/Auth/AuthType.cs b/src/Core/PortaleFatture.BE.Core/Auth/AuthType.cs new file mode 100644 index 0000000..8db4f3d --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/AuthType.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Core.Auth; + +public static class AuthType +{ + public const string SELFCARE = "SELFCARE"; + public const string PAGOPA = "PAGOPA"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/AuthenticationInfo.cs b/src/Core/PortaleFatture.BE.Core/Auth/AuthenticationInfo.cs new file mode 100644 index 0000000..6378334 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/AuthenticationInfo.cs @@ -0,0 +1,16 @@ +namespace PortaleFatture.BE.Core.Auth; + +public class AuthenticationInfo : IAuthenticationInfo +{ + public string? Id { get; set; } + public long? IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public string? IdEnte { get; set; } + public string? NomeEnte { get; set; } + public string? Profilo { get; set; } + public string? Email { get; set; } + public string? Ruolo { get; set; } + public string? GruppoRuolo { get; set; } + public string? DescrizioneRuolo { get; set; } + public string? Auth { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/CustomClaim.cs b/src/Core/PortaleFatture.BE.Core/Auth/CustomClaim.cs new file mode 100644 index 0000000..769bfb2 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/CustomClaim.cs @@ -0,0 +1,22 @@ +namespace PortaleFatture.BE.Core.Auth; + +public static class CustomClaim +{ + // SelfCare + public static string DescrizioneRuolo = "descrizioneRuolo"; + public static string Profilo = "profilo"; + public static string Prodotto = "prodotto"; + public static string IdEnte = "idEnte"; + public static string NomeEnte = "nomeEnte"; + public static string Email = "email"; + public static string IdTipoContratto = "idTipoContratto"; + public static string Uid = "uid"; + public static string Organization = "organization"; + public static string GruppoRuolo = "gruppoRuolo"; + public static string Auth = "auth"; + // pagoPA + public static string PreferredUsername = "preferred_username"; + public static string Oid = "http://schemas.microsoft.com/identity/claims/objectidentifier"; + public static string Name = "name"; + public static string Roles = "roles"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/IAuthenticationInfo.cs b/src/Core/PortaleFatture.BE.Core/Auth/IAuthenticationInfo.cs new file mode 100644 index 0000000..fa124ea --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/IAuthenticationInfo.cs @@ -0,0 +1,16 @@ +namespace PortaleFatture.BE.Core.Auth; + +public interface IAuthenticationInfo +{ + public string? Id { get; set; } + public long? IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public string? IdEnte { get; set; } + public string? NomeEnte { get; set; } + public string? Profilo { get; set; } + public string? Email { get; set; } + public string? Ruolo { get; set; } + public string? GruppoRuolo { get; set; } + public string? DescrizioneRuolo { get; set; } + public string? Auth { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/IIdentityUsersService.cs b/src/Core/PortaleFatture.BE.Core/Auth/IIdentityUsersService.cs new file mode 100644 index 0000000..631247f --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/IIdentityUsersService.cs @@ -0,0 +1,12 @@ +using System.Security.Claims; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity +{ + public interface IIdentityUsersService + { + List> GetListUserClaimsFromUserAsync(List? authInfos); + IList GetUserClaimsFromSelfCareUserAsync(AuthenticationInfo? authInfo); + IList GetUserClaimsFromPagoPAUserAsync(AuthenticationInfo? authInfo); + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/IProfileService.cs b/src/Core/PortaleFatture.BE.Core/Auth/IProfileService.cs new file mode 100644 index 0000000..c830e40 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/IProfileService.cs @@ -0,0 +1,9 @@ +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity; + +public interface IProfileService +{ + Task?> GetSelfCareInfo(string? selfcareToken); + Task GetPagoPAInfo(string? pagoPAIdToken, string? azureADAccessToken); +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/ITokenService.cs b/src/Core/PortaleFatture.BE.Core/Auth/ITokenService.cs new file mode 100644 index 0000000..1402494 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/ITokenService.cs @@ -0,0 +1,8 @@ +using System.Security.Claims; + +namespace PortaleFatture.BE.Core.Auth; + +public interface ITokenService +{ + ProfileInfo GenerateJwtToken(IList authClaims); +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/JwtConfiguration.cs b/src/Core/PortaleFatture.BE.Core/Auth/JwtConfiguration.cs new file mode 100644 index 0000000..6c09e8a --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/JwtConfiguration.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Core.Auth; + +public record JwtConfiguration +{ + public string? ValidIssuer { get; set; } + public string? ValidAudience { get; set; } + public string? Secret { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/PagoPA/GroupRoles.cs b/src/Core/PortaleFatture.BE.Core/Auth/PagoPA/GroupRoles.cs new file mode 100644 index 0000000..d7d825c --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/PagoPA/GroupRoles.cs @@ -0,0 +1,20 @@ +namespace PortaleFatture.BE.Core.Auth.PagoPA; + +public class GroupRoles +{ + public const string APPROVIGIONAMENTO = "procurement"; + public const string FINANZA = "finance"; + public const string ASSISTENZA = "assistenza"; + public const string PORTALE = "portalefatturazione-app"; + + public static Dictionary GetRoles(string prefix) + { + return new Dictionary() + { + { $"{prefix}{APPROVIGIONAMENTO}", false }, + { $"{prefix}{FINANZA}", false }, + { $"{prefix}{ASSISTENZA}", false }, + { $"{prefix}{PORTALE}", true } + }; + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/PagoPA/PagoPADto.cs b/src/Core/PortaleFatture.BE.Core/Auth/PagoPA/PagoPADto.cs new file mode 100644 index 0000000..3b160d6 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/PagoPA/PagoPADto.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Core.Auth.PagoPA; + +public class PagoPADto +{ + [JsonPropertyName("email")] + public string? Email { get; set; } + + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("uid")] + public string? Uid { get; set; } + + [JsonPropertyName("roles")] + public IEnumerable? Roles { get; set; } + + [JsonPropertyName("groups")] + public IEnumerable? Groups { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/Product.cs b/src/Core/PortaleFatture.BE.Core/Auth/Product.cs new file mode 100644 index 0000000..a1e69be --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/Product.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Core.Auth; + +public static class Product +{ + public static string ProdPN = "prod-pn"; + public static string ProdSendino = "prod-sendino"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/ProfileInfo.cs b/src/Core/PortaleFatture.BE.Core/Auth/ProfileInfo.cs new file mode 100644 index 0000000..ba2cd74 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/ProfileInfo.cs @@ -0,0 +1,19 @@ +namespace PortaleFatture.BE.Core.Auth; + +public record ProfileInfo +{ + public long? IdTipoContratto { get; set; } //nullable + public string? Prodotto { get; set; } + public string? IdEnte { get; set; } + public string? Profilo { get; set; } + public string? Email { get; set; } + public string? Ruolo { get; set; } + public string? DescrizioneRuolo { get; set; } + public string? GruppoRuolo { get; set; } + public string? NomeEnte { get; set; } + public string? Id { get; set; } + public string? Nonce { get; set; } + public DateTime? Valido { get; set; } + public string? JWT { get; set; } + public string? Auth { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/Profilo.cs b/src/Core/PortaleFatture.BE.Core/Auth/Profilo.cs new file mode 100644 index 0000000..877d467 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/Profilo.cs @@ -0,0 +1,20 @@ +namespace PortaleFatture.BE.Core.Auth; + +public static class Profilo +{ + //selfcare + public static string Recapitista = "REC"; + public static string Consolidatore = "CON"; + + public static string PubblicaAmministrazione = "PA"; + public static string GestorePubblicoServizio = "GSP"; + public static string SocietaControlloPubblico = "SCP"; + public static string PrestatoreServiziPagamento = "PSP"; + public static string AssicurazioniIVASS = "AS"; + public static string StazioneAppaltanteANAC = "SA"; + public static string PartnerTecnologico = "PT"; + //pagopa + public static string Approvigionamento = "PRO"; + public static string Finanza = "FIN"; + public static string Assistenza = "SUP"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/Ruolo.cs b/src/Core/PortaleFatture.BE.Core/Auth/Ruolo.cs new file mode 100644 index 0000000..2c2d958 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/Ruolo.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PortaleFatture.BE.Core.Auth; + +public static class Ruolo +{ + public const string MANAGER = ADMIN; + public const string DELEGATE = ADMIN; + public const string SUB_DELEGATE = ADMIN; + public const string ADMIN = "R/W"; + public const string OPERATOR = "R"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareDto.cs b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareDto.cs new file mode 100644 index 0000000..5a79914 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareDto.cs @@ -0,0 +1,50 @@ +using System.Text.Json.Serialization; +namespace PortaleFatture.BE.Core.Auth.SelfCare; + +public class SelfCareDto +{ + [JsonPropertyName("email")] + public string? Email { get; set; } + + [JsonPropertyName("family_name")] + public string? FamilyName { get; set; } + + [JsonPropertyName("fiscal_number")] + public string? FiscalNumber { get; set; } + + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("spid_level")] + public string? SpidLevel { get; set; } + + [JsonPropertyName("from_aa")] + public bool FromAA { get; set; } + + [JsonPropertyName("uid")] + public string? Uid { get; set; } + + [JsonPropertyName("level")] + public string? Level { get; set; } + + [JsonPropertyName("iat")] + public int Iat { get; set; } + + [JsonPropertyName("exp")] + public int Exp { get; set; } + + [JsonPropertyName("aud")] + public string? Aud { get; set; } + + [JsonPropertyName("iss")] + public string? Iss { get; set; } + + [JsonPropertyName("iss")] + public string? Jti { get; set; } + + [JsonPropertyName("organization")] + public SelfCareOrganizationDto? Organization { get; set; } + + [JsonPropertyName("desired_exp")] + public int DesiredExp { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareHeader.cs b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareHeader.cs new file mode 100644 index 0000000..60528e1 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareHeader.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Core.Auth.SelfCare; + +public class SelfCareHeader +{ + [JsonPropertyName("kid")] + public string? Kid { get; set; } + + [JsonPropertyName("typ")] + public string? Typ { get; set; } + + [JsonPropertyName("alg")] + public string? Alg { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareOrganizationDto.cs b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareOrganizationDto.cs new file mode 100644 index 0000000..48de521 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareOrganizationDto.cs @@ -0,0 +1,24 @@ +using System.Data; +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Core.Auth.SelfCare; +public class SelfCareOrganizationDto +{ + [JsonPropertyName("id")] + public string? Id { get; set; } + + [JsonPropertyName("fiscal_code")] + public string? FiscalCode { get; set; } + + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("ipaCode")] + public string? IpaCode { get; set; } + + [JsonPropertyName("roles")] + public List? Roles { get; set; } + + [JsonPropertyName("groups")] + public List? Groups { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareRoleDto.cs b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareRoleDto.cs new file mode 100644 index 0000000..3edab52 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/SelfCare/SelfCareRoleDto.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Core.Auth.SelfCare; + +public class SelfCareRoleDto +{ + [JsonPropertyName("partyRole")] + public string? PartyRole { get; set; } + + [JsonPropertyName("role")] + public string? Role { get; set; } + + [JsonPropertyName("productId")] + public string? Product { get; set; } +} diff --git a/src/Core/PortaleFatture.BE.Core/Auth/UtenteInfo.cs b/src/Core/PortaleFatture.BE.Core/Auth/UtenteInfo.cs new file mode 100644 index 0000000..9f94127 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Auth/UtenteInfo.cs @@ -0,0 +1,19 @@ +namespace PortaleFatture.BE.Core.Auth; + +public class UtenteInfo +{ + public string? Id { get; set; } + public long? IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public string? IdEnte { get; set; } + public string? NomeEnte { get; set; } + public string? Profilo { get; set; } + public string? Email { get; set; } + public string? Ruolo { get; set; } + public string? DescrizioneRuolo { get; set; } + public DateTime DataPrimo { get; set; } + public DateTime DataUltimo { get; set; } + public string? Nonce { get; set; } + public string? GruppoRuolo { get; set; } + public string? Auth { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Common/AsyncHelper.cs b/src/Core/PortaleFatture.BE.Core/Common/AsyncHelper.cs new file mode 100644 index 0000000..8db3cba --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Common/AsyncHelper.cs @@ -0,0 +1,26 @@ + namespace PortaleFatture.BE.Core.Common; +public static class AsyncHelper +{ + private static readonly TaskFactory _myTaskFactory = new(CancellationToken.None, + TaskCreationOptions.None, + TaskContinuationOptions.None, + TaskScheduler.Default); + + public static TResult RunSync(Func> func) + { + return AsyncHelper._myTaskFactory + .StartNew>(func) + .Unwrap() + .GetAwaiter() + .GetResult(); + } + + public static void RunSync(Func func) + { + AsyncHelper._myTaskFactory + .StartNew(func) + .Unwrap() + .GetAwaiter() + .GetResult(); + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Common/IPortaleFattureOptions.cs b/src/Core/PortaleFatture.BE.Core/Common/IPortaleFattureOptions.cs new file mode 100644 index 0000000..a8455ad --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Common/IPortaleFattureOptions.cs @@ -0,0 +1,19 @@ +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Core.Common; +public interface IPortaleFattureOptions +{ + public string? ConnectionString { get; set; } + public string? SelfCareCertEndpoint { get; set; } + public string? SelfCareUri { get; set; } + public string? SelfCareTimeOut { get; set; } + public string? FattureSchema { get; set; } + public string? SelfCareSchema { get; set; } + public string? Vault { get; set; } + public JwtConfiguration? JWT { get; set; } + public string? CORSOrigins { get; set; } + public string? AdminKey { get; set; } + public string? SelfCareAudience { get; set; } + public AzureAd? AzureAd { get; set; } + public Storage? Storage { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Common/PortaleFattureOptions.cs b/src/Core/PortaleFatture.BE.Core/Common/PortaleFattureOptions.cs new file mode 100644 index 0000000..269a0b7 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Common/PortaleFattureOptions.cs @@ -0,0 +1,35 @@ +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Core.Common; + +public sealed class PortaleFattureOptions : IPortaleFattureOptions +{ + public string? ConnectionString { get; set; } + public string? SelfCareCertEndpoint { get; set; } + public string? SelfCareUri { get; set; } + public string? SelfCareTimeOut { get; set; } + public string? FattureSchema { get; set; } + public string? SelfCareSchema { get; set; } + public string? Vault { get; set; } + public JwtConfiguration? JWT { get; set; } + public string? CORSOrigins { get; set; } + public string? AdminKey { get; set; } + public string? SelfCareAudience { get; set; } + public string? ApplicationInsights { get; set; } + public AzureAd? AzureAd { get; set; } + public Storage? Storage { get; set; } +} + +public class Storage() +{ + public string? RelFolder { get; set; } + public string? ConnectionString { get; set; } +} + +public class AzureAd() +{ + public string? Instance { get; set; } + public string? TenantId { get; set; } + public string? ClientId { get; set; } + public string? AdGroup { get; set; } +} diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazione.cs new file mode 100644 index 0000000..c574d85 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazione.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +public class DatiFatturazione +{ + [Column("IdDatiFatturazione")] + public long Id { get; set; } + public string? Cup { get; set; } + public string? CodCommessa { get; set; } + public DateTime? DataDocumento { get; set; } + public bool? SplitPayment { get; set; } + + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + public string? IdDocumento { get; set; } + public string? Map { get; set; } + + [Column("FkTipoCommessa")] + public string? TipoCommessa { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + public string? Pec { get; set; } + public bool NotaLegale { get; set; } + public DateTimeOffset DataCreazione { get; set; } + public DateTimeOffset? DataModifica { get; set; } + public IEnumerable? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneContatto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneContatto.cs new file mode 100644 index 0000000..64bbecd --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneContatto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +[Table("DatiFatturazioneContatti")] +public class DatiFatturazioneContatto +{ + [Column("FkIdDatiFatturazione")] + public long IdDatiFatturazione { get; set; } + public string? Email { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneStorico.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneStorico.cs new file mode 100644 index 0000000..e87aa87 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiFatturazioni/DatiFatturazioneStorico.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +public class DatiFatturazioneStorico +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + + [Column("JsonDatiFatturazione")] + public string? DatiFatturazione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCategoriaCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCategoriaCommessa.cs new file mode 100644 index 0000000..b3a2425 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCategoriaCommessa.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +[Table("PercentualeAnticipo")] +public class DatiConfigurazioneModuloCategoriaCommessa +{ + [Column("FKIdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + + [Column("FkIdCategoriaSpedizione")] + public int IdCategoriaSpedizione { get; set; } + public int Percentuale { get; set; } + public string? Descrizione { get; set; } + public DateTime DataCreazione { get; set; } + public DateTime? DataModifica { get; set; } + public DateTime DataInizioValidita { get; set; } + public DateTime DataFineValidita { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCommessa.cs new file mode 100644 index 0000000..003a9a3 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloCommessa.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +public class DatiConfigurazioneModuloCommessa +{ + public IEnumerable? Categorie { get; set; } + public IEnumerable? Tipi { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloTipoCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloTipoCommessa.cs new file mode 100644 index 0000000..c1c4492 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiConfigurazioneModuloTipoCommessa.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +[Table("CostoNotifiche")] +public class DatiConfigurazioneModuloTipoCommessa +{ + [Column("FKIdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + + [Column("FkIdTipoSpedizione")] + public int IdTipoSpedizione { get; set; } + public decimal MediaNotificaNazionale { get; set; } + public decimal MediaNotificaInternazionale { get; set; } + public DateTime DataCreazione { get; set; } + public DateTime? DataModifica { get; set; } + public DateTime DataInizioValidita { get; set; } + public DateTime DataFineValidita { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessa.cs new file mode 100644 index 0000000..cbeac89 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessa.cs @@ -0,0 +1,39 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +public class DatiModuloCommessa +{ + public int TotaleNotifiche + { + get + { + return this.NumeroNotificheInternazionali + this.NumeroNotificheNazionali; + } + } + public int NumeroNotificheNazionali { get; set; } + public int NumeroNotificheInternazionali { get; set; } + public DateTime DataCreazione { get; set; } + public DateTime DataModifica { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + + [Column("FKIdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("FkIdTipoSpedizione")] + public int IdTipoSpedizione { get; set; } + + [Column("FkIdStato")] + public string? Stato { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + public decimal ValoreNazionali { get; set; } + public decimal PrezzoNazionali { get; set; } + public decimal ValoreInternazionali { get; set; } + public decimal PrezzoInternazionali { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaParzialiTotale.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaParzialiTotale.cs new file mode 100644 index 0000000..4e88e80 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaParzialiTotale.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +public class DatiModuloCommessaParzialiTotale +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + + [Column("FKIdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("FkIdStato")] + public string? Stato { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public decimal Totale { get; set; } + public decimal Digitale { get; set; } + public decimal AnalogicoARNazionali{ get; set; } + public decimal AnalogicoARInternazionali { get; set; } + public decimal Analogico890Nazionali { get; set; } + public bool Modifica { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaTotale.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaTotale.cs new file mode 100644 index 0000000..dadd426 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/DatiModuloCommessaTotale.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +[Table("DatiModuloCommessaTotali")] +public class DatiModuloCommessaTotale +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + + [Column("FKIdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("FkIdCategoriaSpedizione")] + public int IdCategoriaSpedizione { get; set; } + + [Column("FkIdStato")] + public string? Stato { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public decimal TotaleCategoria { get; set; } + public int PercentualeCategoria { get; set; } + public decimal Totale { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaByAnnoDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaByAnnoDto.cs new file mode 100644 index 0000000..35fb2b1 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaByAnnoDto.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + + +public class ModuloCommessaByAnnoDto +{ + public bool Modifica { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public string? IdEnte { get; set; } + public long IdTipoContratto { get; set; } + public string? Stato { get; set; } + public string? Prodotto { get; set; } + public decimal Totale { get; set; } + public DateTime DataModifica { get; set; } + public Dictionary? Totali { get; set; } +} + +public class ModuloCommessaMeseTotaleDto +{ + public decimal TotaleCategoria { get; set; } + public int IdCategoriaSpedizione { get; set; } + public string? Tipo { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDocumentoDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDocumentoDto.cs new file mode 100644 index 0000000..a4ce52f --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDocumentoDto.cs @@ -0,0 +1,68 @@ +using System.Text.Json.Serialization; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.SelfCare; +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +public class ModuloCommessaAggregateDto +{ + public Ente? Ente { get; set; } + public DatiFatturazione? DatiFatturazione { get; set; } + public IEnumerable? DatiModuloCommessa { get; set; } + public DatiConfigurazioneModuloCommessa? DatiConfigurazioneModuloCommessa { get; set; } + public ModuloCommessaByAnnoDto? DatiModuloCommessaTotale { get; set; } +} + +public class ModuloCommessaDocumentoDto +{ + // fatt + public string? Cup { get; set; } + public string? CodCommessa { get; set; } + public DateTime? DataDocumento { get; set; } + public string? SplitPayment { get; set; } + public string? IdDocumento { get; set; } + public string? Map { get; set; } + public string? TipoCommessa { get; set; } + public string? Prodotto { get; set; } + public string? Pec { get; set; } + public DateTimeOffset? DataModifica { get; set; } + public string? MeseAttivita { get; set; } + public IEnumerable? Contatti { get; set; } + //fat + + //ente + public string? Descrizione { get; set; } + public string? PartitaIva { get; set; } + public string? IndirizzoCompleto { get; set; } + //ente + + // modulo commessa + public IEnumerable? DatiModuloCommessa { get; set; } + // modulo commessa + + // modulo commessa totali + public IEnumerable? DatiModuloCommessaCosti { get; set; } + // modulo commessa totali +} + +public class DatiModuloCommessaTotaleDto +{ + public int TotaleNotifiche { get; set; } + public int NumeroNotificheNazionali { get; set; } + public int NumeroNotificheInternazionali { get; set; } + public string? Tipo { get; set; } + public int IdTipoSpedizione { get; set; } +} + +public class DatiModuloCommessaTotaleCostoDto +{ + [JsonIgnore] + public decimal Totale { get; set; } + + [JsonPropertyName("Totale")] + public string? TotaleValuta + { + get {return $"{Totale} €"; } + } + + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDto.cs new file mode 100644 index 0000000..f2a47ea --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommessaDto.cs @@ -0,0 +1,11 @@ +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +public class ModuloCommessaDto +{ + public int Anno { get; set; } + public int Mese { get; set; } + public bool Modifica { get; set; } + public DateTime DataModifica { get; set; } + public IEnumerable? DatiModuloCommessa { get; set; } + public IEnumerable? DatiModuloCommessaTotale { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommesseDateByAnnoDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommesseDateByAnnoDto.cs new file mode 100644 index 0000000..cc87e8c --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/Dto/ModuloCommesseDateByAnnoDto.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +public class ModuloCommesseDateByAnnoDto +{ + public int MeseValidita { get; set; } + public DateTime DataCreazione { get; set; } + public DateTime DataModifica { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/StatoModuloCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/StatoModuloCommessa.cs new file mode 100644 index 0000000..1f8cff7 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiModuloCommesse/StatoModuloCommessa.cs @@ -0,0 +1,10 @@ +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +public class StatoModuloCommessa +{ + public const string ApertaCaricato = "Aperta/Caricato"; + public const string ApertaNonCaricato = "Aperta/Non Caricato"; + public const string ChiusaCaricato = "Chiusa/Caricato"; + public const string ChiusaStimato = "Chiusa/Stimato"; + public const string Archiviato = "Archiviato"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelAzioneDocumento.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelAzioneDocumento.cs new file mode 100644 index 0000000..737d0c3 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelAzioneDocumento.cs @@ -0,0 +1,10 @@ +using System.Reflection; + +namespace PortaleFatture.BE.Core.Entities.DatiRel.Dto; + +public class RelAzioneDocumento +{ + public static string Upload = "UP"; + public static string Download = "DOWN"; + public static string Zip = "ZIP"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelDocumentoDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelDocumentoDto.cs new file mode 100644 index 0000000..633935a --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelDocumentoDto.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + + +public class RelDocumentoDto +{ + public string? IdEnte { get; set; } + + public string? RagioneSociale { get; set; } + public DateTime? DataDocumento { get; set; } + public string? IdDocumento { get; set; } + public string? Cup { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public string? Anno { get; set; } + public string? Mese { get; set; } + public string? TotaleAnalogico { get; set; } + public string? TotaleDigitale { get; set; } + public int TotaleNotificheAnalogiche { get; set; } + public int TotaleNotificheDigitali { get; set; } + public string? Totale { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelEmail.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelEmail.cs new file mode 100644 index 0000000..9cc394f --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelEmail.cs @@ -0,0 +1,19 @@ +namespace PortaleFatture.BE.Core.Entities.DatiRel.Dto; + +public class RelEmail +{ + public string? IdEnte { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int Anno { get; set; } + public int Mese { get; set; } + public string? Pec { get; set; } + public string? RagioneSociale { get; set; } +} + +public sealed class RelEmailTracking: RelEmail +{ + public string? Messaggio { get; set; } + public string? Data { get; set; } + public byte Invio { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelTestataDettaglioDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelTestataDettaglioDto.cs new file mode 100644 index 0000000..998b9da --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/Dto/RelTestataDettaglioDto.cs @@ -0,0 +1,83 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public class RelTestataDettaglioDto +{ + public string? IdTestata + { + get + { + return + $"{IdEnte}_{IdContratto}_{TipologiaFattura!.Replace(" ", "-")}_{Anno}_{Mese}"; + } + } + + [Column("internal_organization_id")] + public string? IdEnte { get; set; } + + [Column("description")] + public string? RagioneSociale { get; set; } + + [Column("DataDocumento")] + public DateTime? DataDocumento { get; set; } + + [Column("IdDocumento")] + public string? IdDocumento { get; set; } + + [Column("Cup")] + public string? Cup { get; set; } + + [Column("contract_id")] + public string? IdContratto { get; set; } + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [Column("year")] + public string? Anno { get; set; } + + [Column("month")] + public string? Mese { get; set; } + + [Column("TotaleAnalogico")] + public decimal TotaleAnalogico { get; set; } + + [Column("TotaleDigitale")] + public decimal TotaleDigitale { get; set; } + + [Column("TotaleNotificheAnalogiche")] + public int TotaleNotificheAnalogiche { get; set; } + + [Column("TotaleNotificheDigitali")] + public int TotaleNotificheDigitali { get; set; } + + [Column("Totale")] + public decimal Totale { get; set; } + + public bool DatiFatturazione { get; set; } + + [Column("Iva")] + public decimal Iva { get; set; } + + [Column("TotaleAnalogicoIva")] + public decimal TotaleAnalogicoIva { get; set; } + + [Column("TotaleDigitaleIva")] + public decimal TotaleDigitaleIva { get; set; } + + [Column("TotaleIva")] + public decimal TotaleIva { get; set; } + + public string Firmata + { + get + { + return Caricata.MapRelTestata(); + } + } + + [Column("Caricata")] + public byte Caricata { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestata.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestata.cs new file mode 100644 index 0000000..21b43c4 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestata.cs @@ -0,0 +1,59 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public class RelTestata +{ + public string? IdTestata + { + get + { + return new RelTestataKey(IdEnte, IdContratto, TipologiaFattura, Anno, Mese).ToString(); + } + } + + [Column("internal_organization_id")] + public string? IdEnte { get; set; } + + [Column("description")] + public string? RagioneSociale { get; set; } + + [Column("contract_id")] + public string? IdContratto { get; set; } + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [Column("year")] + public int? Anno { get; set; } + + [Column("month")] + public int? Mese { get; set; } + + [Column("TotaleAnalogico")] + public decimal TotaleAnalogico { get; set; } + + [Column("TotaleDigitale")] + public decimal? TotaleDigitale { get; set; } + + [Column("TotaleNotificheAnalogiche")] + public int TotaleNotificheAnalogiche { get; set; } + + [Column("TotaleNotificheDigitali")] + public int TotaleNotificheDigitali { get; set; } + + [Column("Totale")] + public decimal Totale { get; set; } + + [Column("Iva")] + public decimal Iva { get; set; } + + [Column("TotaleAnalogicoIva")] + public decimal TotaleAnalogicoIva { get; set; } + + [Column("TotaleDigitaleIva")] + public decimal TotaleDigitaleIva { get; set; } + + [Column("TotaleIva")] + public decimal TotaleIva { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestataKey.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestataKey.cs new file mode 100644 index 0000000..2f0f005 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelTestataKey.cs @@ -0,0 +1,37 @@ +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public sealed class RelTestataKey(string? idEnte, string? idContratto, string? tipologiaFattura, int? anno, int? mese) +{ + public string? IdEnte { get; init; } = idEnte; + public string? IdContratto { get; init; } = idContratto; + public string? TipologiaFattura { get; init; } = tipologiaFattura; + public int? Anno { get; init; } = anno; + public int? Mese { get; init; } = mese; + + public override string ToString() + { + return $"{IdEnte}_{IdContratto}_{TipologiaFattura!.Replace(" ", "-")}_{Anno}_{Mese}"; + } + + public static RelTestataKey Deserialize(string idTestata) + { + var dati = idTestata!.Split("_"); + var anno = Convert.ToInt32(dati[3]); + var mese = Convert.ToInt32(dati[4]); + var tipologiaFattura = dati[2].Replace("-", " "); + var idContratto = dati[1]; + var idEnte = dati[0]; + return new RelTestataKey(idEnte, idContratto, tipologiaFattura, anno, mese); + } + + public static string Folder(RelTestataKey idTestata,string parentFolder) + { + return $"{parentFolder}/{idTestata.Anno}/{idTestata.Mese}"; + } + public static string FileName( + RelTestataKey idTestata, + string extension = ".pdf") + { + return $"{idTestata}{extension}"; + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelUpload.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelUpload.cs new file mode 100644 index 0000000..1ad21f2 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/RelUpload.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public class RelUpload +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + + [Column("description")] + public string? RagioneSociale { get; set; } + + [Column("contract_id")] + public string? IdContratto { get; set; } + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [Column("year")] + public int? Anno { get; set; } + + [Column("month")] + public int? Mese { get; set; } + + [Column("DataEvento")] + public DateTime? DataEvento { get; set; } + + [Column("IdUtente")] + public string? IdUtente { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/TipologiaFattura.cs b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/TipologiaFattura.cs new file mode 100644 index 0000000..24a6f9d --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/DatiRel/TipologiaFattura.cs @@ -0,0 +1,13 @@ +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public static class TipologiaFattura +{ + public const string PRIMOSALDO = "PRIMO SALDO"; + public const string SECONDOSALDO = "SECONDO SALDO"; + public const string PRIMOCONGUAGLIO = "PRIMO CONGUAGLIO"; + public const string SECONDOCONGUAGLIO = "SECONDO CONGUAGLIO"; + public const string ASSEVERAZIONE = "ASSEVERAZIONE"; + + public const string ACCONTO = "ACCONTO"; + public const string ANTICIPO = "ANTICIPO"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Fattura/FatturaExtensions.cs b/src/Core/PortaleFatture.BE.Core/Entities/Fattura/FatturaExtensions.cs new file mode 100644 index 0000000..c7c225e --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Fattura/FatturaExtensions.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Core.Entities.Fattura; + +public static class FatturaExtensions +{ + public static string ChiusaCaricato = "Chiusa/Caricato"; + public static string ChiusaStimato = "Chiusa/Stimato"; + public static string ApertaCaricato = "Aperta/Caricato"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Contestazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Contestazione.cs new file mode 100644 index 0000000..9986bc2 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Contestazione.cs @@ -0,0 +1,70 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Notifiche; + +[Table("Contestazioni")] +public class Contestazione +{ + [Column("IdContestazione")] + public int Id { get; set; } + + [Column("FkIdTipoContestazione")] + public int TipoContestazione { get; set; } + + [Column("FkIdNotifica")] + public string? IdNotifica { get; set; } + + [Column("NoteEnte")] + public string? NoteEnte { get; set; } + + [Column("NoteSend")] + public string? NoteSend { get; set; } + + [Column("NoteRecapitista")] + public string? NoteRecapitista { get; set; } + + [Column("NoteConsolidatore")] + public string? NoteConsolidatore { get; set; } + + [Column("RispostaEnte")] + public string? RispostaEnte { get; set; } + + [Column("FkIdFlagContestazione")] + public short StatoContestazione { get; set; } + + [Column("Onere")] + public string? Onere { get; set; } + + [Column("DataInserimentoEnte")] + public DateTime DataInserimentoEnte { get; set; } + + [Column("DataModificaEnte")] + public DateTime? DataModificaEnte { get; set; } + + [Column("DataInserimentoSend")] + public DateTime? DataInserimentoSend { get; set; } + + [Column("DataModificaSend")] + public DateTime? DataModificaSend { get; set; } + + [Column("DataInserimentoRecapitista")] + public DateTime? DataInserimentoRecapitista { get; set; } + + [Column("DataModificaRecapitista")] + public DateTime? DataModificaRecapitista { get; set; } + + [Column("DataInserimentoConsolidatore")] + public DateTime? DataInserimentoConsolidatore { get; set; } + + [Column("DataModificaConsolidatore")] + public DateTime? DataModificaConsolidatore { get; set; } + + [Column("DataChiusura")] + public DateTime? DataChiusura { get; set; } + + [Column("Anno")] + public int Anno { get; set; } + + [Column("Mese")] + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Dto/AzioneNotificaDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Dto/AzioneNotificaDto.cs new file mode 100644 index 0000000..353469a --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Dto/AzioneNotificaDto.cs @@ -0,0 +1,13 @@ +using PortaleFatture.BE.Core.Entities.Scadenziari; + +namespace PortaleFatture.BE.Core.Entities.Notifiche.Dto; + +public sealed class AzioneNotificaDto +{ + public bool ChiusuraPermessa { get; set; } + public bool CreazionePermessa { get; set; } + public bool RispostaPermessa { get; set; } + public Notifica? Notifica { get; set; } + public Contestazione? Contestazione { get; set; } + public CalendarioContestazione? Calendario { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/FlagContestazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/FlagContestazione.cs new file mode 100644 index 0000000..db99869 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/FlagContestazione.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Notifiche; + +public class FlagContestazione +{ + [Column("IdFlagContestazione")] + public short Id { get; set; } + + [Column("FlagContestazione")] + public string? Flag { get; set; } + + [Column("Descrizione")] + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Notifica.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Notifica.cs new file mode 100644 index 0000000..e11e6af --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/Notifica.cs @@ -0,0 +1,110 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Notifiche; +public class Notifica +{ + [Column("internal_organization_id")] + public string? IdEnte { get; set; } + + [Column("description")] + public string? RagioneSociale { get; set; } + + [Column("institutionType")] + public string? Profilo { get; set; } + + [Column("contract_id")] + public string? IdContratto { get; set; } + + [Column("tax_code")] + public string? CodiceFiscale { get; set; } + + [Column("vat_number")] + public string? PIva { get; set; } + + [Column("zip_code")] + public string? CAP { get; set; } + + [Column("foreign_state")] + public string? StatoEstero { get; set; } + + [Column("number_of_pages")] + public string? NumberOfPages { get; set; } + + [Column("g_envelope_weight")] + public string? GEnvelopeWeight { get; set; } + + [Column("cost_eurocent")] + public string? CostEuroInCentesimi { get; set; } + + [Column("timeline_category")] + public string? TimelineCategory { get; set; } + + [Column("contestazione")] + public string? Contestazione { get; set; } + + [Column("idContestazione")] + public short StatoContestazione { get; set; } + + [Column("tipoContestazione")] + public string? TipoContestazione { get; set; } + + private string? _tipoNotifica; + + [Column("paper_product_type")] + public string? TipoNotifica + { + get => _tipoNotifica.Map(); + set { _tipoNotifica = value; } + } + + [Column("event_id")] + public string? IdNotifica { get; set; } + + [Column("iun")] + public string? IUN { get; set; } + + [Column("notification_sent_at")] + public string? DataInvio { get; set; } + + [Column("event_timestamp")] + public string? Data { get; set; } + + [Column("recipient_index")] + public string? RecipientIndex { get; set; } + + [Column("recipient_type")] + public string? RecipientType { get; set; } + + [Column("recipient_id")] + public string? RecipientId { get; set; } + + [Column("year")] + public string? Anno { get; set; } + + [Column("month")] + public string? Mese { get; set; } + + [Column("daily")] + public string? AnnoMeseGiorno { get; set; } + + [Column("item_code")] + public string? ItemCode { get; set; } + + [Column("notification_request_id")] + public string? NotificationRequestId { get; set; } + + [Column("recipient_tax_id")] + public string? RecipientTaxId { get; set; } + + [Column("Fatturabile")] + public bool? Fatturata { get; set; } + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [Column("Recapitista")] + public string? Recapitista { get; set; } + + [Column("Consolidatore")] + public string? Consolidatore { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/NotificaExtensions.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/NotificaExtensions.cs new file mode 100644 index 0000000..33391ea --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/NotificaExtensions.cs @@ -0,0 +1,31 @@ +namespace PortaleFatture.BE.Core.Entities.Notifiche; + +public static class NotificaExtensions +{ + public static string? Map(this TipoNotifica? tipo) + { + return tipo switch + { + TipoNotifica.Digitali => string.Empty, + TipoNotifica.AnalogicoARNazionali => "AR", + TipoNotifica.AnalogicoARInternazionali => "RIR", + TipoNotifica.AnalogicoRSNazionali => "RS", + TipoNotifica.AnalogicoRSInternazionali => "RIS", + TipoNotifica.Analogico890 => "890", + _ => null + }; + } + + public static string? Map(this string? dbValue) + { + return dbValue switch + { + "AR" => TipoNotifica.AnalogicoARNazionali.ToString(), + "RIR" => TipoNotifica.AnalogicoARInternazionali.ToString(), + "RS" => TipoNotifica.AnalogicoRSNazionali.ToString(), + "RIS" => TipoNotifica.AnalogicoRSInternazionali.ToString(), + "890" => TipoNotifica.Analogico890.ToString(), + _ => TipoNotifica.Digitali.ToString(), + }; + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/SoggettoContestazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/SoggettoContestazione.cs new file mode 100644 index 0000000..06c8c48 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/SoggettoContestazione.cs @@ -0,0 +1,95 @@ +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Exceptions; + +namespace PortaleFatture.BE.Core.Entities.Notifiche; + +public static class SoggettiContestazione +{ + public static string OnereContestazioneAccettazionePA(string soggetto) + { + if (soggetto == Profilo.PubblicaAmministrazione) + return $"SEND_{Profilo.PubblicaAmministrazione}"; + else if (soggetto == Profilo.GestorePubblicoServizio) + return $"SEND_{Profilo.GestorePubblicoServizio}"; + else if (soggetto == Profilo.SocietaControlloPubblico) + return $"SEND_{Profilo.SocietaControlloPubblico}"; + else if (soggetto == Profilo.PrestatoreServiziPagamento) + return $"SEND_{Profilo.PrestatoreServiziPagamento}"; + else if (soggetto == Profilo.AssicurazioniIVASS) + return $"SEND_{Profilo.AssicurazioniIVASS}"; + else if (soggetto == Profilo.StazioneAppaltanteANAC) + return $"SEND_{Profilo.StazioneAppaltanteANAC}"; + else if (soggetto == Profilo.PartnerTecnologico) + return $"SEND_{Profilo.PartnerTecnologico}"; + else + throw new DomainException(""); + } + + public static string OnereContestazioneChiusuraPA(string soggetto) + { + if (soggetto == Profilo.Consolidatore) + return $"SEND_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Recapitista) + return $"SEND_{Profilo.Recapitista}"; + else if (soggetto == "SEND") + return $"SEND_SEND"; + else + throw new DomainException(""); + } + + public static string OnereContestazioneChiusuraEnte(string soggetto, string profilo) + { + if (soggetto == Profilo.Consolidatore && profilo == Profilo.PubblicaAmministrazione) + return $"{Profilo.PubblicaAmministrazione}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore && profilo == Profilo.GestorePubblicoServizio) + return $"{Profilo.GestorePubblicoServizio}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore || profilo == Profilo.SocietaControlloPubblico) + return $"{Profilo.SocietaControlloPubblico}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore || profilo == Profilo.PrestatoreServiziPagamento) + return $"{Profilo.PrestatoreServiziPagamento}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore || profilo == Profilo.AssicurazioniIVASS) + return $"{Profilo.PubblicaAmministrazione}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore || profilo == Profilo.StazioneAppaltanteANAC) + return $"{Profilo.StazioneAppaltanteANAC}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore || profilo == Profilo.StazioneAppaltanteANAC) + return $"{Profilo.StazioneAppaltanteANAC}_{Profilo.Consolidatore}"; + else if (soggetto == Profilo.Consolidatore || profilo == Profilo.PartnerTecnologico) + return $"{Profilo.PartnerTecnologico}_{Profilo.Consolidatore}"; + + else if (soggetto == Profilo.Recapitista && profilo == Profilo.PubblicaAmministrazione) + return $"{Profilo.PubblicaAmministrazione}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista && profilo == Profilo.GestorePubblicoServizio) + return $"{Profilo.GestorePubblicoServizio}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista || profilo == Profilo.SocietaControlloPubblico) + return $"{Profilo.SocietaControlloPubblico}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista || profilo == Profilo.PrestatoreServiziPagamento) + return $"{Profilo.PrestatoreServiziPagamento}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista || profilo == Profilo.AssicurazioniIVASS) + return $"{Profilo.PubblicaAmministrazione}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista || profilo == Profilo.StazioneAppaltanteANAC) + return $"{Profilo.StazioneAppaltanteANAC}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista || profilo == Profilo.StazioneAppaltanteANAC) + return $"{Profilo.StazioneAppaltanteANAC}_{Profilo.Recapitista}"; + else if (soggetto == Profilo.Recapitista || profilo == Profilo.PartnerTecnologico) + return $"{Profilo.PartnerTecnologico}_{Profilo.Recapitista}"; + + else if (soggetto == "SEND" && profilo == Profilo.PubblicaAmministrazione) + return $"{Profilo.PubblicaAmministrazione}_SEND"; + else if (soggetto == "SEND" && profilo == Profilo.GestorePubblicoServizio) + return $"{Profilo.GestorePubblicoServizio}_SEND"; + else if (soggetto == "SEND" || profilo == Profilo.SocietaControlloPubblico) + return $"{Profilo.SocietaControlloPubblico}_SEND"; + else if (soggetto == "SEND" || profilo == Profilo.PrestatoreServiziPagamento) + return $"{Profilo.PrestatoreServiziPagamento}_SEND"; + else if (soggetto == "SEND" || profilo == Profilo.AssicurazioniIVASS) + return $"{Profilo.PubblicaAmministrazione}_SEND"; + else if (soggetto == "SEND" || profilo == Profilo.StazioneAppaltanteANAC) + return $"{Profilo.StazioneAppaltanteANAC}_SEND"; + else if (soggetto == "SEND" || profilo == Profilo.StazioneAppaltanteANAC) + return $"{Profilo.StazioneAppaltanteANAC}_SEND"; + else if (soggetto == "SEND" || profilo == Profilo.PartnerTecnologico) + return $"{Profilo.PartnerTecnologico}_SEND"; + else + throw new DomainException(""); + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/StatoContestazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/StatoContestazione.cs new file mode 100644 index 0000000..508ecc6 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/StatoContestazione.cs @@ -0,0 +1,13 @@ +namespace PortaleFatture.BE.Core.Entities.Notifiche; +public enum StatoContestazione +{ + NonContestata = 1, + Annullata = 2, + ContestataEnte = 3, + RispostaSend = 4, + RispostaRecapitista = 5, + RispostaConsolidatore = 6, + RispostaEnte = 7, + Accettata = 8, + Chiusa = 9 +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoContestazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoContestazione.cs new file mode 100644 index 0000000..12bd95c --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoContestazione.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Notifiche; + +public class TipoContestazione +{ + [Column(name: "IdTipoContestazione")] + public int Id { get; set; } + + [Column(name: "TipoContestazione")] + public string? Tipo { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoNotifica.cs b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoNotifica.cs new file mode 100644 index 0000000..06d8d7d --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Notifiche/TipoNotifica.cs @@ -0,0 +1,11 @@ +namespace PortaleFatture.BE.Core.Entities.Notifiche; + +public enum TipoNotifica +{ + Digitali = 1, + AnalogicoARNazionali = 2, + AnalogicoARInternazionali = 3, + AnalogicoRSNazionali = 4, + AnalogicoRSInternazionali = 5, + Analogico890 = 6, +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/CalendarioContestazione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/CalendarioContestazione.cs new file mode 100644 index 0000000..382af01 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/CalendarioContestazione.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Scadenziari; + +[Table("ContestazioniCalendario")] +public class CalendarioContestazione +{ + [Column("DataFine")] + public DateTime DataFine { get; set; } + + [Column("DataInizio")] + public DateTime DataInizio { get; set; } + + [Column("DataVerifica")] + public DateTime DataVerifica{ get; set; } + + [Column("MeseContestazione")] + public int MeseContestazione { get; set; } + + [Column("AnnoContestazione")] + public int AnnoContestazione { get; set; } + public DateTime Adesso { get; set; } + public bool Valid { get; set; } + public bool ValidVerifica { get; set; } + public bool ValidVisualizzazione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Dto/Calendario.cs b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Dto/Calendario.cs new file mode 100644 index 0000000..133746e --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Dto/Calendario.cs @@ -0,0 +1,9 @@ +namespace PortaleFatture.BE.Core.Entities.Scadenziari.Dto; + +public class Calendario +{ + public int GiornoInizio { get; set; } + public int GiornoFine { get; set; } + public int Mese { get; set; } + public int Anno { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Scadenziario.cs b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Scadenziario.cs new file mode 100644 index 0000000..f689e32 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/Scadenziario.cs @@ -0,0 +1,11 @@ +namespace PortaleFatture.BE.Core.Entities.Scadenziari; + +public class Scadenziario +{ + public TipoScadenziario Tipo { get; set; } + public int GiornoInizio { get; set; } + public int GiornoFine { get; set; } + public int Mese { get; set; } + public int Anno { get; set; } + public DateTime Adesso { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/TipoScadenziario.cs b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/TipoScadenziario.cs new file mode 100644 index 0000000..463a0e3 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Scadenziari/TipoScadenziario.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Core.Entities.Scadenziari; + +public enum TipoScadenziario +{ + DatiModuloCommessa = 1, + DatiFatturazione = 2 +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Contratto.cs b/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Contratto.cs new file mode 100644 index 0000000..5a398fd --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Contratto.cs @@ -0,0 +1,16 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.SelfCare +{ + [Table("Contratti")] + public class Contratto + { + [Column("internalistitutionid")] + public string? IdEnte { get; set; } + [Column("product")] + public string? Prodotto { get; set; } + [Column("FkIdTipoContratto")] + public long IdTipoContratto { get; set; } + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Dto/EnteContrattoDto.cs b/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Dto/EnteContrattoDto.cs new file mode 100644 index 0000000..2571085 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Dto/EnteContrattoDto.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.SelfCare.Dto; + +public class EnteContrattoDto +{ + + [Column("IdEnte")] + public string? IdEnte { get; set; } + + [Column("RagioneSociale")] + public string? RagioneSociale { get; set; } + + [Column("TipoContratto")] + public string? TipoContratto { get; set; } + + [Column("IdContratto")] + public string? IdContratto { get; set; } +} diff --git a/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Ente.cs b/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Ente.cs new file mode 100644 index 0000000..25e935b --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/SelfCare/Ente.cs @@ -0,0 +1,48 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.SelfCare; + +[Table("Enti")] +public class Ente +{ + [Column("internalistitutionid")] + public string? IdEnte { get; set; } + + [Column("institutionType")] + public string? Profilo { get; set; } + + [Column("description")] + public string? Descrizione { get; set; } + + [Column("digitalAddress")] + public string? Email { get; set; } + + [Column("address")] + public string? Address { get; set; } + + [Column("zipCode")] + public string? Cap { get; set; } + + [Column("istatCode")] + public string? CodiceIstat { get; set; } + + [Column("city")] + public string? Citta { get; set; } + + [Column("county")] + public string? Provincia { get; set; } + + [Column("country")] + public string? Nazione { get; set; } + + [Column("vatnumber")] + public string? PartitaIva { get; set; } + + public string? IndirizzoCompleto + { + get + { + return $"{Address}, {Cap} {Citta} ({Provincia}) - {Nazione}"; + } + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Storici/Storico.cs b/src/Core/PortaleFatture.BE.Core/Entities/Storici/Storico.cs new file mode 100644 index 0000000..01cf064 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Storici/Storico.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Storici; + +public class Storico +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + public string? IdUtente { get; set; } + public DateTime DataEvento { get; set; } + public string? DescrizioneEvento { get; set; } + public string? JsonTransazione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Storici/TipoStorico.cs b/src/Core/PortaleFatture.BE.Core/Entities/Storici/TipoStorico.cs new file mode 100644 index 0000000..9b86dfb --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Storici/TipoStorico.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Core.Entities.Storici; + +public class TipoStorico +{ + public const string DatiModuloCommessa = "MC"; + public const string DatiFatturazione = "DF"; + public const string Contestazione = "CT"; +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/CategoriaSpedizione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/CategoriaSpedizione.cs new file mode 100644 index 0000000..5029d34 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/CategoriaSpedizione.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Tipologie; + +public class CategoriaSpedizione +{ + [Column("IdCategoriaSpedizione")] + public int Id { get; set; } + + public string? Descrizione { get; set; } + public string? Tipo { get; set; } + public List? TipoSpedizione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/Prodotto.cs b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/Prodotto.cs new file mode 100644 index 0000000..804e0ef --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/Prodotto.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Tipologie; + +[Table("Prodotti")] +public class Prodotto +{ + [Column("Prodotto")] + public string? Nome { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/StatoCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/StatoCommessa.cs new file mode 100644 index 0000000..31dba94 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/StatoCommessa.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Tipologie; + +[Table("Stato")] +public class StatoCommessa +{ + public string? Stato { get; set; } + public bool Default { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoCommessa.cs b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoCommessa.cs new file mode 100644 index 0000000..9a1c9ac --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoCommessa.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Tipologie; + +public sealed class TipoCommessa +{ + [Column("TipoCommessa")] + public string? Id { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoContratto.cs b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoContratto.cs new file mode 100644 index 0000000..cf601bd --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoContratto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Tipologie; + +[Table("TipoContratto")] +public sealed class TipoContratto +{ + [Column("IdTipoContratto")] + public long Id { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoSpedizione.cs b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoSpedizione.cs new file mode 100644 index 0000000..355f90e --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Tipologie/TipoSpedizione.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Tipologie; + +public class TipoSpedizione +{ + [Column("IdTipoSpedizione")] + public int Id { get; set; } + public string? Descrizione { get; set; } + + [Column("FkIdCategoriaSpedizione")] + public int IdCategoriaSpedizione { get; set; } + public string? Tipo { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Entities/Utenti/Utente.cs b/src/Core/PortaleFatture.BE.Core/Entities/Utenti/Utente.cs new file mode 100644 index 0000000..92d9eb0 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Entities/Utenti/Utente.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Core.Entities.Utenti; + +[Table("Utenti")] +public class Utente +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + public string? IdUtente { get; set; } + public DateTime DataPrimo { get; set; } + public DateTime DataUltimo { get; set; } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Exceptions/ConfigurationException.cs b/src/Core/PortaleFatture.BE.Core/Exceptions/ConfigurationException.cs new file mode 100644 index 0000000..ae2b145 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Exceptions/ConfigurationException.cs @@ -0,0 +1,16 @@ +namespace PortaleFatture.BE.Core.Exceptions; + +public class ConfigurationException : Exception +{ + public ConfigurationException() + { + } + + public ConfigurationException(string message) : base(message) + { + } + + public ConfigurationException(string message, Exception ex) : base(message, ex) + { + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Exceptions/DomainException.cs b/src/Core/PortaleFatture.BE.Core/Exceptions/DomainException.cs new file mode 100644 index 0000000..4331ded --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Exceptions/DomainException.cs @@ -0,0 +1,12 @@ +namespace PortaleFatture.BE.Core.Exceptions; + +public class DomainException : Exception +{ + public DomainException(string message) : base(message) + { + } + + public DomainException(string message, Exception ex) : base(message, ex) + { + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Exceptions/NotFoundException.cs b/src/Core/PortaleFatture.BE.Core/Exceptions/NotFoundException.cs new file mode 100644 index 0000000..90b2c92 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Exceptions/NotFoundException.cs @@ -0,0 +1,16 @@ +namespace PortaleFatture.BE.Core.Exceptions; + +public class NotFoundException : Exception +{ + public NotFoundException() + { + } + + public NotFoundException(string message) : base(message) + { + } + + public NotFoundException(string message, Exception ex) : base(message, ex) + { + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Exceptions/RoleException.cs b/src/Core/PortaleFatture.BE.Core/Exceptions/RoleException.cs new file mode 100644 index 0000000..cb09e96 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Exceptions/RoleException.cs @@ -0,0 +1,12 @@ +namespace PortaleFatture.BE.Core.Exceptions; + +public class RoleException : Exception +{ + public RoleException(string message) : base(message) + { + } + + public RoleException(string message, Exception ex) : base(message, ex) + { + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Exceptions/SessionException.cs b/src/Core/PortaleFatture.BE.Core/Exceptions/SessionException.cs new file mode 100644 index 0000000..17caa68 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Exceptions/SessionException.cs @@ -0,0 +1,16 @@ +namespace PortaleFatture.BE.Core.Exceptions; + +public class SessionException : Exception +{ + public SessionException() + { + } + + public SessionException(string message) : base(message) + { + } + + public SessionException(string message, Exception ex) : base(message, ex) + { + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Exceptions/ValidationException.cs b/src/Core/PortaleFatture.BE.Core/Exceptions/ValidationException.cs new file mode 100644 index 0000000..2986245 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Exceptions/ValidationException.cs @@ -0,0 +1,16 @@ +namespace PortaleFatture.BE.Core.Exceptions; + +public class ValidationException : Exception +{ + public ValidationException() + { + } + + public ValidationException(string message) : base(message) + { + } + + public ValidationException(string message, Exception ex) : base(message, ex) + { + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Extensions/DocumentExtensions.cs b/src/Core/PortaleFatture.BE.Core/Extensions/DocumentExtensions.cs new file mode 100644 index 0000000..b603a2e --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Extensions/DocumentExtensions.cs @@ -0,0 +1,283 @@ +using System.Globalization; +using System.Security.Cryptography; +using System.Text; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; + +namespace PortaleFatture.BE.Core.Extensions; + +public static class DocumentExtensions +{ + public static string GetHashSHA512(this byte[] document) + { + using var sha512Hash = SHA512.Create(); + var hashBytes = sha512Hash.ComputeHash(document); + return BitConverter.ToString(hashBytes).Replace("-", String.Empty); + } + + public static string MapRelTestata(this byte caricata) + { + if (caricata == 0) + return "Non Caricata"; + else if (caricata == 1) + return "Firmata"; + else if (caricata == 2) + return "Invalidata"; + else + return "Non Caricata"; + } + + private static string _tableModuloCommessa = @" + + [Tipo] + [NumeroNotificheNazionali] + [NumeroNotificheInternazionali] + [TotaleNotifiche] + + "; + + private static string _tableTotali = @" + + [Descrizione] + [Totale] € + + "; + + public static string GetModuloCommessa(this IEnumerable? commesse) + { + StringBuilder builder = new(); + List ordineCommessa = []; + ordineCommessa.Add(commesse!.Where(x => x.IdTipoSpedizione == 3).FirstOrDefault()!); + ordineCommessa.Add(commesse!.Where(x => x.IdTipoSpedizione == 1).FirstOrDefault()!); + ordineCommessa.Add(commesse!.Where(x => x.IdTipoSpedizione == 2).FirstOrDefault()!); + ordineCommessa.Add(commesse!.Where(x => x.IdTipoSpedizione == 0).FirstOrDefault()!); + + for (var i = 0; i < ordineCommessa!.Count; i++) + { + var commessa = ordineCommessa!.ToList()[i]; + var table = String.Format(_tableModuloCommessa, i == commesse!.Count() - 1 ? "ending" : "details") + .Replace(nameof(commessa.Tipo).GetName(), commessa.Tipo) + .Replace(nameof(commessa.NumeroNotificheNazionali).GetName(), commessa.NumeroNotificheNazionali.ToString()) + .Replace(nameof(commessa.NumeroNotificheInternazionali).GetName(), commessa.NumeroNotificheInternazionali.ToString()) + .Replace(nameof(commessa.TotaleNotifiche).GetName(), commessa.TotaleNotifiche.ToString()) + ; + builder.Append(table); + } + return builder.ToString(); + } + + public static string GetModuloCommessaTotali(this IEnumerable totali) + { + StringBuilder builder = new(); + + for (var i = 0; i < totali!.Count(); i++) + { + var totale = totali!.ToList()[i]; + var table = String.Format(_tableTotali, i == totali!.Count() - 1 ? "ending" : "details") + .Replace(nameof(totale.Descrizione).GetName(), totale.Descrizione) + .Replace(nameof(totale.Totale).GetName(), totale.Totale.ToString()) + ; + builder.Append(table); + } + return builder.ToString(); + } + + public static string GetContatti(this IEnumerable? contatti) + { + StringBuilder builder = new(); + foreach (var contatto in contatti!) + { + builder.Append(contatto.Email.GetEmail() + "
"); + } + return builder.ToString(); + } + + public static string GetMonth(this int month) + { + return new DateTime(1999, month, 1).ToString("MMMM", CultureInfo.CreateSpecificCulture("it-IT")).ToUpperInvariant(); + } + + public static string GetMonth(this int? month) + { + return GetMonth(month!.Value); + } + + public static string GetEmail(this string? email) + { + return $"{email}"; + } + + public static string GetData(this DateTimeOffset? data) + { + var d = data!.Value; + return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second).ToString(new CultureInfo("it-IT")); + } + + private static Dictionary _names = new(); + private static string GetName(this string propertyName) + { + _names.TryGetValue(propertyName, out var name); + if (name == null) + { + var propertyInfo = typeof(T)!.GetProperty(propertyName)!; + name = $"[{propertyInfo.Name!}]"; + _names.TryAdd(propertyName, name); + } + return name; + } + + public static string Replace(this RelDocumentoDto model, string template) + { + + template = template + .Replace(nameof(model.Anno).GetName(), model.Anno) + .Replace(nameof(model.Mese).GetName(), model.Mese) + .Replace(nameof(model.Totale).GetName(), model.Totale!.ToString().Replace(".", ".")) + .Replace(nameof(model.TotaleAnalogico).GetName(), model.TotaleAnalogico!.ToString().Replace(".", ".")) + .Replace(nameof(model.TotaleDigitale).GetName(), model.TotaleDigitale!.ToString().Replace(".", ".")) + .Replace(nameof(model.TotaleNotificheAnalogiche).GetName(), model.TotaleNotificheAnalogiche!.ToString()) + .Replace(nameof(model.TotaleNotificheDigitali).GetName(), model.TotaleNotificheDigitali!.ToString()) + .Replace(nameof(model.TipologiaFattura).GetName(), model.TipologiaFattura!) + .Replace(nameof(model.RagioneSociale).GetName(), model.RagioneSociale!) + .Replace(nameof(model.IdContratto).GetName(), model.IdContratto!) + ; + + return template; + } + + public static string Replace(this RelEmail model, string template) + { + + template = template + .Replace(nameof(model.Anno).GetName(), model.Anno.ToString()) + .Replace(nameof(model.Mese).GetName(), model.Mese.GetMonth()) + .Replace(nameof(model.IdEnte).GetName(), model.IdEnte) + .Replace(nameof(model.IdContratto).GetName(), model.IdContratto) + .Replace(nameof(model.TipologiaFattura).GetName(), model.TipologiaFattura) + .Replace(nameof(model.Pec).GetName(), model.Pec) + .Replace(nameof(model.RagioneSociale).GetName(), model.RagioneSociale) + ; + + return template; + } + + public static string Replace(this ModuloCommessaDocumentoDto model, string template) + { + + template = template + .Replace(nameof(model.Descrizione).GetName(), model.Descrizione) + .Replace(nameof(model.PartitaIva).GetName(), model.PartitaIva) + .Replace(nameof(model.IndirizzoCompleto).GetName(), model.IndirizzoCompleto) + + .Replace(nameof(model.Cup).GetName(), model.Cup) + .Replace(nameof(model.Descrizione).GetName(), model.Descrizione) + .Replace(nameof(model.CodCommessa).GetName(), model.CodCommessa) + .Replace(nameof(model.SplitPayment).GetName(), model.SplitPayment) + .Replace(nameof(model.Map).GetName(), model.Map) + .Replace(nameof(model.TipoCommessa).GetName(), model.TipoCommessa) + .Replace(nameof(model.Prodotto).GetName(), model.Prodotto) + .Replace(nameof(model.Pec).GetName(), model.Pec.GetEmail()) + .Replace(nameof(model.Contatti).GetName(), model.Contatti.GetContatti()) + .Replace(nameof(model.DataModifica).GetName(), model.DataModifica.GetData()) + .Replace(nameof(model.MeseAttivita).GetName(), model.MeseAttivita) + + .Replace(nameof(model.DatiModuloCommessa).GetName(), model.DatiModuloCommessa.GetModuloCommessa()) + + .Replace(nameof(model.DatiModuloCommessaCosti).GetName(), model.DatiModuloCommessaCosti!.GetModuloCommessaTotali()) + ; + + return template; + } + + public static ModuloCommessaDocumentoDto Mapper(this ModuloCommessaAggregateDto model) + { + var fatt = model.DatiFatturazione!; + var ente = model.Ente!; + var modulo = model.DatiModuloCommessa!; + var tipoContratto = modulo.Select(x => x.IdTipoContratto).FirstOrDefault(); + var confModulo = model.DatiConfigurazioneModuloCommessa; + var totaleModulo = model.DatiModuloCommessaTotale!; + + var tipi = confModulo!.Tipi; + var mese = model.DatiModuloCommessa!.Select(x => x.MeseValidita).FirstOrDefault().GetMonth(); + var anno = model.DatiModuloCommessa!.Select(x => x.AnnoValidita).FirstOrDefault(); + var data = $"{mese}/{anno}"; + var dataModificaCommessa = modulo.Select(x => x.DataModifica).FirstOrDefault(); + var dataCreazioneCommessa = modulo.Select(x => x.DataCreazione).FirstOrDefault(); + + var moduloDocumento = new ModuloCommessaDocumentoDto() + { + Descrizione = ente.Descrizione, + PartitaIva = ente.PartitaIva, + IndirizzoCompleto = ente.IndirizzoCompleto, + + Cup = fatt.Cup, + CodCommessa = fatt.CodCommessa, + Contatti = fatt.Contatti, + DataDocumento = fatt.DataDocumento, + DataModifica = dataModificaCommessa == DateTime.MinValue ? dataCreazioneCommessa : dataModificaCommessa, + SplitPayment = fatt.SplitPayment == true ? "SI" : "NO", + IdDocumento = fatt.IdDocumento, + Map = fatt.Map, + TipoCommessa = fatt.TipoCommessa == "1" ? "Ordine" : "Contratto", + Pec = fatt.Pec, + Prodotto = fatt.Prodotto == "prod-pn" ? "SEND" : fatt.Prodotto, + MeseAttivita = data, + DatiModuloCommessa = modulo.Select(x => new DatiModuloCommessaTotaleDto() + { + Tipo = tipi!.Where(y => y.IdTipoSpedizione == x.IdTipoSpedizione).FirstOrDefault()!.Descrizione!.Replace("[data]", data), + NumeroNotificheInternazionali = x.NumeroNotificheInternazionali, + NumeroNotificheNazionali = x.NumeroNotificheNazionali, + TotaleNotifiche = x.NumeroNotificheInternazionali + x.NumeroNotificheNazionali, + IdTipoSpedizione = x.IdTipoSpedizione + }), + DatiModuloCommessaCosti = [] + }; + + var list = moduloDocumento.DatiModuloCommessa.ToList(); + list.Add( + new DatiModuloCommessaTotaleDto() + { + NumeroNotificheInternazionali = moduloDocumento.DatiModuloCommessa.Select(x => x.NumeroNotificheInternazionali).Sum(), + NumeroNotificheNazionali = moduloDocumento.DatiModuloCommessa.Select(x => x.NumeroNotificheNazionali).Sum(), + TotaleNotifiche = moduloDocumento.DatiModuloCommessa.Select(x => x.TotaleNotifiche).Sum(), + Tipo = "Totale notifiche da processare" + }); + moduloDocumento.DatiModuloCommessa = list; + + var catDigitale = confModulo.Categorie!.Where(x => x.IdCategoriaSpedizione == 2 && x.IdTipoContratto == tipoContratto); + var catAnalogico = confModulo.Categorie!.Where(x => x.IdCategoriaSpedizione == 1 && x.IdTipoContratto == tipoContratto); + + var percentDigitale = catDigitale.Select(x => x.Percentuale).FirstOrDefault()!; + var percentAnalogico = catAnalogico.Select(x => x.Percentuale).FirstOrDefault()!; + + var digitale = catDigitale.Select(x => x.Descrizione).FirstOrDefault()!.Replace("[data]", data).Replace("[percent]", percentDigitale.ToString()); + var analogico = catAnalogico.Select(x => x.Descrizione).FirstOrDefault()!.Replace("[data]", data).Replace("[percent]", percentAnalogico.ToString()); + + totaleModulo.Totali!.TryGetValue(2, out var totaleDigitale); + totaleModulo.Totali!.TryGetValue(1, out var totaleAnalogico); + + var totali = moduloDocumento.DatiModuloCommessaCosti!.ToList(); + totali.Add( + new DatiModuloCommessaTotaleCostoDto() + { + Totale = totaleDigitale!.TotaleCategoria, + Descrizione = digitale + }); + totali.Add( + new DatiModuloCommessaTotaleCostoDto() + { + Totale = totaleAnalogico!.TotaleCategoria, + Descrizione = analogico + }); + totali.Add( + new DatiModuloCommessaTotaleCostoDto() + { + Totale = totaleModulo!.Totale, + Descrizione = "TOTALE MODULO COMMESSA NETTO IVA" + }); + moduloDocumento.DatiModuloCommessaCosti = totali; + return moduloDocumento; + } +} diff --git a/src/Core/PortaleFatture.BE.Core/Extensions/DomainExtensions.cs b/src/Core/PortaleFatture.BE.Core/Extensions/DomainExtensions.cs new file mode 100644 index 0000000..38a175a --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Extensions/DomainExtensions.cs @@ -0,0 +1,31 @@ +namespace PortaleFatture.BE.Core.Extensions; + +public static class DomainExtensions +{ + private static readonly TimeZoneInfo _italianTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time"); + public static DateTime ItalianTime(this DateTime dateUtcTime) + { + return TimeZoneInfo.ConvertTimeFromUtc(dateUtcTime, _italianTimeZone); + } + + public static (int, int) YearMonth(this DateTime dateTime) + { + return (dateTime.Year, dateTime.Month); + } +} + +public static class Time +{ + public static (int, int, int, DateTime) YearMonthDay() + { + var adesso = DateTime.UtcNow.ItalianTime(); + return (adesso.Year, adesso.Month, adesso.Day, adesso); + } + + public static (int, int, int, DateTime) YearMonthDayFatturazione() + { + var adesso = DateTime.UtcNow.ItalianTime(); + var refFatturazione = adesso.AddMonths(1); // mese riferimento fatturazione = mese attuale + 1 + return (refFatturazione.Year, refFatturazione.Month, adesso.Day, adesso); + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Extensions/SerializationExtensions.cs b/src/Core/PortaleFatture.BE.Core/Extensions/SerializationExtensions.cs new file mode 100644 index 0000000..43d333a --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Extensions/SerializationExtensions.cs @@ -0,0 +1,25 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Core.Extensions; +public static class SerializationExtensions +{ + public static readonly JsonSerializerOptions _options = new() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = false, + IncludeFields = false, + IgnoreReadOnlyProperties = true, + ReferenceHandler = ReferenceHandler.IgnoreCycles, + }; + + public static string Serialize(this T value) + { + return JsonSerializer.Serialize(value, _options); + } + + public static T Deserialize(this string json) + { + return JsonSerializer.Deserialize(json, _options)!; + } +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Extensions/ValidationExtensions.cs b/src/Core/PortaleFatture.BE.Core/Extensions/ValidationExtensions.cs new file mode 100644 index 0000000..af74afd --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Extensions/ValidationExtensions.cs @@ -0,0 +1,41 @@ +using System.Net.Mail; + +namespace PortaleFatture.BE.Core.Extensions; + +public static class ValidationExtensions +{ + public static bool IsNullNotAny(this IEnumerable enumerable) + { + return enumerable == null || !enumerable.Any(); + } + + //public static bool IsNull(this T? obj) where T : class + //{ + // return obj == null; + //} + + public static bool IsNull(this string? value) + { + return string.IsNullOrWhiteSpace(value); + } + + public static bool IsNotValidEmail(this string value) + { + if (value.IsNull()) return true; + + try + { + var email = new MailAddress(value); + return email.Address != value.Trim(); + } + catch + { + return true; + } + } + + public static bool IsNotValidGuid(this string value) + { + return !Guid.TryParse(value, out _); + } +} diff --git a/src/Core/PortaleFatture.BE.Core/PortaleFatture.BE.Core.csproj b/src/Core/PortaleFatture.BE.Core/PortaleFatture.BE.Core.csproj new file mode 100644 index 0000000..842e044 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/PortaleFatture.BE.Core.csproj @@ -0,0 +1,8 @@ + + + + net8.0 + enable + enable + + diff --git a/src/Core/PortaleFatture.BE.Core/Resources/Localization.cs b/src/Core/PortaleFatture.BE.Core/Resources/Localization.cs new file mode 100644 index 0000000..f6da42e --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Resources/Localization.cs @@ -0,0 +1,5 @@ +namespace PortaleFatture.BE.Core.Resources; + +public class Localization +{ +} \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Resources/Localization.en.resx b/src/Core/PortaleFatture.BE.Core/Resources/Localization.en.resx new file mode 100644 index 0000000..d58980a --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Resources/Localization.en.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Core/PortaleFatture.BE.Core/Resources/Localization.it.resx b/src/Core/PortaleFatture.BE.Core/Resources/Localization.it.resx new file mode 100644 index 0000000..8838992 --- /dev/null +++ b/src/Core/PortaleFatture.BE.Core/Resources/Localization.it.resx @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Esiste già una contestazione relativa alla notifica: "{0}". + + + Si è verificato un errore nel salvare la contestazione relativa alla notifica: "{0}". + + + L'operazione è consentita solo nei seguenti giorni corrente mese: "{0}". + + + Si è verificato un errore nell'inserire i dati di configurazione commessa. + + + Si è verificato un errore nella validazione dati configuazione commessa. + + + Non sono stati configurati i dati configurazione modulo commessa. + + + Il cig è obbligatorio e deve avere al massimo 10 caratteri. + + + Il codice commessa è obbligatorio e deve avere al massimo 100 caratteri. + + + La email del contatto non è valida. + + + Il numero di contatti deve essere almeno pari a uno e non superiore a tre. + + + Il cup è obbligatorio e deve avere al massimo 15 caratteri. + + + L'id ente non può essere nullo. + + + Sono stati trovati dati fatturazione duplicati per lo stesso ente id: "{0}". + + + Il flag ordine contratto è obbligatorio e deve avere al massimo 1 carattere. + + + Non ho trovato i dati fatturazione con id: "{0}". + + + Non ho trovato i dati fatturazione con id ente: "{0}". + + + L'id documento è obbligatorio e deve avere al massimo 20 caratteri. + + + Esiste già un dato fatturazione per l'ente specificato id: "{0}". + + + Non esiste un dato fatturazione per il valore specificato id: "{0}". + + + L'id tipo contratto deve essere un valore maggiore di zero. + + + Passare un valore per i dati fatturazione. + + + Si è verificato un errore nell'inserire i dati commessa. + + + Il map deve avere al massimo 100 caratteri. + + + I dati passati per l'inserimento dati fatturazione non corrispondono ai dati di autenticazione. + + + La pec fornita non è una email valida. + + + Il prodotto è obbligatorio. + + + Il tipo commessa è obbligatorio. + + + Si è verificato un errore nel modificare i dati fatturazione. + + + Il valore deve essere relativo all'anno e mese attuale. + + + L'utente PagoPA può solo modificare i dati modulo commessa, non crearli! + + + Non è stato trovato un contratto associato all'ente e al prodotto specificati. + + + Si è verificato un errore nell'inserire i dati commessa con idEnte: "{0}". + + + Il valore deve essere numerico non negativo. + + + Errore nell'inserimento valori modulo commessa. + + + Il valore dello stato non è valido. + + + Non sono stati configurati i prodotti. + + + Non sono stati configurati e inseriti i dati tipo commessa. + + + Non sono stati configurati e inseriti i dati tipo contratto. + + + Non sono stati configurati e inseriti i dati tipo profilo (institutionType) + + + Inserire un valore descrizione configurazione modulo commessa. + + + Non è stato trovato un profilo ente associato. + + + Non sono stati configurati i flag di contestazione + + + Inserire un valore per la media notifica internazionale. + + + Inserire un valore per la media notifica nazionale. + + + Non è possibile contestare la notifica, controllare lo scadenziario, validità: {0} + + + Il valore della percentuale deve essere un numero positivo. + + + Specificare un parametro di ricerca per l'ente. + + + Ruolo non abilitato per l'esecuzione dell'operazione. + + + Non sono state configurate le tipologie di contestazione + + + Si è verificato un errore nel recuperare il profilo utente. + + \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/CommandHandlers/EnteAsserverazioneImportCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/CommandHandlers/EnteAsserverazioneImportCreateCommandHandler.cs new file mode 100644 index 0000000..25e5c50 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/CommandHandlers/EnteAsserverazioneImportCreateCommandHandler.cs @@ -0,0 +1,37 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class EnteAsserverazioneImportCreateCommandHandler( + ISelfCareDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(EnteAsserverazioneListImportCreateCommand command, CancellationToken ct) + { + var authInfo = command!.AuthenticationInfo!; + + if (!(authInfo.Profilo == Profilo.Approvigionamento || + authInfo.Profilo == Profilo.Finanza || + authInfo.Profilo == Profilo.Assistenza + )) + throw new SecurityException(); //401 + + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Execute(new EnteAsserverazioneImportCreateCommandPersistence(command.ListCommands!, _localizer), ct) > 0; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/EnteAsserverazioneImportCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/EnteAsserverazioneImportCreateCommand.cs new file mode 100644 index 0000000..f919557 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/EnteAsserverazioneImportCreateCommand.cs @@ -0,0 +1,23 @@ +using DocumentFormat.OpenXml.InkML; +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; + +public class EnteAsserverazioneListImportCreateCommand(IAuthenticationInfo? authenticationInfo) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public List? ListCommands { get; set; } +} + +public class EnteAsserverazioneImportCreateCommand(DateTime timestamp) +{ + public DateTime? TimeStamp { get; internal set; } = timestamp; + public string? IdEnte { get; set; } + public string? RagioneSociale { get; set; } + public DateTime? DataAsseverazione { get; set; } + public bool? TipoAsseverazione { get; set; } + public string? IdUtente { get; set; } + public string? Descrizione { get; set; } +} + diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/Persistence/EnteAsserverazioneImportCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/Persistence/EnteAsserverazioneImportCreateCommandPersistence.cs new file mode 100644 index 0000000..dff004e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Commands/Persistence/EnteAsserverazioneImportCreateCommandPersistence.cs @@ -0,0 +1,38 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class EnteAsserverazioneImportCreateCommandPersistence(List commands, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly List _commands = commands; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlInsert= @" + INSERT INTO [pfd].[Asseverazione] + ([InternalIstitutionId] + ,[Asseverazione] + ,[Data] + ,[Timestamp] + ,[IdUtente] + ,[RagioneSociale] + ,[Descrizione]) + VALUES + (@IdEnte + ,@TipoAsseverazione + ,@DataAsseverazione + ,@TimeStamp + ,@IdUtente + ,@RagioneSociale + ,@Descrizione) +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), _commands, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneDto.cs new file mode 100644 index 0000000..e3d80e4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneDto.cs @@ -0,0 +1,95 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; + +public class EnteAsserverazioneDto +{ + [Column("internalistitutionid")] + [HeaderAttributev2(caption: "Id Ente", Order = 1)] + public string? IdEnte { get; set; } + + [Column("description")] + [HeaderAttributev2(caption: "Ragione Sociale", Order = 2)] + public string? RagioneSociale { get; set; } + + [Column("product")] + [HeaderAttributev2(caption: "Prodotto", Order = 3)] + public string? Prodotto { get; set; } + + [Column("IdTipoContratto")] + [HeaderAttributev2(caption: "Id Tipo Contratto", Order = 4)] + public long? IdTipoContratto { get; set; } + + [Column("TipoContratto")] + [HeaderAttributev2(caption: "TipoContratto", Order = 5)] + public string? TipoContratto { get; set; } + + [Column("Asseverazione")] + public bool? Asseverazione { get; set; } + + [Column("calcolo_asseverazione")] + public bool? CalcoloAsseverazione { get; set; } + + [Column("data_asseverazione")] + [HeaderAttributev2(caption: "Data Adesione al Bando", Order = 12)] + public DateTime? DataAsseverazione { get; set; } + + [Column("data_anagrafica")] + [HeaderAttributev2(caption: "Data Ultima Modifica Anagrafica", Order = 7)] + public DateTime? DataAnagrafica { get; set; } + + [HeaderAttributev2(caption: "Adessione al Bando", Order = 13)] + public string? TipoAsseverazione + { + get + { + if (Asseverazione.HasValue) + { + if (Asseverazione.Value) + { + return "SI"; + } + else + { + return "NO"; + } + } + else + return string.Empty; + } + } + + [HeaderAttributev2(caption: "Calcolo Asseverazione", Order = 9)] + public string? TipoCalcoloAsseverazione + { + get + { + if (CalcoloAsseverazione.HasValue) + { + if (CalcoloAsseverazione.Value) + { + return "SI"; + } + else + { + return "NO"; + } + } + else + return "NON CALCOLATO"; + } + } + + [Column("timestamp")] + [HeaderAttributev2(caption: "Timestamp", Order = 15)] + public DateTime? Timestamp { get; set; } + + [Column("idutente")] + [HeaderAttributev2(caption: "Id Utente", Order = 16)] + public string? IdUtente { get; set; } + + [Column("Descrizione")] + [HeaderAttributev2(caption: "Descrizione", Order = 14)] + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneImportDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneImportDto.cs new file mode 100644 index 0000000..6a9c9f8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Dto/EnteAsserverazioneImportDto.cs @@ -0,0 +1,9 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; + +public class EnteAsserverazioneImportDto +{ + public string? IdEnte { get; set; } + public string? RagioneSociale { get; set; } + public DateTime? DataAsseverazione { get; set; } + public bool? TipoAsseverazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Extensions/AsseverazioneExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Extensions/AsseverazioneExtensions.cs new file mode 100644 index 0000000..c503624 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Extensions/AsseverazioneExtensions.cs @@ -0,0 +1,55 @@ +using System.Data; +using System.Globalization; +using Microsoft.AspNetCore.Http; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Asseverazione.Extensions; + +public static class AsseverazioneExtensions +{ + public static List Mapper(this DataTable dt) + { + var list = new List(); + foreach (DataRow row in dt.Rows) + { + var ente = new EnteAsserverazioneImportDto + { + IdEnte = row[0].ToString(), + RagioneSociale = row[1].ToString(), + DataAsseverazione = String.IsNullOrEmpty(row[2].ToString()) ? null : Convert.ToDateTime(row[2]), + TipoAsseverazione = String.IsNullOrEmpty(row[3].ToString()) ? null : row[3].ToString() == "SI" + }; + list.Add(ente); + } + return list; + } + + public static EnteAsserverazioneListImportCreateCommand Mapper(this DataTable dt, AuthenticationInfo? authInfo) + { + var timestamp = DateTime.UtcNow.ItalianTime(); + var command = new EnteAsserverazioneListImportCreateCommand(authInfo); + var list = new List(); + var provider = CultureInfo.InvariantCulture; + string[] formats = { "yyyy-MM-dd", "yyyy/MM/dd", "dd-MM-yyyy", "dd/MM/yyyy", "yyyy-MM-dd 00:00:00", "yyyy/MM/dd 00:00:00", "dd-MM-yyyy 00:00:00", "dd/MM/yyyy 00:00:00" }; + + foreach (DataRow row in dt.Rows) + { + var ente = new EnteAsserverazioneImportCreateCommand(timestamp) + { + IdEnte = row[0].ToString(), + RagioneSociale = row[1].ToString(), + DataAsseverazione = String.IsNullOrEmpty(row[2].ToString()) ? null : DateTime.ParseExact(row[2].ToString()!, formats, provider), // Convert.ToDateTime(row[2]), + TipoAsseverazione = String.IsNullOrEmpty(row[3].ToString()) ? null : row[3].ToString() == "SI", + Descrizione = row[4].ToString(), + IdUtente = authInfo?.Id! + }; + + if (ente.TipoAsseverazione.HasValue) + list.Add(ente); + } + command.ListCommands = list; + return command; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/AsseverazioneQueryGet.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/AsseverazioneQueryGet.cs new file mode 100644 index 0000000..4ee7995 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/AsseverazioneQueryGet.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class AsseverazioneQueryGet(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/AsseverazioneQueryGetPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/AsseverazioneQueryGetPersistence.cs new file mode 100644 index 0000000..1fe2375 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/AsseverazioneQueryGetPersistence.cs @@ -0,0 +1,23 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class AsseverazioneQueryGetPersistence : DapperBase, IQuery> +{ + private readonly AsseverazioneQueryGet _command; + private static readonly string _sqlSelect = AsseverazioneSQLBuilder.SelectAll(); + public AsseverazioneQueryGetPersistence(AsseverazioneQueryGet command) + { + this._command = command; + } + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/Builder/AsseverazioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/Builder/AsseverazioneSQLBuilder.cs new file mode 100644 index 0000000..70d8318 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/Queries/Persistence/Builder/AsseverazioneSQLBuilder.cs @@ -0,0 +1,54 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; + +internal static class AsseverazioneSQLBuilder +{ + + private static string _sql = @" +SELECT ISNULL(b.[InternalIstitutionId], e.InternalIstitutionId) as IdEnte + , b.[Asseverazione] as asseverazione + , b.[Data] as dataasseverazione + , b.[Descrizione] as Descrizione + ,[Timestamp] as timestamp + ,[IdUtente] as idutente + ,e.Asseverazione as calcoloasseverazione + ,ISNULL(e.description, b.RagioneSociale) as RagioneSociale + ,t.Descrizione as TipoContratto + ,t.IdTipoContratto as IdTipoContratto + ,e.LastModified as dataanagrafica + ,c.product as prodotto +FROM (SELECT [InternalIstitutionId] + ,[Asseverazione] + ,[Data] + ,[Timestamp] + ,[IdUtente] + ,[RagioneSociale] + ,[Descrizione] +FROM ( + SELECT + [InternalIstitutionId] + ,[Asseverazione] + ,[Data] + ,[Timestamp] + ,[IdUtente] + ,[RagioneSociale] + ,[Descrizione] + , ROW_NUMBER() OVER (PARTITION BY [InternalIstitutionId] ORDER BY Timestamp DESC) AS RowNum + FROM [pfd].[Asseverazione] +) AS a +WHERE RowNum = 1) AS b +FULL JOIN pfd.Enti e +ON b.InternalIstitutionId = e.InternalIstitutionId +LEFT OUTER JOIN pfd.Contratti c +ON e.InternalIstitutionId = c.InternalIstitutionId +LEFT OUTER JOIN pfw.TipoContratto t +ON t.IdTipoContratto = c.FkIdTipoContratto +WHERE (e.institutionType NOT IN ('REC', 'CON') +OR e.institutionType IS NULL) +"; + + + public static string SelectAll() + { + return _sql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/QueryHandlers/AsseverazioneQueryGetHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/QueryHandlers/AsseverazioneQueryGetHandler.cs new file mode 100644 index 0000000..d7a7734 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Asseverazione/QueryHandlers/AsseverazioneQueryGetHandler.cs @@ -0,0 +1,29 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class AsseverazioneQueryGetHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + IMediator handler, + ILogger logger) : IRequestHandler?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IMediator _handler = handler; + public async Task?> Handle(AsseverazioneQueryGet request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new AsseverazioneQueryGetPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneCreateCommandHandler.cs new file mode 100644 index 0000000..b5914de --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneCreateCommandHandler.cs @@ -0,0 +1,95 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.CommandHandlers; + +public class DatiFatturazioneCreateCommandHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public DatiFatturazioneCreateCommandHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(DatiFatturazioneCreateCommand command, CancellationToken ct) + { + var (_, _, _, adesso) = Time.YearMonthDay(); + + var (error, errorDetails) = DatiFatturazioneValidator.Validate(command); + if (!string.IsNullOrEmpty(error)) + throw new ValidationException(_localizer[error, errorDetails]); + + command.DataCreazione = command.DataCreazione == null ? adesso : command.DataCreazione; + + using var uow = await _factory.Create(true, cancellationToken: ct); + var actualValue = await uow.Query(new DatiFatturazioneQueryGetByIdEntePersistence(command.AuthenticationInfo.IdEnte!), ct); + if (actualValue != null) + throw new DomainException(_localizer["DatiFatturazioneIdEnteExistent", command.AuthenticationInfo.IdEnte!]); + try + { + var rowAffected = 0; + var id = await uow.Execute(new DatiFatturazioneCreateCommandPersistence(command), ct); + if (id == null) + { + uow.Rollback(); + throw new DomainException(_localizer["DatiFatturazioneInputError"]); + } + + if (!command.Contatti!.IsNullNotAny()) + { + foreach (var commandContatto in command.Contatti!) + commandContatto.IdDatiFatturazione = id.Value; + + rowAffected += await uow.Execute(new DatiFatturazioneContattoCreateListCommandPersistence(command.Contatti!), ct); + + if (rowAffected != command.Contatti.Count) + { + uow.Rollback(); + throw new DomainException(_localizer["DatiFatturazioneInputError"]); + } + } + var actualDatiFatturazione = command.Mapper(id.Value); + rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.DatiFatturazione, + actualDatiFatturazione.Serialize())), ct); + + if (rowAffected == 1) + uow.Commit(); + else + { + uow.Rollback(); + throw new DomainException(_localizer["DatiFatturazioneInputError"]); + } + + return actualDatiFatturazione; + } + catch (Exception e) + { + uow.Rollback(); + var methodName = nameof(DatiFatturazioneCreateCommandHandler); + _logger.LogError(e, "Errore nel commando: \"{MethodName}\" per ente: \"{IdEnte}\"", methodName, command.AuthenticationInfo.IdEnte); + throw new DomainException(_localizer["DatiFatturazioneInputError"]); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneUpdateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneUpdateCommandHandler.cs new file mode 100644 index 0000000..55bb52b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/CommandHandlers/DatiFatturazioneUpdateCommandHandler.cs @@ -0,0 +1,97 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.CommandHandlers; + +public class DatiFatturazioneUpdateCommandHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public DatiFatturazioneUpdateCommandHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(DatiFatturazioneUpdateCommand command, CancellationToken ct) + { + var (_, _, _, adesso) = Time.YearMonthDay(); + + var (error, errorDetails) = DatiFatturazioneValidator.Validate(command); + if (!string.IsNullOrEmpty(error)) + throw new ValidationException(_localizer[error, errorDetails]); + + command.DataModifica = command.DataModifica == null ? adesso : command.DataModifica; + + using var uow = await _factory.Create(true, cancellationToken: ct); + var actualValue = await uow.Query(new DatiFatturazioneQueryGetByIdPersistence(command.Id!), ct) ?? throw new DomainException(_localizer["DatiFatturazioneIdExistent", command.Id!]); + + //verifico coerenza dati + if (actualValue.IdEnte != command.AuthenticationInfo.IdEnte || actualValue.Prodotto != command.AuthenticationInfo.Prodotto) + throw new DomainException(_localizer["DatiFatturazioneMismatchError"]); + + try + { + var updatedDatiFatturazione = await uow.Execute(new DatiFatturazioneUpdateCommandPersistence(command), ct) ?? + throw new DomainException(_localizer["DatiFatturazioneUpdateError"]); + + var rowAffected = 0; + + await uow.Execute(new DatiFatturazioneContattoDeleteCommandPersistence(new DatiFatturazioneContattoDeleteCommand() { IdDatiFatturazione = command.Id }), ct); + + if(!command.Contatti!.IsNullNotAny()) + { + foreach (var commandContatto in command.Contatti!) + commandContatto.IdDatiFatturazione = command.Id!; + + rowAffected += await uow.Execute(new DatiFatturazioneContattoCreateListCommandPersistence(command.Contatti!), ct); + + if (rowAffected != command.Contatti.Count) + { + uow.Rollback(); + throw new DomainException(_localizer["DatiFatturazioneInputError"]); + } + updatedDatiFatturazione.Contatti = command.Contatti!.Mapper(); + } + + rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.DatiFatturazione, + updatedDatiFatturazione.Serialize())), ct); + + if (rowAffected == 1) + uow.Commit(); + else + { + uow.Rollback(); + throw new DomainException(_localizer["DatiFatturazioneInputError"]); + } + return updatedDatiFatturazione; + } + catch (Exception e) + { + uow.Rollback(); + var methodName = nameof(DatiFatturazioneUpdateCommandHandler); + _logger.LogError(e, "Errore nel commando: \"{MethodName}\" per dati commessa id: \"{Id}\"", methodName, command.Id); + throw new DomainException(_localizer["DatiFatturazioneUpdateError"]); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateCommand.cs new file mode 100644 index 0000000..aca4f06 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateCommand.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +public sealed class DatiFatturazioneContattoCreateCommand : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public long IdDatiFatturazione { get; set; } + public string? Email { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateListCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateListCommand.cs new file mode 100644 index 0000000..6dc87ab --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoCreateListCommand.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +public sealed class DatiFatturazioneContattoCreateListCommand : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + + List? DatiFatturazioneContattoLista { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoDeleteCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoDeleteCommand.cs new file mode 100644 index 0000000..1bbd2f1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneContattoDeleteCommand.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +public sealed class DatiFatturazioneContattoDeleteCommand : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public long IdDatiFatturazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneCreateCommand.cs new file mode 100644 index 0000000..80a3aeb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneCreateCommand.cs @@ -0,0 +1,21 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +public sealed class DatiFatturazioneCreateCommand(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? Cup { get; set; } + public bool NotaLegale { get; set; } + public string? CodCommessa { get; set; } + public DateTime? DataDocumento { get; set; } + public bool? SplitPayment { get; set; } + public string? IdDocumento { get; set; } + public string? Map { get; set; } + public string? TipoCommessa { get; set; } + public string? Pec { get; set; } + public DateTime? DataCreazione { get; set; } + public List? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneUpdateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneUpdateCommand.cs new file mode 100644 index 0000000..f5e92ee --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/DatiFatturazioneUpdateCommand.cs @@ -0,0 +1,22 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +public sealed class DatiFatturazioneUpdateCommand(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public long Id { get; set; } + public string? Cup { get; set; } + public bool NotaLegale { get; set; } + public string? CodCommessa { get; set; } + public DateTime? DataDocumento { get; set; } + public bool? SplitPayment { get; set; } + public string? IdDocumento { get; set; } + public string? Map { get; set; } + public string? TipoCommessa { get; set; } + public string? Pec { get; set; } + public DateTime? DataModifica { get; set; } + public List? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoCreateListCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoCreateListCommandPersistence.cs new file mode 100644 index 0000000..99defdb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoCreateListCommandPersistence.cs @@ -0,0 +1,21 @@ +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using System.Data; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands.Persistence; + +public class DatiFatturazioneContattoCreateListCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly List _command; + public DatiFatturazioneContattoCreateListCommandPersistence(List command) + => _command = command; + + private static readonly string _sqlInsert = @" + INSERT INTO [schema]DatiFatturazioneContatti + (fkiddatifatturazione, + email) + VALUES (@idDatiFatturazione, + @email);"; + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + => await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), _command, transaction); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoDeleteCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoDeleteCommandPersistence.cs new file mode 100644 index 0000000..a00c0aa --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneContattoDeleteCommandPersistence.cs @@ -0,0 +1,17 @@ +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using System.Data; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands.Persistence; +public class DatiFatturazioneContattoDeleteCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly DatiFatturazioneContattoDeleteCommand _command; + public DatiFatturazioneContattoDeleteCommandPersistence(DatiFatturazioneContattoDeleteCommand command) + => _command = command; + + private static readonly string _sqlDelete = @" +DELETE FROM [schema]DatiFatturazioneContatti +WHERE FkIdDatiFatturazione = @IdDatiFatturazione;"; + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + => await ((IDatabase)this).ExecuteAsync(connection!, _sqlDelete.Add(schema), _command, transaction); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneCreateCommandPersistence.cs new file mode 100644 index 0000000..d7c5998 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneCreateCommandPersistence.cs @@ -0,0 +1,54 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands.Persistence; + +public sealed class DatiFatturazioneCreateCommandPersistence(DatiFatturazioneCreateCommand command) : DapperBase, ICommand +{ + public bool RequiresTransaction => true; + private readonly DatiFatturazioneCreateCommand _command = command; + + private static readonly string _sqlInsert = @" +INSERT INTO [schema]DatiFatturazione + (cup, + notaLegale, + codcommessa, + datadocumento, + splitpayment, + fkidente, + iddocumento, + datacreazione, + [map], + fktipocommessa, + pec, + fkprodotto) +VALUES (@cup, + @notaLegale, + @codcommessa, + @datadocumento, + @splitpayment, + @idente, + @iddocumento, + @datacreazione, + @map, + @tipocommessa, + @pec, + @prodotto); +Select SCOPE_IDENTITY() 'SCOPE_IDENTITY'"; + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + => await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), new + { + cup = _command.Cup, + notaLegale = _command.NotaLegale, + codCommessa = _command.CodCommessa, + dataDocumento = _command.DataDocumento, + splitPayment = _command.SplitPayment, + idEnte = _command.AuthenticationInfo.IdEnte, + idDocumento = _command.IdDocumento, + dataCreazione = _command.DataCreazione, + map = _command.Map, + tipoCommessa = _command.TipoCommessa, + pec = _command.Pec, + prodotto = _command.AuthenticationInfo.Prodotto + }, transaction); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneUpdateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneUpdateCommandPersistence.cs new file mode 100644 index 0000000..f5c66fa --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Commands/Persistence/DatiFatturazioneUpdateCommandPersistence.cs @@ -0,0 +1,55 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands.Persistence; + +public class DatiFatturazioneUpdateCommandPersistence(DatiFatturazioneUpdateCommand command) : DapperBase, ICommand +{ + public bool RequiresTransaction => true; + private readonly DatiFatturazioneUpdateCommand _command = command; + private static readonly string _sqlUpdate = @" +UPDATE [schema]DatiFatturazione +SET cup = @cup, + notaLegale = @notaLegale, + codcommessa = @codcommessa, + datadocumento = @datadocumento, + splitpayment = @splitpayment, + iddocumento = @iddocumento, + datamodifica = @datamodifica, + [map] = @map, + fktipocommessa = @tipocommessa, + pec = @pec +WHERE IdDatiFatturazione = @id;"; + + private static readonly string _sqlSelect = DatiFatturazioneSQLBuilder.SelectById(); + + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + try + { + var rowAffected = await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdate.Add(schema), new + { + id = _command.Id, + cup = _command.Cup, + notaLegale = _command.NotaLegale, + codCommessa = _command.CodCommessa, + dataDocumento = _command.DataDocumento, + splitPayment = _command.SplitPayment, + idDocumento = _command.IdDocumento, + map = _command.Map, + tipoCommessa = _command.TipoCommessa, + pec = _command.Pec, + dataModifica = _command.DataModifica + }, transaction); + + if (rowAffected == 1) + return await ((IDatabase)this).SingleAsync(connection!, _sqlSelect.Add(schema), new { id = _command.Id }, transaction); + } + catch { } + return null; + } + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneMapper.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneMapper.cs new file mode 100644 index 0000000..49291c4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneMapper.cs @@ -0,0 +1,39 @@ +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni; +public static class DatiFatturazioneMapper +{ + public static IEnumerable? Mapper(this List model) + { + if (model == null) + return null; + return model.Select(x => x.Mapper()); + } + + public static DatiFatturazioneContatto Mapper(this DatiFatturazioneContattoCreateCommand model) => + new() + { + Email = model.Email, + IdDatiFatturazione = model.IdDatiFatturazione + }; + + public static DatiFatturazione Mapper(this DatiFatturazioneCreateCommand model, long id) => + new() + { + NotaLegale = model.NotaLegale, + CodCommessa = model.CodCommessa, + Cup = model.Cup, + DataCreazione = model.DataCreazione!.Value, + Id = id, + DataDocumento = model.DataDocumento, + SplitPayment = model.SplitPayment, + IdDocumento = model.IdDocumento, + Map = model.Map, + Pec = model.Pec, + TipoCommessa = model.TipoCommessa, + Contatti = model.Contatti!.Mapper(), + IdEnte = model.AuthenticationInfo.IdEnte, + Prodotto = model.AuthenticationInfo.Prodotto + }; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneValidator.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneValidator.cs new file mode 100644 index 0000000..53be9b6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/DatiFatturazioneValidator.cs @@ -0,0 +1,93 @@ +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni; + +public static class DatiFatturazioneValidator +{ + public static (string, string[]) Validate(DatiFatturazioneUpdateCommand cmd) + { + return Validate( + cmd.Cup, + cmd.CodCommessa, + cmd.DataDocumento, + cmd.SplitPayment, + cmd.IdDocumento, + cmd.Map, + cmd.TipoCommessa, + cmd.Pec, + cmd.Contatti); + } + + public static (string, string[]) Validate(DatiFatturazioneCreateCommand cmd) + { + return Validate( + cmd.Cup, + cmd.CodCommessa, + cmd.DataDocumento, + cmd.SplitPayment, + cmd.IdDocumento, + cmd.Map, + cmd.TipoCommessa, + cmd.Pec, + cmd.Contatti); + } + + private static (string, string[]) Validate( + string? cup, + string? codCommessa, + DateTimeOffset? dataDocumento, + bool? splitPayment, + string? idDocumento, + string? map, + string? tipoCommessa, + string? pec) + { + if (!string.IsNullOrEmpty(cup) && cup.Length > 15) + return ("DatiFatturazioneCupInvalid", Array.Empty()); + + if (!string.IsNullOrEmpty(codCommessa) && codCommessa.Length > 100) + return ("DatiFatturazioneCodiceInvalid", Array.Empty()); + + if (!string.IsNullOrEmpty(idDocumento) && idDocumento.Length > 20) + return ("DatiFatturazioneIdDocumentoInvalid", Array.Empty()); + + if (!string.IsNullOrEmpty(map) && map.Length > 100) + return ("DatiFatturazioneMapInvalid", Array.Empty()); + + if (!string.IsNullOrEmpty(tipoCommessa) && tipoCommessa.Length > 1) + return ("DatiFatturazioneTipoCommessaInvalid", Array.Empty()); + + if (string.IsNullOrEmpty(pec) || pec.IsNotValidEmail()) + return ("DatiFatturazionePecInvalid", Array.Empty()); + + return (null, null)!; + } + + private static (string, string[]) Validate( + string? cup, + string? codCommessa, + DateTimeOffset? dataDocumento, + bool? splitPayment, + string? idDocumento, + string? map, + string? tipoCommessa, + string? pec, + List? contatti) + { + if (!contatti!.IsNullNotAny()) + { + if (contatti!.Count > 3) + return ("DatiFatturazioneContattoInvalid", Array.Empty()); + foreach (var contatto in contatti) + { + if (contatto.Email!.IsNotValidEmail()) + return ("DatiFatturazioneContattoEmailInvalid", Array.Empty()); + } + }else // deve esistere almeno un contatto + return ("DatiFatturazioneContattoInvalid", Array.Empty()); + + return Validate(cup, codCommessa, dataDocumento, splitPayment, idDocumento, map, tipoCommessa, pec); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Dto/DatiFatturazioneEnteDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Dto/DatiFatturazioneEnteDto.cs new file mode 100644 index 0000000..82d40a0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Dto/DatiFatturazioneEnteDto.cs @@ -0,0 +1,92 @@ +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; + +[Table("DatiFatturazione")] +public class DatiFatturazioneEnteDto +{ + [JsonPropertyOrder(-6)] + public string? Key + { + get + { + return $"{IdEnte}_{Prodotto}_{Profilo}"; + } + } + + [Column("Description")] + [JsonPropertyOrder(-5)] + [HeaderAttribute(caption: "Ragione Sociale", Order = 1)] + public string? RagioneSociale { get; set; } + + [Column("FkIdEnte")] + [JsonPropertyOrder(-4)] + public string? IdEnte { get; set; } + + [Column("internalistitutionid")] + [JsonIgnore] + public string? InternalInstituitionId { get; set; } + + [Column("product")] + [JsonIgnore] + [Header(caption: "Prodotto", Order = 2)] + public string? InternalProduct { get; set; } + + [Column("institutionType")] + [JsonPropertyOrder(-2)] + [Header(caption: "Profilo", Order = 3)] + public string? Profilo { get; set; } + + [Column("IdDatiFatturazione")] + [JsonPropertyOrder(-1)] + public long? Id { get; set; } + + [Column("FkTipoCommessa")] + public string? TipoCommessa { get; set; } + + [Column("FkProdotto")] + [JsonPropertyOrder(-3)] + public string? Prodotto { get; set; } + + [Header(caption: "Cup", Order = 4)] + public string? Cup { get; set; } + + [Header(caption: "Cod. Commessa", Order = 5)] + public string? CodCommessa { get; set; } + public DateTime? DataDocumento { get; set; } + public bool? SplitPayment { get; set; } + + [Header(caption: "Id Documento", Order = 6)] + public string? IdDocumento { get; set; } + public string? Map { get; set; } + + [Header(caption: "Pec", Order = 9)] + public string? Pec { get; set; } + public bool? NotaLegale { get; set; } + public DateTimeOffset? DataCreazione { get; set; } + public DateTimeOffset? DataModifica { get; set; } + + + [JsonIgnore] + [Header(caption: "Data Documento", Order = 7)] + public string? SDataDocumento { get { return DataDocumento?.ToString("d"); } } + + [Header(caption: "Split Payment", Order = 8)] + [JsonIgnore] + public string? SSplitPayment { get { return SplitPayment.To(); } } + + [Header(caption: "Nota Legale", Order = 10)] + [JsonIgnore] + public string? SNotaLegale { get { return NotaLegale.To(); } } + + [Header(caption: "Data Creazione", Order = 11)] + [JsonIgnore] + public string? SDataCreazione { get { return DataCreazione?.ToString("d"); } } + + [Header(caption: "Data Modifica", Order = 12)] + [JsonIgnore] + public string? SDataModifica { get { return DataModifica?.ToString("d"); } } + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByDescrizione.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByDescrizione.cs new file mode 100644 index 0000000..937dd47 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByDescrizione.cs @@ -0,0 +1,14 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; + +public class DatiFatturazioneQueryGetByDescrizione(IAuthenticationInfo? authenticationInfo, string[]? idEnti, string? prodotto, string? profilo, int? top) : IRequest> +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? IdEnti { get; internal set; } = idEnti; + public string? Prodotto { get; internal set; } = prodotto; + public string? Profilo { get; internal set; } = profilo; + public int? Top { get; internal set; } = top; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetById.cs new file mode 100644 index 0000000..2fe1cfc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetById.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; + +public class DatiFatturazioneQueryGetById : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public long Id { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByIdEnte.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByIdEnte.cs new file mode 100644 index 0000000..783c226 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/DatiFatturazioneQueryGetByIdEnte.cs @@ -0,0 +1,14 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; + +public class DatiFatturazioneQueryGetByIdEnte : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } + public DatiFatturazioneQueryGetByIdEnte(IAuthenticationInfo? authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneContattoSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneContattoSQLBuilder.cs new file mode 100644 index 0000000..47c1b35 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneContattoSQLBuilder.cs @@ -0,0 +1,35 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; + +public static class DatiFatturazioneContattoSQLBuilder +{ + private static string WhereByIdDatiFatturazione() + { + DatiFatturazioneContatto? obj; + var fieldId = nameof(@obj.IdDatiFatturazione).GetColumn(); + return $"{fieldId} = @{nameof(@obj.IdDatiFatturazione)}"; + } + + private static SqlBuilder CreateSelect() + { + DatiFatturazioneContatto? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdDatiFatturazione).GetAsColumn()); + builder.Select(nameof(@obj.Email)); + return builder; + } + + public static string SelectAllByIdDatiFatturazione() + { + var tableName = nameof(DatiFatturazioneContatto); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereByIdDatiFatturazione(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneSQLBuilder.cs new file mode 100644 index 0000000..cd1ee8d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneSQLBuilder.cs @@ -0,0 +1,122 @@ +using Dapper; +using DocumentFormat.OpenXml.Spreadsheet; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; + +public static class DatiFatturazioneSQLBuilder +{ + private static string WhereByIdEnte() + { + DatiFatturazione? obj; + var fieldIdEnteName = nameof(@obj.IdEnte).GetColumn(); + return $"{fieldIdEnteName} = @{nameof(@obj.IdEnte)}"; + } + + private static string WhereById() + { + DatiFatturazione? obj; + var fieldId = nameof(@obj.Id).GetColumn(); + return $"{fieldId} = @{nameof(@obj.Id)}"; + } + + private static SqlBuilder CreateSelect() + { + DatiFatturazione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Cup)); + builder.Select(nameof(@obj.NotaLegale)); + builder.Select(nameof(@obj.CodCommessa)); + builder.Select(nameof(@obj.DataDocumento)); + builder.Select(nameof(@obj.SplitPayment)); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.IdDocumento)); + builder.Select(nameof(@obj.Map)); + builder.Select(nameof(@obj.TipoCommessa).GetAsColumn()); + builder.Select(nameof(@obj.Prodotto).GetAsColumn()); + builder.Select(nameof(@obj.Pec)); + builder.Select(nameof(@obj.DataCreazione)); + builder.Select(nameof(@obj.DataModifica)); + return builder; + } + + public static string SelectById() + { + var tableName = nameof(DatiFatturazione); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectByIdEnte() + { + var tableName = nameof(DatiFatturazione); + var builder = CreateSelect(); + var where = WhereByIdEnte(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectByDescrizione(bool all = true) + { + DatiFatturazioneEnteDto? @obj = null; + var idEnte = nameof(@obj.IdEnte).GetColumn(); + var internalIdEnte = nameof(@obj.InternalInstituitionId).GetColumn(); + var id = nameof(Ente.IdEnte).GetColumn(); + var prodotto = nameof(@obj.Prodotto).GetColumn(); + var internalProdotto = nameof(@obj.InternalProduct).GetColumn(); + var profilo = nameof(@obj.Profilo).GetColumn(); + + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.RagioneSociale).GetAsColumn()); + builder.Select($"ISNULL({idEnte},e.{internalIdEnte}) as {nameof(@obj.IdEnte)}"); + builder.Select($"ISNULL({prodotto},{internalProdotto}) as {nameof(@obj.Prodotto)}"); + builder.Select($"{nameof(@obj.Profilo).GetAsColumn()}"); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Cup)); + builder.Select(nameof(@obj.NotaLegale)); + builder.Select(nameof(@obj.CodCommessa)); + builder.Select(nameof(@obj.DataDocumento)); + builder.Select(nameof(@obj.SplitPayment)); + builder.Select(nameof(@obj.IdDocumento)); + builder.Select(nameof(@obj.Map)); + builder.Select(nameof(@obj.TipoCommessa).GetAsColumn()); + builder.Select(nameof(@obj.Pec)); + builder.Select(nameof(@obj.DataCreazione)); + builder.Select(nameof(@obj.DataModifica)); + builder.Select(nameof(@obj.DataModifica)); + + var tableName = $"[schema]{nameof(DatiFatturazioneEnteDto).GetTable()} f"; + var rightEnteTable = $"[schema_inner].{nameof(Ente).GetTable()}"; + var innerContrattoTable = $"[schema_inner].{nameof(Contratto).GetTable()}"; + + builder.RightJoin($"{rightEnteTable} e on e.{internalIdEnte} = f.{idEnte}"); + builder.InnerJoin($"{innerContrattoTable} c on e.{internalIdEnte} = c.{internalIdEnte}"); + + if (!all) + builder.Where(WhereByIdEnti()); + + var builderTemplate = builder.AddTemplate($"Select /*top*/ /**select**/ from {tableName} /**rightjoin**/ /**innerjoin**/ /**where**/ "); + return builderTemplate.RawSql; + } + + private static string WhereBySearch() + { + Ente? obj; + var fieldDescription = nameof(@obj.Descrizione).GetColumn(); + return $"{fieldDescription} LIKE '%' + @{nameof(@obj.Descrizione)} + '%'"; + } + private static string WhereByIdEnti() + { + Ente? obj; + var fieldDescription = nameof(@obj.IdEnte).GetColumn(); + return $"e.{fieldDescription} IN @IdEnti "; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneStoricoSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneStoricoSQLBuilder.cs new file mode 100644 index 0000000..a9e5804 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/Builder/DatiFatturazioneStoricoSQLBuilder.cs @@ -0,0 +1,39 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; + +public static class DatiFatturazioneStoricoSQLBuilder +{ + private static string WhereByIdEnteAnnoMese() + { + DatiFatturazioneStorico? obj; + var fieldIdEnteName = nameof(@obj.IdEnte).GetColumn(); + var fieldAnno = nameof(@obj.AnnoValidita); + var fieldMese = nameof(@obj.MeseValidita); + return $"{fieldIdEnteName} = @{nameof(@obj.IdEnte)} AND {fieldAnno} = @{nameof(@obj.AnnoValidita)} AND {fieldMese} = @{nameof(@obj.MeseValidita)}"; + } + + + private static SqlBuilder CreateSelect() + { + DatiFatturazioneStorico? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.AnnoValidita)); + builder.Select(nameof(@obj.MeseValidita)); + builder.Select(nameof(@obj.DatiFatturazione).GetAsColumn()); + return builder; + } + + public static string SelectByIdEnteAnnoMese() + { + var tableName = nameof(DatiFatturazione); + var builder = CreateSelect(); + var where = WhereByIdEnteAnnoMese(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneContattoQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneContattoQueryGetByIdPersistence.cs new file mode 100644 index 0000000..c0a8e3c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneContattoQueryGetByIdPersistence.cs @@ -0,0 +1,21 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class DatiFatturazioneContattoQueryGetByIdPersistence : DapperBase, IQuery> +{ + private readonly long _id; + private static readonly string _sqlSelect = DatiFatturazioneContattoSQLBuilder.SelectAllByIdDatiFatturazione(); + + public DatiFatturazioneContattoQueryGetByIdPersistence(long id) + { + this._id = id; + } + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), new { IdDatiFatturazione = _id }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByDescrizionePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByDescrizionePersistence.cs new file mode 100644 index 0000000..d8ba759 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByDescrizionePersistence.cs @@ -0,0 +1,39 @@ +using System.Data; +using System.Data.SqlTypes; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class DatiFatturazioneQueryGetByDescrizionePersistence(IPortaleFattureOptions options, string[]? idEnti, string? prodotto, string? profilo, int? top) : DapperBase, IQuery?> +{ + private readonly IPortaleFattureOptions _options = options; + private readonly string[]? _idEnti = idEnti; + private readonly string? _prodotto = prodotto; + private readonly string? _profilo = profilo; + private readonly int? _top = top; + private static readonly string _sqlSelect = DatiFatturazioneSQLBuilder.SelectByDescrizione(false); + private static readonly string _sqlSelectAll = DatiFatturazioneSQLBuilder.SelectByDescrizione(true); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + string? sql; + if (_idEnti!.IsNullNotAny()) + sql = _sqlSelectAll.Add(schema); + else + sql = _sqlSelect.Add(schema); + + sql = sql.AddJoin(_options.SelfCareSchema!); + sql += EnteSQLBuilder.AddSearch(_prodotto, _profilo); + sql = sql.AddTop(_top); + return await ((IDatabase)this).SelectAsync(connection!, sql, new + { + idEnti = _idEnti, + prodotto = _prodotto, + profilo = _profilo + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdEntePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdEntePersistence.cs new file mode 100644 index 0000000..d60f3fb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdEntePersistence.cs @@ -0,0 +1,30 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class DatiFatturazioneQueryGetByIdEntePersistence : DapperBase, IQuery +{ + private readonly string _idEnte; + private static readonly string _sqlSelect = DatiFatturazioneSQLBuilder.SelectByIdEnte(); + public DatiFatturazioneQueryGetByIdEntePersistence(string idEnte) + { + this._idEnte = idEnte; + } + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var values = await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), new { idente = _idEnte }, transaction); + if (values.IsNullNotAny()) + return null; + if (values.Count() > 1) + throw new DomainException($"Duplicate values in dati fatturazione for ente id: {_idEnte}"); + return values.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdPersistence.cs new file mode 100644 index 0000000..df6268c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneQueryGetByIdPersistence.cs @@ -0,0 +1,30 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class DatiFatturazioneQueryGetByIdPersistence : DapperBase, IQuery +{ + private readonly long _id; + private static readonly string _sqlSelect = DatiFatturazioneSQLBuilder.SelectById(); + + public DatiFatturazioneQueryGetByIdPersistence(long id) + { + this._id = id; + } + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + try + { + return await ((IDatabase)this).SingleAsync(connection!, _sqlSelect.Add(schema), new { id = _id }, transaction); + } + catch + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneStoricoQueryGetByIdEntePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneStoricoQueryGetByIdEntePersistence.cs new file mode 100644 index 0000000..5cdf70b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneStoricoQueryGetByIdEntePersistence.cs @@ -0,0 +1,26 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class DatiFatturazioneStoricoQueryGetByIdEntePersistence(string idEnte, int annoValidita, int meseValidita) : DapperBase, IQuery +{ + private readonly string _idEnte = idEnte; + private readonly int _annoValidita = annoValidita; + private readonly int _meseValidita = meseValidita; + private static readonly string _sqlSelect = DatiFatturazioneStoricoSQLBuilder.SelectByIdEnteAnnoMese(); + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var value = (await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new + { + idente = _idEnte, + annovalidita = _annoValidita, + meseValidita = _meseValidita + }, transaction)).FirstOrDefault(); + return value; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneWithContattiQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneWithContattiQueryGetByIdPersistence.cs new file mode 100644 index 0000000..d75fff7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/Queries/Persistence/DatiFatturazioneWithContattiQueryGetByIdPersistence.cs @@ -0,0 +1,26 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class DatiFatturazioneWithContattiQueryGetByIdPersistence : DapperBase, IQuery +{ + private readonly long _id; + private static readonly string _sqlSelect = String.Join(";", DatiFatturazioneSQLBuilder.SelectById(), DatiFatturazioneContattoSQLBuilder.SelectAllByIdDatiFatturazione()); + + public DatiFatturazioneWithContattiQueryGetByIdPersistence(long id) + { + this._id = id; + } + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var values = await ((IDatabase)this).QueryMultipleAsync(connection!, _sqlSelect.Add(schema), new { id = _id , IdDatiFatturazione = _id }, transaction); + if (values == null) + return null; + var datiFatturazione = await values.ReadFirstAsync(); + datiFatturazione.Contatti = await values.ReadAsync(); + return datiFatturazione; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByDescrizioneHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByDescrizioneHandler.cs new file mode 100644 index 0000000..8b22260 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByDescrizioneHandler.cs @@ -0,0 +1,45 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.QueryHandlers; + +public class DatiFatturazioneQueryGetByDescrizioneHandler : IRequestHandler?> +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + private readonly IPortaleFattureOptions _options; + public DatiFatturazioneQueryGetByDescrizioneHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + IPortaleFattureOptions options, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + _options = options; + } + + public async Task?> Handle(DatiFatturazioneQueryGetByDescrizione command, CancellationToken ct) + { + if (command.AuthenticationInfo!.Auth! != AuthType.PAGOPA) + throw new SecurityException(); + + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new DatiFatturazioneQueryGetByDescrizionePersistence(_options, + command.IdEnti, + command.Prodotto, + command.Profilo, + command.Top), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdEnteHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdEnteHandler.cs new file mode 100644 index 0000000..9ebd4ba --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdEnteHandler.cs @@ -0,0 +1,37 @@ +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using MediatR; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.QueryHandlers; + +public class DatiFatturazioneQueryGetByIdEnteHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public DatiFatturazioneQueryGetByIdEnteHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(DatiFatturazioneQueryGetByIdEnte command, CancellationToken ct) + { + var idEnte = command.AuthenticationInfo!.IdEnte!; + using var uow = await _factory.Create(true, cancellationToken: ct); + var datiCommessa = await uow.Query(new DatiFatturazioneQueryGetByIdEntePersistence(idEnte), ct) ?? throw new NotFoundException(_localizer["DatiFatturazioneGetErrorIdEnte", idEnte]); + datiCommessa.Contatti = await uow.Query(new DatiFatturazioneContattoQueryGetByIdPersistence(datiCommessa.Id), ct); + return datiCommessa; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdHandler.cs new file mode 100644 index 0000000..8d81347 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiFatturazioni/QueryHandlers/DatiFatturazioneQueryGetByIdHandler.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using MediatR; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.QueryHandlers; + +public class DatiFatturazioneQueryGetByIdHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public DatiFatturazioneQueryGetByIdHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(DatiFatturazioneQueryGetById command, CancellationToken ct) + { + // 403 + using var uow = await _factory.Create(true, cancellationToken: ct); + var datiCommessa = await uow.Query(new DatiFatturazioneWithContattiQueryGetByIdPersistence(command.Id), ct); + return datiCommessa is null ? throw new NotFoundException(_localizer["DatiFatturazioneGetError", command.Id]) : datiCommessa; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiConfigurazioneModuloCommessaCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiConfigurazioneModuloCommessaCreateCommandHandler.cs new file mode 100644 index 0000000..9b8adfc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiConfigurazioneModuloCommessaCreateCommandHandler.cs @@ -0,0 +1,119 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class DatiConfigurazioneModuloCommessaCreateCommandHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public DatiConfigurazioneModuloCommessaCreateCommandHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(DatiConfigurazioneModuloCommessaCreateCommand command, CancellationToken ct) + { + var tipi = command.Tipi; + + foreach (var cmd in tipi!) + { + var (error, errorDetails) = DatiConfigurazioneModuloCommessaValidator.ValidateTipo(cmd); + if (!string.IsNullOrEmpty(error)) + throw new DomainException(_localizer[error, errorDetails]); + } + + var categorie = command.Categorie; + foreach (var cmd in categorie!) + { + var (error, errorDetails) = DatiConfigurazioneModuloCommessaValidator.ValidateCategoria(cmd); + if (!string.IsNullOrEmpty(error)) + throw new DomainException(_localizer[error, errorDetails]); + } + + // verifico configurazione e valido + using var dbContext = await _factory.Create(cancellationToken: ct); + var spedizioneConfig = await dbContext.Query(new SpedizioneQueryGetAllPersistence()); + var (errorct, errorDetailsct) = spedizioneConfig!.ValidateCategorieConfiguazione(command); + if (!string.IsNullOrEmpty(errorct)) + throw new DomainException(_localizer[errorct, errorDetailsct]); + + var count = command.Tipi!.Count() + command.Categorie!.Count(); + var firstTipoRequest = command.Tipi!.FirstOrDefault(); + var idTipoContratto = firstTipoRequest!.IdTipoContratto; + var prodotto = firstTipoRequest.Prodotto; + var dataCreazione = command.Tipi!.FirstOrDefault()!.DataCreazione!.Value; + + // verifico se esiste già un valore per la configurazione modulo commessa + using var uow = await _factory.Create(true, cancellationToken: ct); + var lastValue = await uow.Query(new DatiConfigurazioneModuloCommessaQueryGetPersistence(idTipoContratto: idTipoContratto, prodotto: prodotto)); + + try + { + if (lastValue != null) + { + var lastInizioValidità = lastValue.Tipi!.FirstOrDefault()!.DataInizioValidita; + var lastIdTipoContratto = lastValue.Tipi!.FirstOrDefault()!.IdTipoContratto; + var lastProdotto = lastValue.Tipi!.FirstOrDefault()!.Prodotto; + var updateCommand = new DatiConfigurazioneModuloCommessaUpdateCommand() + { + Tipo = new DatiConfigurazioneModuloCommessaUpdateTipoCommand() + { + IdTipoContratto = lastIdTipoContratto, + Prodotto = lastProdotto, + DataModifica = dataCreazione, + DataFineValidita = dataCreazione, + DataInizioValidita = lastInizioValidità + }, + Categoria = new DatiConfigurazioneModuloCommessaUpdateCategoriaCommand() + { + IdTipoContratto = lastIdTipoContratto, + Prodotto = lastProdotto, + DataModifica = dataCreazione, + DataFineValidita = dataCreazione, + DataInizioValidita = lastInizioValidità + } + }; + var updateRowAffected = await uow.Execute(new DatiConfigurazioneModuloCommessaUpdateCommandPersistence(updateCommand), ct); + if (updateRowAffected != count) + { + uow.Rollback(); + throw new DomainException(_localizer["DatiConfigurazioneModuloCommessaError"]); + } + } + + var rowAffected = await uow.Execute(new DatiConfigurazioneModuloCommessaCreateCommandPersistence(command), ct); + if (rowAffected != count) + { + uow.Rollback(); + throw new DomainException(_localizer["DatiConfigurazioneModuloCommessaError"]); + } + else + uow.Commit(); + return await uow.Query(new DatiConfigurazioneModuloCommessaQueryGetPersistence(idTipoContratto: idTipoContratto, prodotto: prodotto)); + } + catch (Exception e) + { + uow.Rollback(); + var methodName = nameof(DatiConfigurazioneModuloCommessaCreateCommandHandler); + _logger.LogError(e, "Errore nel salvataggio dei dati configurazione: \"{MethodName}\" per tipo contratto: \"{TipoContratto}\"", methodName, firstTipoRequest.IdTipoContratto); + throw new DomainException(_localizer["DatiConfigurazioneModuloCommessaError"]); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiModuloCommessaCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiModuloCommessaCreateCommandHandler.cs new file mode 100644 index 0000000..a9e0ef7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/CommandHandlers/DatiModuloCommessaCreateCommandHandler.cs @@ -0,0 +1,174 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class DatiModuloCommessaCreateCommandHandler( + IFattureDbContextFactory factory, + IScadenziarioService scadenziarioService, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IScadenziarioService _scadenziarioService = scadenziarioService; + + public async Task Handle(DatiModuloCommessaCreateListCommand command, CancellationToken ct) + { + var (annoAttuale, meseAttuale, giornoAttuale, adesso) = Time.YearMonthDayFatturazione(); + + var (valid, scadenziario) = await _scadenziarioService.GetScadenziario(command.AuthenticationInfo, TipoScadenziario.DatiModuloCommessa, annoAttuale, meseAttuale); + + if (!valid) + throw new ValidationException(_localizer["DataScadenziarioValidationError", $"{scadenziario.GiornoInizio}-{scadenziario.GiornoFine}"]); + + var idTipoContratto = command.AuthenticationInfo.IdTipoContratto; + var prodotto = command.AuthenticationInfo.Prodotto; + var idEnte = command.AuthenticationInfo.IdEnte; + var stato = string.Empty; + + using (var at = await _factory.Create(cancellationToken: ct)) + { + // recupero sempre lo stesso contratto mese anno prodotto ente + // anche se è cambiato il contratto + var datiAttivi = await at.Query(new DatiModuloCommessaQueryGetByIdPersistence(idEnte, annoAttuale, meseAttuale, prodotto), ct); + if (!datiAttivi!.IsNullNotAny()) + idTipoContratto = datiAttivi!.Select(x => x.IdTipoContratto).FirstOrDefault(); + } + + Dictionary categorieTotale = []; + IEnumerable? categorie; + DatiConfigurazioneModuloCommessa? confModuloCommessa = null; + + using (var rs = await _factory.Create(true, cancellationToken: ct)) + { + var prodotti = await rs.Query(new ProdottoQueryGetAllPersistence(), ct); + if (prodotti.IsNullNotAny()) + { + var msg = "Provide products in configurazion!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + prodotto = prodotti.Where(x => x.Nome!.ToLower() == prodotto!.ToLower()).Select(x => x.Nome).FirstOrDefault(); + if (prodotto == null) + { + var msg = "I could not find the specified product!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + var contratti = await rs.Query(new TipoContrattoQueryGetAllPersistence(), ct); + if (contratti.IsNullNotAny()) + { + var msg = "Provide contracts in configurazion!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + idTipoContratto = contratti.Where(x => x.Id! == idTipoContratto!).Select(x => x.Id).FirstOrDefault(); + if (idTipoContratto == null) + { + var msg = "I could not find the specified coontract!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + + categorie = await rs.Query(new SpedizioneQueryGetAllPersistence()); + confModuloCommessa = await rs.Query(new DatiConfigurazioneModuloCommessaQueryGetPersistence(idTipoContratto.Value, prodotto), ct); + + var statoCommessa = await rs.Query(new StatoCommessaQueryGetByDefaultPersistence(), ct); + stato = statoCommessa!.Stato; + } + + var commandTotale = command.GetTotali(categorie, confModuloCommessa, idEnte, annoAttuale, meseAttuale, idTipoContratto.Value, prodotto, stato); + + bool fatturabile = true; + foreach (var cmd in command.DatiModuloCommessaListCommand!) // validazione per id tipo spedizione + { + cmd.Stato = stato; + cmd.Prodotto = prodotto; + cmd.IdTipoContratto = idTipoContratto.Value; + cmd.AnnoValidita = annoAttuale; + cmd.MeseValidita = meseAttuale; + cmd.DataCreazione = adesso; + cmd.DataModifica = adesso; + fatturabile = cmd.Fatturabile; // segno fatturabile se passato + + var (error, errorDetails) = DatiModuloCommessaValidator.Validate(cmd); + if (!string.IsNullOrEmpty(error)) + throw new DomainException(_localizer[error, errorDetails]); + + cmd.ValoreNazionali = commandTotale.ParzialiTipoCommessa![cmd.IdTipoSpedizione].ValoreNazionali; + cmd.ValoreInternazionali = commandTotale.ParzialiTipoCommessa![cmd.IdTipoSpedizione].ValoreInternazionali; + cmd.PrezzoNazionali = commandTotale.ParzialiTipoCommessa![cmd.IdTipoSpedizione].PrezzoNazionali; + cmd.PrezzoInternazionali = commandTotale.ParzialiTipoCommessa![cmd.IdTipoSpedizione].PrezzoInternazionali; + } + + using var uow = await _factory.Create(true, cancellationToken: ct); + try + { + var rowAffected = await uow.Execute(new DatiModuloCommessaCreateCommandPersistence(command), ct); + if (rowAffected == command.DatiModuloCommessaListCommand!.Count) + { + commandTotale.DatiModuloCommessaTotaleListCommand!.ForEach(x => x.Fatturabile = fatturabile); + rowAffected = await uow.Execute(new DatiModuloCommessaCreateTotaleCommandPersistence(commandTotale), ct); + if (rowAffected == commandTotale.DatiModuloCommessaTotaleListCommand!.Count) + uow.Commit(); + else + { + uow.Rollback(); + throw new DomainException(_localizer["DatiModuloCommessaError", idEnte!]); + } + } + else + { + uow.Rollback(); + throw new DomainException(_localizer["DatiModuloCommessaError", idEnte!]); + } + } + catch (Exception e) + { + uow.Rollback(); + var methodName = nameof(DatiConfigurazioneModuloCommessaCreateCommandHandler); + _logger.LogError(e, "Errore nel salvataggio del modulo commessa: \"{MethodName}\" per tipo ente: \"{idEnte}\"", methodName, idEnte); + throw new DomainException(_localizer["DatiModuloCommessaError", idEnte!]); + } + + var datic = await uow.Query(new DatiModuloCommessaQueryGetByIdPersistence(idEnte, annoAttuale, meseAttuale, prodotto), ct); + var datit = await uow.Query(new DatiModuloCommessaTotaleQueryGetByIdPersistence(idEnte, annoAttuale, meseAttuale, prodotto), ct); + var moduloCommessa = new ModuloCommessaDto() + { + Modifica = valid && stato == StatoModuloCommessa.ApertaCaricato, + DatiModuloCommessa = datic!, + DatiModuloCommessaTotale = datit!, + Anno = datic!.Select(x=>x.AnnoValidita).FirstOrDefault(), + Mese = datic!.Select(x => x.MeseValidita).FirstOrDefault(), + DataModifica = adesso, + }; + + using var usto = await _factory.Create(cancellationToken: ct); + await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.DatiModuloCommessa, + moduloCommessa.Serialize())), ct); + + return moduloCommessa; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaCreateCommand.cs new file mode 100644 index 0000000..1f57a39 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaCreateCommand.cs @@ -0,0 +1,33 @@ +using MediatR; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class DatiConfigurazioneModuloCommessaCreateCommand : IRequest +{ + public List? Tipi { get; set; } + public List? Categorie { get; set; } +} + +public class DatiConfigurazioneModuloCommessaCreateTipoCommand +{ + public long IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public int IdTipoSpedizione { get; set; } + public decimal MediaNotificaNazionale { get; set; } + public decimal MediaNotificaInternazionale { get; set; } + public DateTime? DataCreazione { get; set; } + public DateTime DataInizioValidita { get; set; } + public string? Descrizione { get; set; } +} + +public class DatiConfigurazioneModuloCommessaCreateCategoriaCommand +{ + public long IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public int IdCategoriaSpedizione { get; set; } + public int Percentuale { get; set; } + public DateTime? DataCreazione { get; set; } + public DateTime DataInizioValidita { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaUpdateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaUpdateCommand.cs new file mode 100644 index 0000000..c3ed099 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiConfigurazioneModuloCommessaUpdateCommand.cs @@ -0,0 +1,31 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class DatiConfigurazioneModuloCommessaUpdateCommand : IRequest +{ + public DatiConfigurazioneModuloCommessaUpdateTipoCommand? Tipo { get; set; } + public DatiConfigurazioneModuloCommessaUpdateCategoriaCommand? Categoria { get; set; } +} + +public class DatiConfigurazioneModuloCommessaUpdateTipoCommand +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public long IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public DateTime DataInizioValidita { get; set; } + public DateTime DataFineValidita { get; set; } + public DateTime DataModifica { get; set; } +} + +public class DatiConfigurazioneModuloCommessaUpdateCategoriaCommand +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public long IdTipoContratto { get; set; } + public string? Prodotto { get; set; } + public DateTime DataInizioValidita { get; set; } + public DateTime DataFineValidita { get; set; } + public DateTime DataModifica { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateCommand.cs new file mode 100644 index 0000000..d31ed3d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateCommand.cs @@ -0,0 +1,26 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class DatiModuloCommessaCreateCommand : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public int NumeroNotificheNazionali { get; set; } + public int NumeroNotificheInternazionali { get; set; } + public DateTime DataCreazione { get; set; } + public DateTime DataModifica { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public string? IdEnte { get; set; } + public long IdTipoContratto { get; set; } + public string? Stato { get; set; } + public string? Prodotto { get; set; } + public int IdTipoSpedizione { get; set; } + public decimal ValoreNazionali { get; set; } + public decimal PrezzoNazionali { get; set; } + public decimal ValoreInternazionali { get; set; } + public decimal PrezzoInternazionali { get; set; } + public bool Fatturabile { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateListCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateListCommand.cs new file mode 100644 index 0000000..03cf381 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaCreateListCommand.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class DatiModuloCommessaCreateListCommand(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + + public List? DatiModuloCommessaListCommand { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateCommand.cs new file mode 100644 index 0000000..a6c002a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateCommand.cs @@ -0,0 +1,22 @@ +using System.Runtime.Serialization; +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class DatiModuloCommessaTotaleCreateCommand : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public string? IdEnte { get; set; } + public long IdTipoContratto { get; set; } + public string? Stato { get; set; } + public string? Prodotto { get; set; } + public int IdCategoriaSpedizione { get; set; } + public decimal TotaleCategoria { get; set; } + public int PercentualeCategoria { get; set; } + public decimal Totale { get; set; } + public bool Fatturabile { get; set; } = true; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateListCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateListCommand.cs new file mode 100644 index 0000000..a0ae001 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/DatiModuloCommessaTotaleCreateListCommand.cs @@ -0,0 +1,21 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class DatiModuloCommessaTotaleCreateListCommand : IRequest> +{ + public IAuthenticationInfo? AuthenticationInfo { get; set; } + + public List? DatiModuloCommessaTotaleListCommand { get; set; } + public Dictionary? ParzialiTipoCommessa { get; set; } +} + +public class ParzialiTipoCommessa() +{ + public decimal ValoreNazionali { get; set; } + public decimal PrezzoNazionali { get; set; } + public decimal ValoreInternazionali { get; set; } + public decimal PrezzoInternazionali { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaCreateCommandPersistence.cs new file mode 100644 index 0000000..3f38671 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaCreateCommandPersistence.cs @@ -0,0 +1,56 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands.Persistence; + +public class DatiConfigurazioneModuloCommessaCreateCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly DatiConfigurazioneModuloCommessaCreateCommand _command; + + public DatiConfigurazioneModuloCommessaCreateCommandPersistence(DatiConfigurazioneModuloCommessaCreateCommand command) + => _command = command; + + private static readonly string _sqlInsertTipo = @" +INSERT INTO [schema]costonotifiche + (MediaNotificaNazionale, + MediaNotificaInternazionale, + FkIdTipoSpedizione, + FkIdTipoContratto, + FkProdotto, + DataInizioValidita, + DataCreazione, + Descrizione) +VALUES (@medianotificanazionale, + @medianotificainternazionale, + @idtipospedizione, + @idtipocontratto, + @prodotto, + @datainiziovalidita, + @datacreazione, + @descrizione)"; + + private static readonly string _sqlInsertCategoria = @" +INSERT INTO [schema]percentualeanticipo + (fkprodotto, + fkidtipocontratto, + fkidcategoriaspedizione, + percentuale, + descrizione, + datainiziovalidita, + datacreazione) +VALUES (@prodotto, + @idtipocontratto, + @idcategoriaspedizione, + @percentuale, + @descrizione, + @datainiziovalidita, + @datacreazione); "; + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + + var resultTipi = await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsertTipo.Add(schema), _command.Tipi, transaction); + var resultCategorie = await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsertCategoria.Add(schema), _command.Categorie, transaction); + return resultTipi + resultCategorie; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaUpdateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaUpdateCommandPersistence.cs new file mode 100644 index 0000000..261b1c6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiConfigurazioneModuloCommessaUpdateCommandPersistence.cs @@ -0,0 +1,36 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands.Persistence; + +public class DatiConfigurazioneModuloCommessaUpdateCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly DatiConfigurazioneModuloCommessaUpdateCommand _command; + + public DatiConfigurazioneModuloCommessaUpdateCommandPersistence(DatiConfigurazioneModuloCommessaUpdateCommand command) + => _command = command; + + private static readonly string _sqlUpdateTipo = @" +UPDATE [schema]costonotifiche +SET datafinevalidita = @dataFineValidita, + datamodifica = @dataModifica +WHERE fkprodotto=@prodotto + AND fkidtipocontratto=@idtipocontratto + AND datainiziovalidita=@datainiziovalidita + AND datafinevalidita IS NULL"; + private static readonly string _sqlUpdateCategoria = @" +UPDATE [schema]percentualeanticipo +SET datafinevalidita = @dataFineValidita, + datamodifica = @dataModifica +WHERE fkprodotto=@prodotto + AND fkidtipocontratto=@idtipocontratto + AND datainiziovalidita=@datainiziovalidita + AND datafinevalidita IS NULL"; + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var resultTipi = await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdateTipo.Add(schema), _command.Tipo, transaction); + var resultCategorie = await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdateCategoria.Add(schema), _command.Categoria, transaction); + return resultTipi + resultCategorie; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateCommandPersistence.cs new file mode 100644 index 0000000..863b5db --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateCommandPersistence.cs @@ -0,0 +1,91 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands.Persistence; + +public class DatiModuloCommessaCreateCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly DatiModuloCommessaCreateListCommand _command; + public DatiModuloCommessaCreateCommandPersistence(DatiModuloCommessaCreateListCommand command) + => _command = command; + + private static readonly string _sqlInsertUpdate = @" +MERGE +INTO [schema]datimodulocommessa as dm +using (VALUES + ( + @numeronotifichenazionali, + @numeronotificheinternazionali, + @datamodifica, + @idente, + @IdTipoContratto, + @Prodotto, + @IdTipoSpedizione, + @annovalidita, + @mesevalidita, + @datacreazione, + @stato, + @valoreNazionali, + @prezzoNazionali, + @valoreInternazionali, + @prezzoInternazionali + ) + ) AS source (numeronotifichenazionali, numeronotificheinternazionali, datamodifica, idente, idtipocontratto, prodotto, idtipospedizione, annovalidita, mesevalidita, datacreazione, stato, valoreNazionali, prezzoNazionali, valoreInternazionali, prezzoInternazionali) +ON dm.fkidente = source.idente +AND dm.fkidtipocontratto = source.idtipocontratto +AND dm.fkprodotto = source.prodotto +AND dm.fkidtipospedizione = source.idtipospedizione +AND dm.annovalidita = source.annovalidita +AND dm.mesevalidita = source.mesevalidita +WHEN matched THEN +UPDATE +SET numeronotifichenazionali = source.numeronotifichenazionali, + numeronotificheinternazionali = source.numeronotificheinternazionali, + datamodifica = source.datamodifica, + valoreNazionali = source.valoreNazionali, + prezzoNazionali = source.prezzoNazionali, + valoreInternazionali = source.valoreInternazionali, + prezzoInternazionali = source.prezzoInternazionali +WHEN NOT matched THEN +INSERT + ( + numeronotifichenazionali, + numeronotificheinternazionali, + datacreazione, + fkidente, + fkidtipocontratto, + fkidstato, + fkprodotto, + fkidtipospedizione, + annovalidita, + mesevalidita, + valoreNazionali, + prezzoNazionali, + valoreInternazionali, + prezzoInternazionali + ) + VALUES + ( + source.numeronotifichenazionali, + source.numeronotificheinternazionali, + source.datacreazione, + source.idente, + source.idtipocontratto, + source.stato, + source.prodotto, + source.idtipospedizione, + source.annovalidita, + source.mesevalidita, + source.valoreNazionali, + source.prezzoNazionali, + source.valoreInternazionali, + source.prezzoInternazionali + ); +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsertUpdate.Add(schema), _command.DatiModuloCommessaListCommand, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateTotaleCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateTotaleCommandPersistence.cs new file mode 100644 index 0000000..94a1d95 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Commands/Persistence/DatiModuloCommessaCreateTotaleCommandPersistence.cs @@ -0,0 +1,78 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands.Persistence; + +public class DatiModuloCommessaCreateTotaleCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly DatiModuloCommessaTotaleCreateListCommand _command; + public DatiModuloCommessaCreateTotaleCommandPersistence(DatiModuloCommessaTotaleCreateListCommand command) + => _command = command; + + private static readonly string _sqlInsertUpdate = @" +MERGE +INTO [schema]DatiModuloCommessaTotali as dm +using (VALUES + ( + @idente, + @IdTipoContratto, + @Prodotto, + @idCategoriaSpedizione, + @annovalidita, + @mesevalidita, + @TotaleCategoria, + @stato, + @percentualeCategoria, + @totale, + @fatturabile + ) + ) AS source (idente, idtipocontratto, prodotto, idCategoriaSpedizione, annovalidita, mesevalidita, totaleCategoria, stato, percentualeCategoria, totale, fatturabile) +ON dm.fkidente = source.idente +AND dm.fkidtipocontratto = source.idtipocontratto +AND dm.fkprodotto = source.prodotto +AND dm.fkIdCategoriaSpedizione = source.idCategoriaSpedizione +AND dm.annovalidita = source.annovalidita +AND dm.mesevalidita = source.mesevalidita +WHEN matched THEN +UPDATE +SET totaleCategoria = source.totaleCategoria, + percentualeCategoria = source.percentualeCategoria, + totale =source.totale, + fatturabile = source.fatturabile +WHEN NOT matched THEN +INSERT + ( + fkidente, + fkidtipocontratto, + fkidstato, + fkprodotto, + fkIdCategoriaSpedizione, + annovalidita, + mesevalidita, + totaleCategoria, + percentualeCategoria, + totale, + fatturabile + ) + VALUES + ( + source.idente, + source.idtipocontratto, + source.stato, + source.prodotto, + source.idCategoriaSpedizione, + source.annovalidita, + source.mesevalidita, + source.totaleCategoria, + source.percentualeCategoria, + source.totale, + 1 + ); +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsertUpdate.Add(schema), _command.DatiModuloCommessaTotaleListCommand, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiConfigurazioneModuloCommessaValidator.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiConfigurazioneModuloCommessaValidator.cs new file mode 100644 index 0000000..c9e5a4e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiConfigurazioneModuloCommessaValidator.cs @@ -0,0 +1,83 @@ +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse; + +public static class DatiConfigurazioneModuloCommessaValidator +{ + public static (string, string[]) ValidateCategorieConfiguazione(this IEnumerable model, DatiConfigurazioneModuloCommessaCreateCommand command) + { + var dataCreazione = DateTime.UtcNow.ItalianTime(); + if (model.IsNullNotAny() || command == null || command.Tipi!.IsNullNotAny() || command.Categorie!.IsNullNotAny()) + return ("DatiConfigurazioneModuloCommessaInvalid", Array.Empty()); + + foreach (var cat in model) + { + var foundCat = command.Categorie!.Where(x => x.IdCategoriaSpedizione == cat.Id).FirstOrDefault(); + if (foundCat == null) + return ("DatiConfigurazioneModuloCommessaInvalid", Array.Empty()); + foundCat.Descrizione = cat.Descrizione; + foundCat.DataCreazione = dataCreazione; + foundCat.DataInizioValidita = dataCreazione; + foreach (var tp in cat.TipoSpedizione!) + { + var foundTipo = command.Tipi!.Where(x => x.IdTipoSpedizione == tp.Id).FirstOrDefault(); + if (foundTipo == null) + return ("DatiConfigurazioneModuloCommessaInvalid", Array.Empty()); + foundTipo.Descrizione = tp.Descrizione; + foundTipo.DataCreazione = dataCreazione; + foundTipo.DataInizioValidita = dataCreazione; + } + } + if (model.Count() != command.Categorie!.Count() || model.SelectMany(x => x.TipoSpedizione!).Count() != command.Tipi!.Count()) + return ("DatiConfigurazioneModuloCommessaInvalid", Array.Empty()); + + return (null, null)!; + } + + public static (string, string[]) ValidateTipo(DatiConfigurazioneModuloCommessaCreateTipoCommand cmd) + { + return ValidateTipo( + cmd.MediaNotificaInternazionale, + cmd.MediaNotificaNazionale, + cmd.Descrizione); + } + + public static (string, string[]) ValidateCategoria(DatiConfigurazioneModuloCommessaCreateCategoriaCommand cmd) + { + return ValidateCategoria( + cmd.Percentuale, + cmd.Descrizione); + } + + private static (string, string[]) ValidateTipo( + decimal? mediaNotificaInternazionale, + decimal? mediaNotificaNazionale, + string? descrizione) + { + if (!mediaNotificaInternazionale.HasValue || mediaNotificaInternazionale.Value < 0) + return ("MediaNotificaInternazionaleInvalid", Array.Empty()); + + if (!mediaNotificaNazionale.HasValue || mediaNotificaNazionale.Value < 0) + return ("MediaNotificaNazionaleInvalid", Array.Empty()); + + if (!string.IsNullOrEmpty(descrizione) && descrizione!.Length > 250) + return ("DescrizioneConfiguazioneModuloCommessaInvalid", Array.Empty()); + + return (null, null)!; + } + + private static (string, string[]) ValidateCategoria( + int? percentuale, + string? descrizione) + { + if (percentuale < 0) + return ("PercentoConfiguazioneModuloCommessaInvalid", Array.Empty()); + + if (!string.IsNullOrEmpty(descrizione) && descrizione.Length > 250) + return ("DescrizioneConfiguazioneModuloCommessaInvalid", Array.Empty()); + + return (null, null)!; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaExtensions.cs new file mode 100644 index 0000000..1b6a433 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaExtensions.cs @@ -0,0 +1,121 @@ +using System.Security.Cryptography; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse; + +public static class DatiModuloCommessaExtensions +{ + internal static string Map(this long idTipoContratto) + { + if (idTipoContratto == 1) + return "PAL"; + else if (idTipoContratto == 2) + return "PAC"; + return string.Empty; + } + + public static DatiModuloCommessaTotaleCreateListCommand GetTotali( + this DatiModuloCommessaCreateListCommand command, + IEnumerable? categorie, + DatiConfigurazioneModuloCommessa? confModuloCommessa, + string? idEnte, + int anno, + int mese, + long idTipoContratto, + string? prodotto, + string? stato) + { + DatiModuloCommessaTotaleCreateListCommand tCommand = new(); + + var categorieTotale = categorie! + .Select(x => new KeyValuePair(x.Id, 0M)) + .ToDictionary(x => x.Key, x => x.Value); + + var categoriePercentuali = confModuloCommessa!.Categorie! + .Select(x => new KeyValuePair(x.IdCategoriaSpedizione, x.Percentuale)) + .ToDictionary(x => x.Key, x => x.Value); + + var tipiSpedizionePrezziInter = confModuloCommessa!.Tipi! + .Select(x => new KeyValuePair(x.IdTipoSpedizione, x.MediaNotificaInternazionale)) + .ToDictionary(x => x.Key, x => x.Value); + + var tipiSpedizionePrezziNaz = confModuloCommessa!.Tipi! + .Select(x => new KeyValuePair(x.IdTipoSpedizione, x.MediaNotificaNazionale)) + .ToDictionary(x => x.Key, x => x.Value); + + var numeroTotaleNotifiche = command.DatiModuloCommessaListCommand!.Select(x => x.NumeroNotificheNazionali + x.NumeroNotificheInternazionali).Sum(); + Dictionary? parzialiTipoCommessa = []; + foreach (var cmd in command.DatiModuloCommessaListCommand!) // per id tipo spedizione + { + + var idCategoria = categorie!.SelectMany(x => x.TipoSpedizione!).Where(x => x.Id == cmd.IdTipoSpedizione).FirstOrDefault()!.IdCategoriaSpedizione; + + var fNotifica = categorieTotale.TryGetValue(idCategoria, out decimal totale); + var fprezzoInter = tipiSpedizionePrezziInter.TryGetValue(cmd.IdTipoSpedizione, out decimal prezzoInter); + var fprezzoNaz = tipiSpedizionePrezziNaz.TryGetValue(cmd.IdTipoSpedizione, out decimal prezzoNaz); + + var categoriaDigitale = categorie!.Where(x => x.Tipo!.Contains("digitale", StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault(); // seleziono digitale + + var isCategoriaDigitale = categoriaDigitale!.Id == idCategoria; + + + decimal prezzo; + + if (isCategoriaDigitale) + { + parzialiTipoCommessa.TryAdd(cmd.IdTipoSpedizione, new ParzialiTipoCommessa() + { + PrezzoInternazionali = prezzoInter, + PrezzoNazionali = prezzoNaz, + ValoreInternazionali = prezzoInter * cmd.NumeroNotificheInternazionali, + ValoreNazionali = prezzoNaz * cmd.NumeroNotificheNazionali + }); + + categorieTotale[idCategoria] = prezzoNaz * numeroTotaleNotifiche; + } + else // analogico + { + parzialiTipoCommessa.TryAdd(cmd.IdTipoSpedizione, new ParzialiTipoCommessa() + { + PrezzoInternazionali = prezzoInter, + PrezzoNazionali = prezzoNaz, + ValoreInternazionali = cmd.NumeroNotificheInternazionali * prezzoInter, + ValoreNazionali = cmd.NumeroNotificheNazionali * prezzoNaz, + }); ; + + prezzo = cmd.NumeroNotificheInternazionali * prezzoInter + cmd.NumeroNotificheNazionali * prezzoNaz; + + if (fNotifica) + categorieTotale[idCategoria] += prezzo; + else + categorieTotale.Add(idCategoria, prezzo); + } + } + + + tCommand.DatiModuloCommessaTotaleListCommand = []; + foreach (var keyValue in categorieTotale) + { + var fpercent = categoriePercentuali.TryGetValue(keyValue.Key, out int percent); + var apercent = (keyValue.Value / 100M) * percent; + tCommand.DatiModuloCommessaTotaleListCommand.Add(new DatiModuloCommessaTotaleCreateCommand() + { + IdCategoriaSpedizione = keyValue.Key, + IdEnte = idEnte, + AnnoValidita = anno, + MeseValidita = mese, + IdTipoContratto = idTipoContratto, + Prodotto = prodotto, + Stato = stato, + TotaleCategoria = apercent, + PercentualeCategoria = percent, + Totale = keyValue.Value + }); + } + + tCommand.ParzialiTipoCommessa = parzialiTipoCommessa; + return tCommand; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaMapper.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaMapper.cs new file mode 100644 index 0000000..9afdc28 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaMapper.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse; + +public static class DatiModuloCommessaMapper +{ + + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaValidator.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaValidator.cs new file mode 100644 index 0000000..c0048e5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/DatiModuloCommessaValidator.cs @@ -0,0 +1,46 @@ +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse; + +public static class DatiModuloCommessaValidator +{ + + public static (string, string[]) Validate(DatiModuloCommessaCreateCommand cmd) + { + return Validate( + cmd.NumeroNotificheNazionali, + cmd.NumeroNotificheInternazionali, + cmd.AnnoValidita, + cmd.MeseValidita, + cmd.Stato + ); + } + + private static (string, string[]) Validate( + int? numeroNotificheNazionali, + int? numeroNotificheInternazionali, + int? annoValidita, + int? meseValidita, + string? stato) + { + var (annoFatturazione, meseFatturazione, _, _) = Time.YearMonthDayFatturazione(); + + if (numeroNotificheNazionali == null || numeroNotificheNazionali < 0) + return ("DatiModuloCommessaInvalid", Array.Empty()); + + if (numeroNotificheInternazionali == null || numeroNotificheInternazionali < 0) + return ("DatiModuloCommessaInvalid", Array.Empty()); + + if (annoValidita == null || annoValidita != annoFatturazione) + return ("DatiModuloCommessaDataInvalid", Array.Empty()); + + if (meseValidita == null || meseValidita != meseFatturazione) + return ("DatiModuloCommessaDataInvalid", Array.Empty()); + + if (string.IsNullOrEmpty(stato)) + return ("DatiModuloCommessaStatoInvalid", Array.Empty()); + + return (null, null)!; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Dto/ModuloCommessaByRicercaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Dto/ModuloCommessaByRicercaDto.cs new file mode 100644 index 0000000..48ff94c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Dto/ModuloCommessaByRicercaDto.cs @@ -0,0 +1,121 @@ +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Dto; + +public sealed class ModuloCommessaByRicercaDto +{ + [Column("Description")] + [JsonPropertyOrder(-6)] + public string? Key + { + get + { + return $"{IdEnte}_{Prodotto}_{Anno}_{Mese}"; + } + } + + [Column("FkIdEnte")] + [HeaderAttribute(caption: "identificativo SC", Order = 1)] + public string? IdEnte { get; set; } + + [HeaderAttribute(caption: "ragione sociale ente", Order = 2)] + [Column("description")] + public string? RagioneSociale { get; set; } + + [HeaderAttribute(caption: "codice fiscale", Order = 3)] + [Column("vatnumber")] + public string? CodiceFiscale { get; set; } + + [HeaderAttribute(caption: "prodotto", Order = 4)] + [Column("FkProdotto")] + public string? Prodotto { get; set; } + + [HeaderAttribute(caption: "Tipo Spedizione", Order = 5)] + [Column("TipoSpedizione")] + public string? TipoSpedizioneDigitale { get; set; } + + + [HeaderAttribute(caption: "N. Notifiche NZ", Order = 6)] + + [Column("NumeroNotificheNazionali")] + public int NumeroNotificheNazionaliDigitale { get; set; } + + + [HeaderAttribute(caption: "N. Notifiche INT", Order = 7)] + + [Column("NumeroNotificheInternazionali")] + public int NumeroNotificheInternazionaliDigitale { get; set; } + + + [HeaderAttribute(caption: "Tipo Spedizione", Order = 8)] + + [Column("TipoSpedizione")] + public string? TipoSpedizioneAnalogicoAR { get; set; } + + [HeaderAttribute(caption: "N. Notifiche NZ", Order = 9)] + [Column("NumeroNotificheNazionali")] + public int NumeroNotificheNazionaliAnalogicoAR { get; set; } + + [HeaderAttribute(caption: "N. Notifiche INT", Order = 10)] + [Column("NumeroNotificheInternazionali")] + public int NumeroNotificheInternazionaliAnalogicoAR { get; set; } + + [HeaderAttribute(caption: "Tipo Spedizione", Order = 11)] + [Column("TipoSpedizione")] + public string? TipoSpedizioneAnalogico890 { get; set; } + + [HeaderAttribute(caption: "N. Notifiche NZ", Order = 12)] + [Column("NumeroNotificheNazionali")] + public int NumeroNotificheNazionaliAnalogico890 { get; set; } + + [HeaderAttribute(caption: "N. Notifiche INT", Order = 13)] + [Column("NumeroNotificheInternazionali")] + public int NumeroNotificheInternazionaliAnalogico890 { get; set; } + + [HeaderAttribute(caption: "Totale Spedizioni Analogiche", Order = 14)] + [Column("TotaleCategoria")] + public decimal TotaleCategoriaAnalogico { get; set; } + + [HeaderAttribute(caption: "Totale Spedizioni Digitali", Order = 15)] + [Column("TotaleCategoria")] + public decimal TotaleCategoriaDigitale { get; set; } + + [HeaderAttribute(caption: "Anno", Order = 16)] + [Column("Anno")] + public int Anno { get; set; } + + [HeaderAttribute(caption: "Mese", Order = 17)] + [JsonIgnore] + public string? SMese { get { return Mese.GetMonth(); } } + + [Column("Mese")] + public int Mese { get; set; } + + [HeaderAttribute(caption: "Totale Analogiche Lordo", Order = 18)] + [Column("Totale")] + public decimal TotaleAnalogicoLordo { get; set; } + + [HeaderAttribute(caption: "Totale Digitali Lordo", Order = 18)] + [Column("Totale")] + public decimal TotaleDigitaleLordo { get; set; } + + [HeaderAttribute(caption: "Totale Lordo", Order = 19)] + [Column("Totale")] + public decimal TotaleLordo { get; set; } + + [HeaderAttribute(caption: "tipo contratto", Order = 20)] + [JsonIgnore] + public string? SIdTipoContratto { get { return IdTipoContratto.Map(); } } + + [Column("IdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("Stato")] + [HeaderAttribute(caption: "Stato", Order = 21)] + public string? Stato { get; set; } +} + + diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiConfigurazioneModuloCommessaQueryGet.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiConfigurazioneModuloCommessaQueryGet.cs new file mode 100644 index 0000000..24c22fa --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiConfigurazioneModuloCommessaQueryGet.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; + +public class DatiConfigurazioneModuloCommessaQueryGet : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } + public string? Prodotto { get; set; } + public long IdTipoContratto { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaDocumentoQueryGet.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaDocumentoQueryGet.cs new file mode 100644 index 0000000..d8c7bf5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaDocumentoQueryGet.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +public class DatiModuloCommessaDocumentoQueryGet(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaGetAnni.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaGetAnni.cs new file mode 100644 index 0000000..072d6de --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaGetAnni.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; + +public class DatiModuloCommessaGetAnni(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaParzialiQueryGetByAnno.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaParzialiQueryGetByAnno.cs new file mode 100644 index 0000000..b9342cb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaParzialiQueryGetByAnno.cs @@ -0,0 +1,15 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; + +public class DatiModuloCommessaParzialiQueryGetByAnno : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } + public DatiModuloCommessaParzialiQueryGetByAnno(IAuthenticationInfo authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } + public int? AnnoValidita { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGet.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGet.cs new file mode 100644 index 0000000..e3702a0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGet.cs @@ -0,0 +1,16 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +public class DatiModuloCommessaQueryGet : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } + public DatiModuloCommessaQueryGet(IAuthenticationInfo authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } + public string? Prodotto { get; set; } + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByAnno.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByAnno.cs new file mode 100644 index 0000000..7b82486 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByAnno.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +public class DatiModuloCommessaQueryGetByAnno(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByDescrizione.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByDescrizione.cs new file mode 100644 index 0000000..86c8105 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaQueryGetByDescrizione.cs @@ -0,0 +1,13 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +public class DatiModuloCommessaQueryGetByDescrizione(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } + public string? Prodotto { get; set; } + public string[]? IdEnti { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaTotaleQueryGet.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaTotaleQueryGet.cs new file mode 100644 index 0000000..9c92b49 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/DatiModuloCommessaTotaleQueryGet.cs @@ -0,0 +1,15 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +public class DatiModuloCommessaTotaleQueryGet : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } + public DatiModuloCommessaTotaleQueryGet(IAuthenticationInfo authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiConfigurazioneModuloCommessaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiConfigurazioneModuloCommessaSQLBuilder.cs new file mode 100644 index 0000000..231a535 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiConfigurazioneModuloCommessaSQLBuilder.cs @@ -0,0 +1,87 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; + +public class DatiConfigurazioneModuloCommessaSQLBuilder +{ + private static string OrderByDataInizioValidita() + { + DatiConfigurazioneModuloTipoCommessa? obj; + var fieldDataInizioValidita = nameof(@obj.DataInizioValidita); + return $"{fieldDataInizioValidita}"; + } + + private static string WhereByTipo() + { + DatiConfigurazioneModuloTipoCommessa? obj; + var fieldProdotto = nameof(@obj.Prodotto).GetColumn(); + var fieldTipoContratto = nameof(@obj.IdTipoContratto).GetColumn(); + return $"{fieldTipoContratto} = @{nameof(@obj.IdTipoContratto)} AND {fieldProdotto} = @{nameof(@obj.Prodotto)} AND {nameof(@obj.DataFineValidita)} IS NULL"; + } + + private static string WhereByCategoria() + { + DatiConfigurazioneModuloCategoriaCommessa? obj; + var fieldProdotto = nameof(@obj.Prodotto).GetColumn(); + var fieldTipoContratto = nameof(@obj.IdTipoContratto).GetColumn(); + return $"{fieldTipoContratto} = @{nameof(@obj.IdTipoContratto)} AND {fieldProdotto} = @{nameof(@obj.Prodotto)} AND {nameof(@obj.DataFineValidita)} IS NULL"; + } + + private static SqlBuilder CreateSelectTipo() + { + DatiConfigurazioneModuloTipoCommessa? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdTipoContratto).GetAsColumn()); + builder.Select(nameof(@obj.Prodotto).GetAsColumn()); + builder.Select(nameof(@obj.IdTipoSpedizione).GetAsColumn()); + builder.Select(nameof(@obj.MediaNotificaNazionale)); + builder.Select(nameof(@obj.MediaNotificaInternazionale)); + builder.Select(nameof(@obj.DataCreazione)); + builder.Select(nameof(@obj.DataModifica)); + builder.Select(nameof(@obj.DataInizioValidita)); + builder.Select(nameof(@obj.DataFineValidita)); + builder.Select(nameof(@obj.Descrizione)); + return builder; + } + + public static string SelectTipoBy() + { + var tableName = nameof(DatiConfigurazioneModuloTipoCommessa); + tableName = tableName.GetTable(); + var builder = CreateSelectTipo(); + var where = WhereByTipo(); + builder.Where(where); + builder.OrderBy($"{OrderByDataInizioValidita()} DESC"); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ /**orderby**/"); + return builderTemplate.RawSql; + } + + public static string SelectCategoriaBy() + { + var tableName = nameof(DatiConfigurazioneModuloCategoriaCommessa); + tableName = tableName.GetTable(); + var builder = CreateSelectCategoria(); + var where = WhereByCategoria(); + builder.Where(where); + builder.OrderBy($"{OrderByDataInizioValidita()} DESC"); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ /**orderby**/"); + return builderTemplate.RawSql; + } + private static SqlBuilder CreateSelectCategoria() + { + DatiConfigurazioneModuloCategoriaCommessa? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdTipoContratto).GetAsColumn()); + builder.Select(nameof(@obj.Prodotto).GetAsColumn()); + builder.Select(nameof(@obj.IdCategoriaSpedizione).GetAsColumn()); + builder.Select(nameof(@obj.Percentuale)); + builder.Select(nameof(@obj.DataCreazione)); + builder.Select(nameof(@obj.DataModifica)); + builder.Select(nameof(@obj.DataInizioValidita)); + builder.Select(nameof(@obj.DataFineValidita)); + builder.Select(nameof(@obj.Descrizione)); + return builder; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaAnniSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaAnniSQLBuilder.cs new file mode 100644 index 0000000..d671a40 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaAnniSQLBuilder.cs @@ -0,0 +1,38 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; + +public class DatiModuloCommessaAnniSQLBuilder +{ + private static string WhereById() + { + DatiModuloCommessaTotale? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldProdotto = nameof(@obj.Prodotto).GetColumn(); + + return String.Join(" AND ", + $"{fieldIdEnte} = @{nameof(@obj.IdEnte)}", + $"{fieldProdotto} = @{nameof(@obj.Prodotto)}"); + } + + private static SqlBuilder CreateSelect() + { + DatiModuloCommessaTotale? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.AnnoValidita)); + return builder; + } + + public static string SelectBy() + { + var tableName = nameof(DatiModuloCommessaTotale); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select DISTINCT(/**select**/) from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaSQLBuilder.cs new file mode 100644 index 0000000..c4ea724 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaSQLBuilder.cs @@ -0,0 +1,128 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; + +public class DatiModuloCommessaSQLBuilder +{ + private static string WhereById() + { + DatiModuloCommessa? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldAnno = nameof(@obj.AnnoValidita); + var fieldMese = nameof(@obj.MeseValidita); + var prodotto = nameof(@obj.Prodotto).GetColumn(); + return $"{fieldIdEnte} = @{nameof(@obj.IdEnte)} AND {fieldAnno} = @{nameof(@obj.AnnoValidita)} AND {fieldMese} = @{nameof(@obj.MeseValidita)} AND {prodotto} = @{nameof(@obj.Prodotto)}"; + } + + private static string WhereByAnno() + { + DatiModuloCommessa? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldAnno = nameof(@obj.AnnoValidita); + var prodotto = nameof(@obj.Prodotto).GetColumn(); + return $"{fieldIdEnte} = @{nameof(@obj.IdEnte)} AND {fieldAnno} = @{nameof(@obj.AnnoValidita)} AND {prodotto} = @{nameof(@obj.Prodotto)}"; + } + + private static SqlBuilder CreateSelect() + { + DatiModuloCommessa? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdTipoContratto).GetAsColumn()); + builder.Select(nameof(@obj.Prodotto).GetAsColumn()); + builder.Select(nameof(@obj.IdTipoSpedizione).GetAsColumn()); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.MeseValidita)); + builder.Select(nameof(@obj.DataCreazione)); + builder.Select(nameof(@obj.DataModifica)); + builder.Select(nameof(@obj.AnnoValidita)); + builder.Select(nameof(@obj.NumeroNotificheInternazionali)); + builder.Select(nameof(@obj.NumeroNotificheNazionali)); + builder.Select(nameof(@obj.Stato).GetAsColumn()); + builder.Select(nameof(@obj.ValoreNazionali)); + builder.Select(nameof(@obj.PrezzoNazionali)); + builder.Select(nameof(@obj.ValoreInternazionali)); + builder.Select(nameof(@obj.PrezzoInternazionali)); + return builder; + } + + private static SqlBuilder CreateSelectDate() + { + DatiModuloCommessa? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.MeseValidita)); + builder.Select(nameof(@obj.DataCreazione)); + builder.Select(nameof(@obj.DataModifica)); + return builder; + } + + public static string SelectByRicerca() + { + return $@" +SELECT + [IdEnte] + ,[RagioneSociale] + ,[CodiceFiscale] + ,[Prodotto] + ,[TipoSpedizioneDigitale] + ,[NumeroNotificheNazionaliDigitale] + ,[NumeroNotificheInternazionaliDigitale] + ,[TipoSpedizioneAnalogicoAR] + ,[NumeroNotificheNazionaliAnalogicoAR] + ,[NumeroNotificheInternazionaliAnalogicoAR] + ,[TipoSpedizioneAnalogico890] + ,[NumeroNotificheNazionaliAnalogico890] + ,[NumeroNotificheInternazionaliAnalogico890] + ,[TotaleCategoriaAnalogico] + ,[TotaleCategoriaDigitale] + ,[Anno] + ,[Mese] + ,[TotaleAnalogicoLordo] + ,[TotaleDigitaleLordo] + ,[TotaleLordo] + ,[IdTipoContratto] + ,[Stato] +FROM pfd.vModuliCommessa +WHERE Anno = @Anno and Mese = @Mese"; + } + + + public static string SelectBy() + { + var tableName = nameof(DatiModuloCommessa); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectByDate() + { + var tableName = nameof(DatiModuloCommessa); + var builder = CreateSelectDate(); + var where = WhereByAnno(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectByAnno() + { + var tableName = nameof(DatiModuloCommessa); + var builder = CreateSelect(); + var where = WhereByAnno(); + builder.Where(where); + builder.OrderBy($"{OrderByMeseValidita()} DESC"); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ /**orderby**/"); + return builderTemplate.RawSql; + } + + private static string OrderByMeseValidita() + { + DatiModuloCommessa? obj; + var fieldMeseValidita = nameof(@obj.MeseValidita); + return $"{fieldMeseValidita}"; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaTotaleSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaTotaleSQLBuilder.cs new file mode 100644 index 0000000..8c3898f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/Builder/DatiModuloCommessaTotaleSQLBuilder.cs @@ -0,0 +1,80 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; + +public class DatiModuloCommessaTotaleSQLBuilder +{ + private static string WhereByAnno() + { + DatiModuloCommessaTotale? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldAnno = nameof(@obj.AnnoValidita); + var fieldProdotto = nameof(@obj.Prodotto).GetColumn(); + return String.Join(" AND ", + $"{fieldIdEnte} = @{nameof(@obj.IdEnte)}", + $"{fieldAnno} = @{nameof(@obj.AnnoValidita)}", + $"{fieldProdotto} = @{nameof(@obj.Prodotto)}"); + } + private static string WhereById() + { + DatiModuloCommessaTotale? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldAnno = nameof(@obj.AnnoValidita); + var fieldMese = nameof(@obj.MeseValidita); + var fieldProdotto = nameof(@obj.Prodotto).GetColumn(); + return String.Join(" AND ", + $"{fieldIdEnte} = @{nameof(@obj.IdEnte)}", + $"{fieldAnno} = @{ nameof(@obj.AnnoValidita)}", + $"{fieldMese} = @{nameof(@obj.MeseValidita)}", + $"{fieldProdotto} = @{nameof(@obj.Prodotto)}"); + } + + private static SqlBuilder CreateSelect() + { + DatiModuloCommessaTotale? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdTipoContratto).GetAsColumn()); + builder.Select(nameof(@obj.Prodotto).GetAsColumn()); + builder.Select(nameof(@obj.IdCategoriaSpedizione).GetAsColumn()); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.Stato).GetAsColumn()); + builder.Select(nameof(@obj.MeseValidita)); + builder.Select(nameof(@obj.AnnoValidita)); + builder.Select(nameof(@obj.TotaleCategoria)); + builder.Select(nameof(@obj.PercentualeCategoria)); + builder.Select(nameof(@obj.Totale)); + return builder; + } + + public static string SelectBy() + { + var tableName = nameof(DatiModuloCommessaTotale); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectByAnno() + { + var tableName = nameof(DatiModuloCommessaTotale); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereByAnno(); + builder.Where(where); + builder.OrderBy($"{OrderByMeseValidita()} DESC"); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ /**orderby**/"); + return builderTemplate.RawSql; + } + + private static string OrderByMeseValidita() + { + DatiModuloCommessaTotale? obj; + var fieldMeseValidita = nameof(@obj.MeseValidita); + return $"{fieldMeseValidita}"; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiConfigurazioneModuloCommessaQueryGetPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiConfigurazioneModuloCommessaQueryGetPersistence.cs new file mode 100644 index 0000000..b396398 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiConfigurazioneModuloCommessaQueryGetPersistence.cs @@ -0,0 +1,40 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiConfigurazioneModuloCommessaQueryGetPersistence : DapperBase, IQuery +{ + private readonly string? _prodotto; + private readonly long _idTipoContratto; + private static readonly string _sqlSelect = String.Join(";", DatiConfigurazioneModuloCommessaSQLBuilder.SelectTipoBy(), DatiConfigurazioneModuloCommessaSQLBuilder.SelectCategoriaBy()); + public DatiConfigurazioneModuloCommessaQueryGetPersistence(long idTipoContratto, string? prodotto) + { + this._idTipoContratto = idTipoContratto; + this._prodotto = prodotto; + } + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + var values = await ((IDatabase)this).QueryMultipleAsync(connection!, _sqlSelect.Add(schema), + new + { + prodotto = _prodotto, + idTipoContratto = _idTipoContratto + }, transaction); + + if (values == null) + return null; + var tipi = await values.ReadAsync(); + var categorie = await values.ReadAsync(); + if (tipi.Any() && categorie.Any()) + return new DatiConfigurazioneModuloCommessa() + { + Tipi = tipi, + Categorie = categorie + }; + return null; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaDateQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaDateQueryGetByIdPersistence.cs new file mode 100644 index 0000000..8eaaffa --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaDateQueryGetByIdPersistence.cs @@ -0,0 +1,35 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaDateQueryGetByIdPersistence : DapperBase, IQuery?> +{ + private readonly string? _prodotto; + private readonly long? _idTipoContratto; + private readonly int _annoValidita; + private readonly string? _idEnte; + private static readonly string _sqlSelect = DatiModuloCommessaSQLBuilder.SelectByDate(); + + public DatiModuloCommessaDateQueryGetByIdPersistence(string? idEnte, int annoValidita, long? idTipoContratto, string? prodotto) + { + this._idTipoContratto = idTipoContratto; + this._prodotto = prodotto; + this._annoValidita = annoValidita; + this._idEnte = idEnte; + } + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new + { + idEnte = _idEnte, + annoValidita = _annoValidita, + prodotto = _prodotto, + idTipoContratto = _idTipoContratto + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence.cs new file mode 100644 index 0000000..011897f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence.cs @@ -0,0 +1,73 @@ +using System.Data; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence : DapperBase, IQuery?> +{ + private readonly string? _prodotto; + private readonly long? _idTipoContratto; + private readonly int _annoValidita; + private readonly string? _idEnte; + private readonly string? _ruolo; + private static readonly string _sqlSelect = String.Join(";", DatiModuloCommessaTotaleSQLBuilder.SelectByAnno(), DatiModuloCommessaSQLBuilder.SelectByAnno()); + + public DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence(string? idEnte, int annoValidita,string? prodotto, string? ruolo) + { + this._prodotto = prodotto; + this._annoValidita = annoValidita; + this._idEnte = idEnte; + this._ruolo = ruolo; + } + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + var parziali = new Dictionary(); + var values = await ((IDatabase)this).QueryMultipleAsync(connection!, _sqlSelect.Add(schema), + new + { + idEnte = _idEnte, + annoValidita = _annoValidita, + prodotto = _prodotto, + }, transaction); + + var totalePerCategoria = await values.ReadAsync(); + var moduliCommessa = await values.ReadAsync(); + foreach (var tot in totalePerCategoria) + { + parziali.TryGetValue(tot.MeseValidita, out DatiModuloCommessaParzialiTotale? parziale); + if (parziale == null) + parziale = new(); + + parziale.Totale += tot.Totale; + parziale.AnnoValidita = tot.AnnoValidita; + parziale.MeseValidita = tot.MeseValidita; + parziale.Prodotto = tot.Prodotto; + parziale.IdEnte = tot.IdEnte; + parziale.IdTipoContratto = tot.IdTipoContratto; + parziale.Stato = tot.Stato; + parziali.TryAdd(tot.MeseValidita, parziale); + parziale.Modifica = tot.Stato == StatoModuloCommessa.ApertaCaricato && _ruolo == Ruolo.ADMIN; + } + foreach (var commessa in moduliCommessa) + { + parziali.TryGetValue(commessa.MeseValidita, out DatiModuloCommessaParzialiTotale? parziale); + if (parziale == null) + parziale = new(); + + if (commessa.IdTipoSpedizione == 1) // Analog.A/R + { + parziale.AnalogicoARNazionali += commessa.ValoreNazionali; + parziale.AnalogicoARInternazionali += commessa.ValoreInternazionali; + } + else if (commessa.IdTipoSpedizione == 2) // Analog.L. 890/82 + parziale.Analogico890Nazionali += commessa.ValoreNazionali; + else // Digitale + parziale.Digitale = totalePerCategoria.Where(x => x.IdCategoriaSpedizione == 2).Select(x => x.Totale).FirstOrDefault(); + + } + return parziali.Values.ToList(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetAnniPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetAnniPersistence.cs new file mode 100644 index 0000000..72b901b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetAnniPersistence.cs @@ -0,0 +1,22 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaQueryGetAnniPersistence(string? idEnte, string? prodotto) : DapperBase, IQuery?> +{ + private readonly string? _idEnte = idEnte; + private readonly string? _prodotto = prodotto; + private static readonly string _sqlSelect = DatiModuloCommessaAnniSQLBuilder.SelectBy(); + + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new + { + idEnte = _idEnte, + prodotto = _prodotto + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByAnnoPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByAnnoPersistence.cs new file mode 100644 index 0000000..00f48b6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByAnnoPersistence.cs @@ -0,0 +1,25 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaQueryGetByAnnoPersistence(string? idEnte, int annoValidita, string? prodotto) : DapperBase, IQuery?> +{ + private readonly int _annoValidita = annoValidita; + private readonly string? _idEnte = idEnte; + private readonly string? _prodotto = prodotto; + private static readonly string _sqlSelect = DatiModuloCommessaTotaleSQLBuilder.SelectByAnno(); + + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new + { + idEnte = _idEnte, + annoValidita = _annoValidita, + prodotto = _prodotto, + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByDescrizionePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByDescrizionePersistence.cs new file mode 100644 index 0000000..8ebcdfb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByDescrizionePersistence.cs @@ -0,0 +1,34 @@ +using System.Data; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaQueryGetByDescrizionePersistence(string[]? idEnti, int annoValidita, int meseValidita, string? prodotto) : DapperBase, IQuery?> +{ + private readonly string? _prodotto = prodotto; + private readonly int _annoValidita = annoValidita; + private readonly long _meseValidita = meseValidita; + private readonly string[]? _idEnti = idEnti; + private static readonly string _sqlSelect = DatiModuloCommessaSQLBuilder.SelectByRicerca(); + + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + string? where = null; + if (!_idEnti!.IsNullNotAny()) + where = " AND IdEnte in @idEnti"; + + if (!string.IsNullOrEmpty(_prodotto)) + where += " AND Prodotto = @prodotto"; + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema) + where, + new + { + idEnti = _idEnti, + mese = _meseValidita, + anno = _annoValidita, + prodotto = _prodotto, + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByIdPersistence.cs new file mode 100644 index 0000000..1db14be --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaQueryGetByIdPersistence.cs @@ -0,0 +1,27 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaQueryGetByIdPersistence(string? idEnte, int annoValidita, int meseValidita, string? prodotto) : DapperBase, IQuery?> +{ + private readonly string? _prodotto = prodotto; + private readonly int _annoValidita = annoValidita; + private readonly long _meseValidita = meseValidita; + private readonly string? _idEnte = idEnte; + private static readonly string _sqlSelect = DatiModuloCommessaSQLBuilder.SelectBy(); + + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new + { + idEnte = _idEnte, + meseValidita = _meseValidita, + annoValidita = _annoValidita, + prodotto = _prodotto, + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaTotaleQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaTotaleQueryGetByIdPersistence.cs new file mode 100644 index 0000000..4845a2f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/Queries/Persistence/DatiModuloCommessaTotaleQueryGetByIdPersistence.cs @@ -0,0 +1,34 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; + +public class DatiModuloCommessaTotaleQueryGetByIdPersistence : DapperBase, IQuery?> +{ + private readonly string? _prodotto; + private readonly int _annoValidita; + private readonly long _meseValidita; + private readonly string? _idEnte; + private static readonly string _sqlSelect = DatiModuloCommessaTotaleSQLBuilder.SelectBy(); + + public DatiModuloCommessaTotaleQueryGetByIdPersistence(string? idEnte, int annoValidita, int meseValidita, string? prodotto) + { + this._prodotto = prodotto; + this._annoValidita = annoValidita; + this._meseValidita = meseValidita; + this._idEnte = idEnte; + } + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new + { + idEnte = _idEnte, + meseValidita = _meseValidita, + annoValidita = _annoValidita, + prodotto = _prodotto, + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiConfigurazioneModuloCommessaQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiConfigurazioneModuloCommessaQueryHandler.cs new file mode 100644 index 0000000..41b2411 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiConfigurazioneModuloCommessaQueryHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers; + +public class DatiConfigurazioneModuloCommessaQueryHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public DatiConfigurazioneModuloCommessaQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(DatiConfigurazioneModuloCommessaQueryGet request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new DatiConfigurazioneModuloCommessaQueryGetPersistence(prodotto: request.Prodotto, idTipoContratto: request.IdTipoContratto), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaGetAnniHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaGetAnniHandler.cs new file mode 100644 index 0000000..d41147c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaGetAnniHandler.cs @@ -0,0 +1,35 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers +{ + public class DatiModuloCommessaGetAnniHandler : IRequestHandler?> + { + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public DatiModuloCommessaGetAnniHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task?> Handle(DatiModuloCommessaGetAnni request, CancellationToken ct) + { + var idEnte = request.AuthenticationInfo.IdEnte; + var prodotto = request.AuthenticationInfo.Prodotto; + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new DatiModuloCommessaQueryGetAnniPersistence(idEnte, prodotto), ct); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByAnnoHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByAnnoHandler.cs new file mode 100644 index 0000000..90ae392 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByAnnoHandler.cs @@ -0,0 +1,108 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers +{ + public class DatiModuloCommessaQueryByAnnoHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + IScadenziarioService scadenziarioService, + ILogger logger) : IRequestHandler?> + { + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IScadenziarioService _scadenziarioService = scadenziarioService; + + public async Task?> Handle(DatiModuloCommessaQueryGetByAnno command, CancellationToken ct) + { + var (annoFatturazione, meseFatturazione, _, _) = Time.YearMonthDayFatturazione(); + + command.AnnoValidita = command.AnnoValidita != null ? command.AnnoValidita : annoFatturazione; + IEnumerable? dati; + IEnumerable? categorie; + IEnumerable? moduloCommesseDate; + using (var uow = await _factory.Create(true, cancellationToken: ct)) + { + dati = await uow.Query(new DatiModuloCommessaQueryGetByAnnoPersistence( + command.AuthenticationInfo.IdEnte, + command.AnnoValidita.Value, + command.AuthenticationInfo.Prodotto), ct); + categorie = await uow.Query(new SpedizioneQueryGetAllPersistence(), ct); + moduloCommesseDate = await uow.Query(new DatiModuloCommessaDateQueryGetByIdPersistence( + command.AuthenticationInfo.IdEnte, + command.AnnoValidita.Value, + command.AuthenticationInfo.IdTipoContratto, + command.AuthenticationInfo.Prodotto), ct); + } + + if (categorie!.IsNullNotAny()) + { + var msg = "Provide categorie and tipo commessa in configuration!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + + if (dati!.IsNullNotAny()) + return null; + + var dicCategorie = categorie! + .Select(x => new KeyValuePair(x.Id, x.Tipo!)) + .ToDictionary(x => x.Key, x => x.Value); + + Dictionary lista = new(); + foreach (var dato in dati!) + { + var dates = moduloCommesseDate!.Where(x => x.MeseValidita == dato.MeseValidita).FirstOrDefault()!; + var dataModifica = dates.DataModifica == DateTime.MinValue ? dates.DataCreazione : dates.DataModifica; + lista.TryGetValue(dato.MeseValidita, out var modulo); + modulo ??= new() + { + Prodotto = dato.Prodotto, + AnnoValidita = dato.AnnoValidita, + IdEnte = dato.IdEnte, + IdTipoContratto = dato.IdTipoContratto, + MeseValidita = dato.MeseValidita, + Stato = dato.Stato, + Totali = [], + DataModifica = dataModifica + }; + + modulo.Totali!.TryGetValue(dato.IdCategoriaSpedizione, out var totMese); + totMese = new() + { + IdCategoriaSpedizione = dato.IdCategoriaSpedizione, + Tipo = dicCategorie[dato.IdCategoriaSpedizione], + TotaleCategoria = dato.TotaleCategoria + }; + modulo.Totali[dato.IdCategoriaSpedizione] = totMese; + modulo.Totale = modulo.Totali.Sum(x => x.Value.TotaleCategoria); + + var (valid, scadenziario) = await _scadenziarioService.GetScadenziario( + command.AuthenticationInfo, + TipoScadenziario.DatiModuloCommessa, + dato.AnnoValidita, + dato.MeseValidita); + + modulo.Modifica = dato.Stato == StatoModuloCommessa.ApertaCaricato && valid; + lista[dato.MeseValidita] = modulo; + } + + return lista.Select(x => x.Value); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByDescrizioneHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByDescrizioneHandler.cs new file mode 100644 index 0000000..a000581 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByDescrizioneHandler.cs @@ -0,0 +1,31 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers; + +public class DatiModuloCommessaQueryByDescrizioneHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task?> Handle(DatiModuloCommessaQueryGetByDescrizione command, CancellationToken ct) + { + if (command.MeseValidita == null || command.AnnoValidita == null) + throw new ArgumentException("Passare un anno e un mese"); + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new DatiModuloCommessaQueryGetByDescrizionePersistence(command.IdEnti, + command.AnnoValidita.Value, + command.MeseValidita.Value, + command.Prodotto), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByParzialiAnnoHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByParzialiAnnoHandler.cs new file mode 100644 index 0000000..6c103c4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryByParzialiAnnoHandler.cs @@ -0,0 +1,46 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers +{ + public class DatiModuloCommessaQueryByParzialiAnnoHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + IScadenziarioService scadenziarioService, + ILogger logger) : IRequestHandler?> + { + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IScadenziarioService _scadenziarioService = scadenziarioService; + + public async Task?> Handle(DatiModuloCommessaParzialiQueryGetByAnno command, CancellationToken ct) + { + var (annoFatturazione, _, _, _) = Time.YearMonthDayFatturazione(); + command.AnnoValidita = command.AnnoValidita != null ? command.AnnoValidita : annoFatturazione; + var idEnte = command.AuthenticationInfo.IdEnte; + var prodotto = command.AuthenticationInfo.Prodotto; + var ruolo = command.AuthenticationInfo.Ruolo; + using var uow = await _factory.Create(true, cancellationToken: ct); + var parzialiTotale = await uow.Query(new DatiModuloCommessaParzialiTotaleQueryGetByIdPersistence(idEnte, command.AnnoValidita.Value, prodotto, ruolo), ct); + if (parzialiTotale!.IsNullNotAny()) + return null; + + foreach (var parziali in parzialiTotale!) + { + var(valid, _) = await _scadenziarioService.GetScadenziario(command.AuthenticationInfo, TipoScadenziario.DatiModuloCommessa, parziali.AnnoValidita, parziali.MeseValidita); + parziali.Modifica = parziali.Stato == StatoModuloCommessa.ApertaCaricato && valid; + } + return parzialiTotale; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryDocumentoHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryDocumentoHandler.cs new file mode 100644 index 0000000..cfa03bb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryDocumentoHandler.cs @@ -0,0 +1,71 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers +{ + public class DatiModuloCommessaQueryDocumentoHandler( + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler + { + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(DatiModuloCommessaDocumentoQueryGet command, CancellationToken ct) + { + var (annoFatturazione, meseFatturazione, _, _) = Time.YearMonthDayFatturazione(); + command.AnnoValidita = command.AnnoValidita != null ? command.AnnoValidita : annoFatturazione; + command.MeseValidita = command.MeseValidita != null ? command.MeseValidita : meseFatturazione; + var authInfo = command.AuthenticationInfo; + + var datiFatturazione = await _handler.Send(new DatiFatturazioneQueryGetByIdEnte(authInfo), ct); + if (datiFatturazione == null) + return null; + + var datiModuloCommessa = await _handler.Send(new DatiModuloCommessaQueryGet(authInfo) + { + AnnoValidita = command.AnnoValidita, + MeseValidita = command.MeseValidita, + }, ct); + if (datiModuloCommessa == null) + return null; + + var ente = await _handler.Send(new EnteQueryGetById(authInfo)) ?? throw new DomainException("EnteSelfCareError"); + + var prodotto = datiModuloCommessa.DatiModuloCommessa!.Select(x => x.Prodotto).FirstOrDefault(); + var idTipoContratto = datiModuloCommessa.DatiModuloCommessa!.Select(x => x.IdTipoContratto).FirstOrDefault(); + var configurazioneModuloCommessa = await _handler.Send(new DatiConfigurazioneModuloCommessaQueryGet() + { + Prodotto = prodotto, + IdTipoContratto = idTipoContratto + }, ct); + + var moduliTotaleAnno = await _handler.Send(new DatiModuloCommessaQueryGetByAnno(authInfo) + { + AnnoValidita = command.AnnoValidita, + }); + + var moduloTotaleMese = moduliTotaleAnno!.Where(x => x.MeseValidita == command.MeseValidita).FirstOrDefault(); + + var prepare = new ModuloCommessaAggregateDto() + { + Ente = ente, + DatiFatturazione = datiFatturazione, + DatiModuloCommessa = datiModuloCommessa.DatiModuloCommessa, + DatiModuloCommessaTotale = moduloTotaleMese, + DatiConfigurazioneModuloCommessa = configurazioneModuloCommessa + }; + + return prepare.Mapper(); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryHandler.cs new file mode 100644 index 0000000..be680c8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiModuloCommesse/QueryHandlers/DatiModuloCommessaQueryHandler.cs @@ -0,0 +1,99 @@ +using Azure.Core; +using MediatR; +using Microsoft.AspNetCore.Identity.Data; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.QueryHandlers +{ + public class DatiModuloCommessaQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + IScadenziarioService scadenziarioService, + ILogger logger) : IRequestHandler + { + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IScadenziarioService _scadenziarioService = scadenziarioService; + + public async Task Handle(DatiModuloCommessaQueryGet request, CancellationToken ct) + { + var (annoFatturazione, meseFatturazione, _, adesso) = Time.YearMonthDayFatturazione(); + var idTipoContratto = request.AuthenticationInfo.IdTipoContratto; + var prodotto = request.AuthenticationInfo.Prodotto; + + using (var rs = await _factory.Create(true, cancellationToken: ct)) + { + var prodotti = await rs.Query(new ProdottoQueryGetAllPersistence(), ct); + if (prodotti.IsNullNotAny()) + { + var msg = "Provide products in configurazion!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + prodotto = prodotti.Where(x => x.Nome!.ToLower() == prodotto!.ToLower()).Select(x => x.Nome).FirstOrDefault(); + if (prodotto == null) + { + var msg = "I could not find the specified product!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + var contratti = await rs.Query(new TipoContrattoQueryGetAllPersistence(), ct); + if (contratti.IsNullNotAny()) + { + var msg = "Provide contracts in configurazion!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + idTipoContratto = contratti.Where(x => x.Id! == idTipoContratto!).Select(x => x.Id).FirstOrDefault(); + if (idTipoContratto == null) + { + var msg = "I could not find the specified contruct!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + } + + request.AnnoValidita = request.AnnoValidita != null ? request.AnnoValidita : annoFatturazione; + request.MeseValidita = request.MeseValidita != null ? request.MeseValidita : meseFatturazione; + request.Prodotto = prodotto; + + var idEnte = request.AuthenticationInfo.IdEnte; + + using var uow = await _factory.Create(true, cancellationToken: ct); + var datic = await uow.Query(new DatiModuloCommessaQueryGetByIdPersistence(idEnte, request.AnnoValidita.Value, request.MeseValidita.Value, request.Prodotto), ct); + var datit = await uow.Query(new DatiModuloCommessaTotaleQueryGetByIdPersistence(idEnte, request.AnnoValidita.Value, request.MeseValidita.Value, request.Prodotto), ct); + + + var (valid, _) = await _scadenziarioService.GetScadenziario( + request.AuthenticationInfo, + TipoScadenziario.DatiModuloCommessa, + request.AnnoValidita.Value, + request.MeseValidita.Value); + + return new ModuloCommessaDto() + { + Modifica = valid && (datic!.IsNullNotAny() || datic!.Select(x => x.Stato).FirstOrDefault() == StatoModuloCommessa.ApertaCaricato), + DatiModuloCommessa = datic!, + DatiModuloCommessaTotale = datit!, + Anno = datic!.Select(x => x.AnnoValidita).FirstOrDefault() == 0 ? request.AnnoValidita.Value : datic!.Select(x => x.AnnoValidita).FirstOrDefault(), + Mese = datic!.Select(x => x.MeseValidita).FirstOrDefault() == 0 ? request.MeseValidita.Value : datic!.Select(x => x.MeseValidita).FirstOrDefault(), + }; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelBulkDownloadCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelBulkDownloadCommandHandler.cs new file mode 100644 index 0000000..0a24e21 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelBulkDownloadCommandHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class RelBulkDownloadCommandHandler( + ISelfCareDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(RelBulkDownloadCommand command, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + { + var rowAffected = await uow.Execute(new RelBulkUploadCreateCommandPersistence(command, _localizer), ct); + return (rowAffected == command.Commands!.Count); + } + throw new DomainException(_localizer["xxx"]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelDownloadCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelDownloadCommandHandler.cs new file mode 100644 index 0000000..c7790f2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelDownloadCommandHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class RelDownloadCommandHandler( + ISelfCareDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(RelDownloadCommand command, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + { + var rowAffected = await uow.Execute(new RelUploadCreateCommandPersistence(command.Map(), _localizer), ct); + return (rowAffected == 1); + } + throw new DomainException(_localizer["xxx"]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelFatturabileByIdEntiCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelFatturabileByIdEntiCommandHandler.cs new file mode 100644 index 0000000..b97aadf --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelFatturabileByIdEntiCommandHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class RelFatturabileByIdEntiCommandHandler( + ISelfCareDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(RelFatturabileByIdEnti command, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + { + var rowAffected = await uow.Execute(new RelFatturabileByIdEntiCommandPersistence(command, _localizer), ct); + return (rowAffected); + } + throw new DomainException(_localizer["xxx"]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelUploadCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelUploadCreateCommandHandler.cs new file mode 100644 index 0000000..cbde99f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/CommandHandlers/RelUploadCreateCommandHandler.cs @@ -0,0 +1,53 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class RelUploadCreateCommandHandler( + ISelfCareDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(RelUploadCreateCommand command, CancellationToken ct) + { + var authInfo = command.AuthenticationInfo!; + + if (!(authInfo.Profilo == Profilo.PubblicaAmministrazione)) + throw new SecurityException(); //401 + + using var uow = await _factory.Create(true, cancellationToken: ct); + { + var id = await uow.Execute(new RelTestataUpdateCommandPersistence(command.Map(), _localizer), ct); + if (id > 0) + { + var rowAffected = await uow.Execute(new RelUploadCreateCommandPersistence(command, _localizer), ct); + + if (rowAffected == 1) + { + uow.Commit(); + return true; + } + else + uow.Rollback(); + } + else + uow.Rollback(); + } + throw new DomainException(_localizer["xxx"]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelBulkUploadCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelBulkUploadCreateCommandPersistence.cs new file mode 100644 index 0000000..35b518d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelBulkUploadCreateCommandPersistence.cs @@ -0,0 +1,42 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class RelBulkUploadCreateCommandPersistence(RelBulkDownloadCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly RelBulkDownloadCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlInsert = @" + INSERT INTO [schema][RelUpload] + ([FkIdEnte] + ,[contract_id] + ,[TipologiaFattura] + ,[year] + ,[month] + ,[DataEvento] + ,[IdUtente] + ,[Azione] + ,[Hash]) + VALUES + (@IdEnte + ,@IdContratto + ,@TipologiaFattura + ,@Anno + ,@Mese + ,@DataEvento + ,@IdUtente + ,@Azione + ,@Hash) +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), _command.Commands, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelFatturabileByIdEntiCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelFatturabileByIdEntiCommandPersistence.cs new file mode 100644 index 0000000..c40b338 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelFatturabileByIdEntiCommandPersistence.cs @@ -0,0 +1,26 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class RelFatturabileByIdEntiCommandPersistence(RelFatturabileByIdEnti command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly RelFatturabileByIdEnti _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlUpdate = @" + UPDATE [pfd].[Notifiche] + SET + [Fatturabile] = @Fatturabile + WHERE year=@anno AND month=@mese AND internal_organization_id IN @EntiIds +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdate.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelTestataUpdateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelTestataUpdateCommandPersistence.cs new file mode 100644 index 0000000..cbb3e8d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelTestataUpdateCommandPersistence.cs @@ -0,0 +1,29 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class RelTestataUpdateCommandPersistence(RelUploadStateCreateCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly RelUploadStateCreateCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlInsert = @" + UPDATE [schema][RelTestata] + SET [Caricata] = 1 + WHERE internal_organization_id = @IdEnte + AND contract_id = @IdContratto + AND TipologiaFattura = @TipologiaFattura + AND year=@Anno + AND month=@Mese; +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelUploadCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelUploadCreateCommandPersistence.cs new file mode 100644 index 0000000..4681825 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/Persistence/RelUploadCreateCommandPersistence.cs @@ -0,0 +1,42 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class RelUploadCreateCommandPersistence(RelUploadCreateCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly RelUploadCreateCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlInsert = @" + INSERT INTO [schema][RelUpload] + ([FkIdEnte] + ,[contract_id] + ,[TipologiaFattura] + ,[year] + ,[month] + ,[DataEvento] + ,[IdUtente] + ,[Azione] + ,[Hash]) + VALUES + (@IdEnte + ,@IdContratto + ,@TipologiaFattura + ,@Anno + ,@Mese + ,@DataEvento + ,@IdUtente + ,@Azione + ,@Hash) +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelBulkDownloadCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelBulkDownloadCommand.cs new file mode 100644 index 0000000..34f5ec6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelBulkDownloadCommand.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class RelBulkDownloadCommand(IAuthenticationInfo? authenticationInfo) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + + public List? Commands { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelDownloadCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelDownloadCommand.cs new file mode 100644 index 0000000..1a11082 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelDownloadCommand.cs @@ -0,0 +1,20 @@ +using MediatR; +using Microsoft.VisualBasic; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; + +public class RelDownloadCommand(IAuthenticationInfo? authenticationInfo) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdEnte { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } + public DateTime? DataEvento { get; set; } + public string? IdUtente { get; set; } + public string? Azione { get; set; } + public string? Hash { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelFatturabileByIdEnti.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelFatturabileByIdEnti.cs new file mode 100644 index 0000000..9fcdc9a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelFatturabileByIdEnti.cs @@ -0,0 +1,13 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; + +public class RelFatturabileByIdEnti(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int Anno { get; set; } + public int Mese { get; set; } + public string[]? EntiIds { get; set; } + public byte? Fatturabile { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadCreateCommand.cs new file mode 100644 index 0000000..f03735d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadCreateCommand.cs @@ -0,0 +1,20 @@ +using MediatR; +using Microsoft.VisualBasic; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class RelUploadCreateCommand(IAuthenticationInfo? authenticationInfo) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdEnte { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } + public DateTime? DataEvento { get; set; } + public string? IdUtente { get; set; } + public string? Azione { get; set; } + public string? Hash { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadStateCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadStateCreateCommand.cs new file mode 100644 index 0000000..9be08a6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Commands/RelUploadStateCreateCommand.cs @@ -0,0 +1,16 @@ +using MediatR; +using Microsoft.VisualBasic; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class RelUploadStateCreateCommand(IAuthenticationInfo? authenticationInfo) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdEnte { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQuadraturaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQuadraturaDto.cs new file mode 100644 index 0000000..dbdc584 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQuadraturaDto.cs @@ -0,0 +1,169 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public class RelQuadraturaDto +{ + [Column("IdEnte")] + [HeaderAttributev2(caption: "IdEnte", Order = 1)] + public string? IdEnte { get; set; } + + + [HeaderAttributev2(caption: "Ragione Sociale", Order = 2)] + + [Column("RagioneSociale")] + public string? RagioneSociale { get; set; } + + [HeaderAttributev2(caption: "IdContratto", Order = 3)] + + [Column("IdContratto")] + public string? IdContratto { get; set; } + + + [HeaderAttributev2(caption: "Tipologia Fattura", Order = 4)] + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [HeaderAttributev2(caption: "Anno", Order = 5)] + + [Column("Anno")] + public int? Anno { get; set; } + + [HeaderAttributev2(caption: "Mese", Order = 6)] + + [Column("Mese")] + public int? Mese { get; set; } + + //contestazioni -init + [HeaderAttributev2(caption: "Imponibile Contestazioni Analogico €", Order = 7)] + + [Column("ContestazioniTotaleAnalogico")] + public decimal ContestazioniTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Imponibile Contestazioni Digitale €", Order = 8)] + + [Column("ContestazioniTotaleDigitale")] + public decimal ContestazioniTotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "Imponibile Contestazioni €", Order = 9)] + + [Column("ContestazioniTotale")] + public decimal ContestazioniTotale { get; set; } + + [HeaderAttributev2(caption: "N. Contestazioni Analogiche", Order = 10)] + [Column("ContestazioniTotaleNotificheAnalogiche")] + public int ContestazioniTotaleNotificheAnalogiche { get; set; } + + + [HeaderAttributev2(caption: "N. Contestazioni Digitale", Order = 11)] + + [Column("ContestazioniTotaleNotificheDigitali")] + public int ContestazioniTotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "N. Totale Contestazioni", Order = 12)] + + [Column("ContestazioniNotificheTotale")] + public int ContestazioniNotificheTotale { get; set; } + //contestazioni -end + + //rel -init + [HeaderAttributev2(caption: "REL Imponibile Analogico €", Order = 13)] + [Column("RelTotaleAnalogico")] + public decimal RelTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "REL Imponibile Digitale €", Order = 14)] + [Column("RelTotaleDigitale")] + public decimal RelTotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "REL Imponibile €", Order = 15)] + [Column("RelTotale")] + public decimal RelTotale { get; set; } + + [HeaderAttributev2(caption: "N. REL Analogico", Order = 16)] + [Column("RelTotaleNotificheAnalogiche")] + public int RelTotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "N. REL Digitale", Order = 17)] + [Column("RelTotaleNotificheDigitali")] + public int RelTotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "N. REL Totale", Order = 18)] + [Column("RelTotaleNotifiche")] + public int RelTotaleNotifiche { get; set; } + //rel -end + + //rel asse -init + [HeaderAttributev2(caption: "Ass. Imponibile Analogico €", Order = 19)] + [Column("RelAsseTotaleAnalogico")] + public decimal RelAsseTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Ass. Imponibile Digitalie €", Order = 20)] + [Column("RelAsseTotaleDigitale")] + public decimal RelAsseTotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "Ass. Imponibile €", Order = 21)] + [Column("RelAsseTotale")] + public decimal RelAsseTotale { get; set; } + + [HeaderAttributev2(caption: "N. Asseverazione Analogico", Order = 22)] + [Column("RelAsseTotaleNotificheAnalogiche")] + public int RelAsseTotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "N. Asseverazione Digitale", Order = 23)] + [Column("RelAsseTotaleNotificheDigitali")] + public int RelAsseTotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "N. Asseverazione", Order = 24)] + [Column("RelAsseTotaleNotifiche")] + public int RelAsseTotaleNotifiche { get; set; } + //rel asse -end + + // notifiche --init + [HeaderAttributev2(caption: "Consuntivo Imponible Analogico €", Order = 25)] + [Column("NotificheTotaleAnalogico")] + public decimal NotificheTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Consuntivo Imponibile Digitale €", Order = 26)] + [Column("NotificheTotaleDigitale")] + public decimal NotificheTotaleDigitale { get; set; } + + + [HeaderAttributev2(caption: "Consuntivo Imponibile €", Order = 27)] + [Column("NotificheTotale")] + public decimal NotificheTotale { get; set; } + + [HeaderAttributev2(caption: "N. Consuntivo Analogico", Order = 28)] + [Column("NotificheTotaleNotificheAnalogiche")] + public int NotificheTotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "N. Consuntivo Digitali", Order = 29)] + [Column("NotificheTotaleNotificheDigitali")] + public int NotificheTotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "N. Totale consuntivo", Order = 30)] + [Column("NotificheTotaleNotifiche")] + public int NotificheTotaleNotifiche { get; set; } + + + [HeaderAttributev2(caption: "Check Imponibile Analogico €", Order = 31)] + [Column("DiffTotaleAnalogico")] + public decimal DiffTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Check Imponibile Digitale €", Order = 32)] + [Column("DiffTotaleDigitale")] + public decimal DiffTotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "Check Notifiche Analogico", Order = 33)] + [Column("DiffTotaleNotificheAnalogiche")] + public int DiffTotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "Check Notifiche Digitali", Order = 34)] + [Column("DiffTotaleNotificheDigitali")] + public int DiffTotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "Check Notifiche", Order = 35)] + [Column("DiffTotaleNotificheZero")] + public int DiffTotaleNotificheZero { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQueryDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQueryDto.cs new file mode 100644 index 0000000..381eae0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelQueryDto.cs @@ -0,0 +1,15 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +public class RelQueryDto +{ + public string? IdEnte { get; set; } = null; + public int? Anno { get; set; } + public int? Mese { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } + public string? TipologiaFattura { get; set; } + public string? IdContratto { get; set; } + public byte? Caricata { get; set; } + public string? Azione { get; set; } + public string[]? EntiIds { get; set; } = null; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataDto.cs new file mode 100644 index 0000000..41372fe --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataDto.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using PortaleFatture.BE.Core.Entities.DatiRel; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +public sealed class RelTestataDto +{ + [JsonPropertyOrder(-1)] + public List? RelTestate { get; set; } + + [JsonPropertyOrder(-2)] + public int Count { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataQuadraturaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataQuadraturaDto.cs new file mode 100644 index 0000000..675c8f1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelTestataQuadraturaDto.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using PortaleFatture.BE.Core.Entities.DatiRel; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +public sealed class RelTestataQuadraturaDto +{ + [JsonPropertyOrder(-1)] + public List? Quadratura { get; set; } + + [JsonPropertyOrder(-2)] + public int Count { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelVerificaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelVerificaDto.cs new file mode 100644 index 0000000..79cbca7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RelVerificaDto.cs @@ -0,0 +1,22 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +public class RelVerificaEmailDto +{ + public string? Messaggio { get; set; } + public string? RagioneSociale { get; set; } + public string? TipologiaFattura { get; set; } +} + +public class RelVerificaRelDto +{ + public string? TipologiaFattura { get; set; } + public string? RagioneSociale { get; set; } +} + +public class RelVerificaDto +{ + public string? IdEnte { get; set; } + public RelVerificaEmailDto? VerificaEmail { get; set; } + + public RelVerificaRelDto? VerificaRel{ get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RigheRelDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RigheRelDto.cs new file mode 100644 index 0000000..c2be5e2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/RigheRelDto.cs @@ -0,0 +1,142 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +public class RigheRelDto +{ + [Column("internal_organization_id")] + [HeaderAttributev2(caption: "internal_organization_id", Order = 16)] + public string? IdEnte { get; set; } + + [Column("description")] + [HeaderAttributev2(caption: "description", Order = 27)] + public string? RagioneSociale { get; set; } + + [Column("institutionType")] + [HeaderAttributev2(caption: "institutionType", Order = 28)] + public string? Profilo { get; set; } + + [Column("contract_id")] + [HeaderAttribute(caption: "contract_id", Order = 1)] + [HeaderAttributev2(caption: "contract_id", Order = 1)] + public string? IdContratto { get; set; } + + [Column("tax_code")] + [HeaderAttribute(caption: "tax_code", Order = 2)] + [HeaderAttributev2(caption: "tax_code", Order = 2)] + public string? CodiceFiscale { get; set; } + + [Column("vat_number")] + [HeaderAttribute(caption: "vat_number", Order = 3)] + [HeaderAttributev2(caption: "vat_number", Order = 3)] + public string? PIva { get; set; } + + [Column("zip_code")] + [HeaderAttribute(caption: "zip_code", Order = 4)] + [HeaderAttributev2(caption: "zip_code", Order = 4)] + public string? CAP { get; set; } + + [Column("foreign_state")] + [HeaderAttribute(caption: "foreign_state", Order = 5)] + [HeaderAttributev2(caption: "foreign_state", Order = 5)] + public string? StatoEstero { get; set; } + + [Column("number_of_pages")] + [HeaderAttributev2(caption: "number_of_pages", Order = 6)] + public string? NumberOfPages { get; set; } + + [Column("g_envelope_weight")] + [HeaderAttributev2(caption: "g_envelope_weight", Order = 7)] + public string? GEnvelopeWeight { get; set; } + + [Column("cost")] + [HeaderAttribute(caption: "costo €", Order = 6)] + [HeaderAttributev2(caption: "cost", Order = 8)] + public decimal Cost { get; set; } + + [Column("timeline_category")] + [HeaderAttribute(caption: "timeline_category", Order = 7)] + [HeaderAttributev2(caption: "timeline_category", Order = 9)] + public string? TimelineCategory { get; set; } + + [Column("contestazione")] + [HeaderAttribute(caption: "contestazione", Order = 18)] + public string? Contestazione { get; set; } + + [Column("idContestazione")] + public short StatoContestazione { get; set; } + + [Column("notificationtype")] + [HeaderAttribute(caption: "paper_product_type", Order = 8)] + [HeaderAttributev2(caption: "paper_product_type", Order = 10)] + public string? TipoNotifica { get; set; } + + [Column("event_id")] + [HeaderAttribute(caption: "event_id", Order = 9)] + [HeaderAttributev2(caption: "event_id", Order = 11)] + public string? IdNotifica { get; set; } + + [Column("iun")] + [HeaderAttribute(caption: "iun", Order = 10)] + [HeaderAttributev2(caption: "iun", Order = 12)] + public string? IUN { get; set; } + + [Column("recapitista")] + [HeaderAttribute(caption: "recapitista", Order = 11)] + [HeaderAttributev2(caption: "recapitista", Order = 14)] + public string? Recapitista { get; set; } + + [Column("notification_sent_at")] + [HeaderAttribute(caption: "notification_sent_at", Order = 12)] + [HeaderAttributev2(caption: "notification_sent_at", Order = 15)] + public string? DataInvio { get; set; } + + [Column("event_timestamp")] + [HeaderAttribute(caption: "event_timestamp", Order = 13)] + [HeaderAttributev2(caption: "event_timestamp", Order = 17)] + public string? Data { get; set; } + + [Column("recipient_index")] + [HeaderAttributev2(caption: "recipient_index", Order = 18)] + public string? RecipientIndex { get; set; } + + [Column("recipient_type")] + [HeaderAttributev2(caption: "recipient_type", Order = 19)] + public string? RecipientType { get; set; } + + [Column("recipient_id")] + [HeaderAttributev2(caption: "recipient_id", Order = 20)] + public string? RecipientId { get; set; } + + [Column("year")] + [HeaderAttribute(caption: "year", Order = 14)] + [HeaderAttributev2(caption: "year", Order = 21)] + public string? Anno { get; set; } + + [Column("month")] + [HeaderAttribute(caption: "month", Order = 15)] + [HeaderAttributev2(caption: "month", Order = 22)] + public string? Mese { get; set; } + + [Column("daily")] + [HeaderAttribute(caption: "daily", Order = 16)] + [HeaderAttributev2(caption: "daily", Order = 23)] + public string? AnnoMeseGiorno { get; set; } + + [Column("item_code")] + [HeaderAttributev2(caption: "item_code", Order = 24)] + public string? ItemCode { get; set; } + + [Column("notification_request_id")] + [HeaderAttributev2(caption: "notification_request_id", Order = 25)] + public string? NotificationRequestId { get; set; } + + [Column("recipient_tax_id")] + [HeaderAttributev2(caption: "recipient_tax_id", Order = 26)] + public string? RecipientTaxId { get; set; } + + [Column("TipologiaFattura")] + [HeaderAttribute(caption: "Tipologia Fattura", Order = 18)] + public string? TipologiaFattura { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/SimpleRelTestata.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/SimpleRelTestata.cs new file mode 100644 index 0000000..88ee444 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Dto/SimpleRelTestata.cs @@ -0,0 +1,199 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public class SimpleRelTestata +{ + public string? IdTestata + { + get + { + return new RelTestataKey(IdEnte, IdContratto, TipologiaFattura, Anno, Mese).ToString(); + } + } + public string? NomeTestata + { + get + { + return $"{RagioneSociale}_{IdTestata}"; + } + } + + [Column("internal_organization_id")] + [HeaderAttribute(caption: "IdEnte", Order = 1)] + [HeaderAttributev2(caption: "IdEnte", Order = 1)] + public string? IdEnte { get; set; } + + + [HeaderAttribute(caption: "Ragione Sociale", Order = 2)] + [HeaderAttributev2(caption: "Ragione Sociale", Order = 2)] + + [Column("description")] + public string? RagioneSociale { get; set; } + + + [HeaderAttribute(caption: "IdContratto", Order = 3)] + [HeaderAttributev2(caption: "IdContratto", Order = 3)] + + [Column("contract_id")] + public string? IdContratto { get; set; } + + + [HeaderAttribute(caption: "Tipologia Fattura", Order = 4)] + [HeaderAttributev2(caption: "Tipologia Fattura", Order = 4)] + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [HeaderAttribute(caption: "Anno", Order = 5)] + [HeaderAttributev2(caption: "Anno", Order = 5)] + + [Column("year")] + public int? Anno { get; set; } + + + [HeaderAttribute(caption: "Mese", Order = 6)] + [HeaderAttributev2(caption: "Mese", Order = 6)] + + [Column("month")] + public int? Mese { get; set; } + + + [HeaderAttribute(caption: "Totale Imponibile Analogico €", Order = 11)] + [HeaderAttributev2(caption: "Totale Imponibile Analogico €", Order = 11)] + + [Column("TotaleAnalogico")] + public decimal TotaleAnalogico { get; set; } + + + [HeaderAttribute(caption: "Totale Imponibile Digitale €", Order = 12)] + [HeaderAttributev2(caption: "Totale Imponibile Digitale €", Order = 12)] + + [Column("TotaleDigitale")] + public decimal TotaleDigitale { get; set; } + + + [HeaderAttribute(caption: "N. Notifiche Analogiche", Order = 8)] + [HeaderAttributev2(caption: "N. Notifiche Analogiche", Order = 8)] + [Column("TotaleNotificheAnalogiche")] + public int TotaleNotificheAnalogiche { get; set; } + + + [HeaderAttribute(caption: "N. Notifiche Digitali", Order = 9)] + [HeaderAttributev2(caption: "N. Notifiche Digitali", Order = 9)] + + [Column("TotaleNotificheDigitali")] + public int TotaleNotificheDigitali { get; set; } + + + [HeaderAttribute(caption: "N. Totale Notifiche", Order = 10)] + [HeaderAttributev2(caption: "N. Totale Notifiche", Order = 10)] + public int TotaleNotifiche + { + get + { + + return TotaleNotificheAnalogiche + TotaleNotificheDigitali; + + + } + } + + [HeaderAttribute(caption: "Totale Imponibile €", Order = 13)] + [HeaderAttributev2(caption: "Totale Imponibile €", Order = 13)] + [Column("Totale")] + public decimal Totale { get; set; } + + [HeaderAttribute(caption: "%Iva", Order = 14)] + + [Column("Iva")] + public decimal Iva { get; set; } + + + [HeaderAttribute(caption: "Totale Ivato Analogico €", Order = 15)] + [HeaderAttributev2(caption: "Totale Ivato Analogico €", Order = 15)] + + [Column("TotaleAnalogicoIva")] + public decimal TotaleAnalogicoIva { get; set; } + + + [HeaderAttribute(caption: "Totale Ivato Digitale €", Order = 16)] + [HeaderAttributev2(caption: "Totale Ivato Digitale €", Order = 16)] + + [Column("TotaleDigitaleIva")] + public decimal TotaleDigitaleIva { get; set; } + + + [HeaderAttribute(caption: "Totale Ivato €", Order = 17)] + [HeaderAttributev2(caption: "Totale Ivato €", Order = 17)] + + [Column("TotaleIva")] + public decimal TotaleIva { get; set; } + + [HeaderAttribute(caption: "Firmata", Order = 18)] + [HeaderAttributev2(caption: "Firmata", Order = 18)] + public string Firmata + { + get + { + return Caricata.MapRelTestata(); + } + } + + [Column("Caricata")] + public byte Caricata { get; set; } + + + [HeaderAttributev2(caption: "Totale Asseveraz. Imponibile Analogico €", Order = 22)] + [Column("AsseverazioneTotaleAnalogico")] + public decimal AsseverazioneTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale Asseveraz. Imponibile Digitale €", Order = 23)] + [Column("AsseverazioneTotaleDigitale")] + public decimal AsseverazioneTotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "N. Notifiche Asseveraz. Analogiche", Order = 19)] + [Column("AsseverazioneTotaleNotificheAnalogiche")] + public int AsseverazioneTotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "N. Notifiche Asseveraz. Digitali", Order = 20)] + [Column("AsseverazioneTotaleNotificheDigitali")] + public int AsseverazioneTotaleNotificheDigitali { get; set; } + + + [HeaderAttributev2(caption: "N. Totale Asseveraz. Notifiche", Order = 21)] + public int AsseverazioneTotaleNotifiche + { + get + { + + return AsseverazioneTotaleNotificheAnalogiche + AsseverazioneTotaleNotificheDigitali; + + + } + } + + [HeaderAttributev2(caption: "Totale Asseveraz. Imponibile €", Order = 24)] + [Column("AsseverazioneTotale")] + public decimal AsseverazioneTotale { get; set; } + + + [HeaderAttributev2(caption: "Totale Asseveraz. Ivato Analogico €", Order = 25)] + + [Column("AsseverazioneTotaleAnalogicoIva")] + public decimal AsseverazioneTotaleAnalogicoIva { get; set; } + + + [HeaderAttributev2(caption: "Totale Asseveraz. Ivato Digitale €", Order = 26)] + + [Column("AsseverazioneTotaleDigitaleIva")] + public decimal AsseverazioneTotaleDigitaleIva { get; set; } + + + [HeaderAttributev2(caption: "Totale Asseveraz. Ivato €", Order = 27)] + + [Column("AsseverazioneTotaleIva")] + public decimal AsseverazioneTotaleIva { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Extensions/DatiRelInfraExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Extensions/DatiRelInfraExtensions.cs new file mode 100644 index 0000000..3e82e35 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Extensions/DatiRelInfraExtensions.cs @@ -0,0 +1,84 @@ +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Extensions; + +public static class DatiRelInfraExtensions +{ + public static RelUploadStateCreateCommand Map(this RelUploadCreateCommand command) + { + return new RelUploadStateCreateCommand(command.AuthenticationInfo) + { + Anno = command.Anno, + IdContratto = command.IdContratto, + IdEnte = command.IdEnte, + Mese = command.Mese, + TipologiaFattura = command.TipologiaFattura + }; + } + + public static RelUploadCreateCommand Map(this RelDownloadCommand command) + { + return new RelUploadCreateCommand(command.AuthenticationInfo) + { + Anno = command.Anno, + IdContratto = command.IdContratto, + IdEnte = command.IdEnte, + Mese = command.Mese, + TipologiaFattura = command.TipologiaFattura, + Azione = command.Azione, + DataEvento = command.DataEvento, + IdUtente = command.IdUtente, + Hash = command.Hash + }; + } + + public static List Map(this List commands) + { + List uploads = []; + foreach (var command in commands) + { + uploads.Add(new RelUploadCreateCommand(command.AuthenticationInfo) + { + Anno = command.Anno, + IdContratto = command.IdContratto, + IdEnte = command.IdEnte, + Mese = command.Mese, + TipologiaFattura = command.TipologiaFattura, + Azione = command.Azione, + DataEvento = command.DataEvento, + IdUtente = command.IdUtente, + Hash = command.Hash + }); + } + return uploads; + } + + public static RelBulkDownloadCommand Map(this IEnumerable? testate, Dictionary values, AuthenticationInfo info) + { + RelBulkDownloadCommand command = new(info); + var adesso = DateTime.UtcNow.ItalianTime(); + command.Commands = []; + foreach (var testata in testate!) + { + values.TryGetValue(testata.IdTestata!, out var hash); + command.Commands.Add(new RelDownloadCommand(info) + { + Anno = testata.Anno, + IdContratto = testata.IdContratto, + IdEnte = testata.IdEnte, + Mese = testata.Mese, + TipologiaFattura = testata.TipologiaFattura, + Azione = RelAzioneDocumento.Zip, + DataEvento = adesso, + IdUtente = info.Id, + Hash = hash + }); + } + return command; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelRigheSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelRigheSQLBuilder.cs new file mode 100644 index 0000000..0eb6e56 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelRigheSQLBuilder.cs @@ -0,0 +1,48 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; + +public static class RelRigheSQLBuilder +{ + private static string _sql = @" + SELECT [contract_id] AS IdContratto, + [tax_code] AS CodiceFiscale, + [vat_number] AS PIva, + [zip_code] AS CAP, + [foreign_state] AS StatoEstero, + [number_of_pages] AS NumberOfPages, + [g_envelope_weight] AS GEnvelopeWeight, + [cost] AS Cost, + [timeline_category] AS TimelineCategory, + [notificationtype] AS TipoNotifica, + [event_id] AS IdNotifica, + [iun] AS Iun, + [notification_sent_at] AS DataInvio , + r.[internal_organization_id] AS IdEnte , + [event_timestamp] AS DATA , + [recipient_index] AS RecipientIndex, + [recipient_type] AS RecipientType, + [recipient_id] AS RecipientId, + r.[year] AS anno, + r.[month] AS mese, + r.[daily] AS AnnoMeseGiorno, + [item_code] AS ItemCode, + [notification_request_id] AS NotificationRequestId, + [recipient_tax_id] AS RecipientTaxId, + [Recapitista] AS Recapitista, + e.description AS RagioneSociale, + CAST( + CASE + WHEN [TipologiaFattura] = 'ASSEVERAZIONE' + THEN 'Notifica di ente aderente al bando PNRR in cui è prevista la fase di asseverazione' + ELSE [TipologiaFattura] + END AS nvarchar(300)) as TipologiaFattura + FROM pfd.RelRighe r + INNER JOIN pfd.Enti e ON e.InternalIstitutionId = r.internal_organization_id + INNER JOIN pfd.Contratti c ON e.InternalIstitutionId = c.internalistitutionid + "; + + public static string SelectAll() + { + return _sql; + } + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataQuadraturaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataQuadraturaSQLBuilder.cs new file mode 100644 index 0000000..6d80773 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataQuadraturaSQLBuilder.cs @@ -0,0 +1,196 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; + +internal static class RelTestataQuadraturaSQLBuilder +{ + private static string _sqlCount = @" +SELECT Count(nc.[internal_organization_id]) +FROM [pfd].[NotificheCount] as nc + left outer join pfd.Enti as e + ON e.InternalIstitutionId = nc.internal_organization_id + left outer join pfd.RelTestata as r + ON r.internal_organization_id = nc.internal_organization_id + AND r.contract_id = nc.contract_id + AND r.year= nc.year + AND r.month = nc.month + AND r.TipologiaFattura = @TipologiaFattura + left outer join pfd.ContestazioniStorico as c + ON c.internal_organization_id = nc.internal_organization_id + AND c.contract_id = nc.contract_id + AND c.year= nc.year + AND c.month = nc.month + AND c.TipologiaFattura=@TipologiaFattura +"; + private static string _sqlNoTipologiaFattura = @" +SELECT + nc.[internal_organization_id] as IdEnte + ,e.description as RagioneSociale + ,nc.[contract_id] as IdContratto + ,nc.[year] as Anno + ,nc.[month] as Mese + ,nc.[TotaleAnalogico] as NotificheTotaleAnalogico + ,nc.[TotaleDigitale] as NotificheTotaleDigitale + ,nc.[TotaleNotificheAnalogiche] as NotificheTotaleNotificheAnalogiche + ,nc.[TotaleNotificheDigitali] as NotificheTotaleNotificheDigitali + ,nc.[Totale] as NotificheTotale + ,nc.[TotaleNotificheAnalogiche] + nc.[TotaleNotificheDigitali] as NotificheTotaleNotifiche + ,r.TotaleAnalogico as RelTotaleAnalogico + ,r.TotaleDigitale as RelTotaleDigitale + ,r.TotaleNotificheAnalogiche as RelTotaleNotificheAnalogiche + ,r.TotaleNotificheDigitali as RelTotaleNotificheDigitali + ,ISNULL(r.[TotaleNotificheAnalogiche],0) + ISNULL(r.[TotaleNotificheDigitali],0) as RelTotaleNotifiche + ,r.Totale as RelTotale + ,r.AsseverazioneTotaleAnalogico as RelAsseTotaleAnalogico + ,r.AsseverazioneTotaleDigitale as RelAsseTotaleDigitale + ,r.AsseverazioneTotaleNotificheAnalogiche as RelAsseTotaleNotificheAnalogiche + ,r.AsseverazioneTotaleNotificheDigitali as RelAsseTotaleNotificheDigitali + ,r.AsseverazioneTotale as RelAsseTotale + ,ISNULL(r.AsseverazioneTotaleNotificheAnalogiche,0) + ISNULL(r.AsseverazioneTotaleNotificheDigitali,0) as RelAsseTotaleNotifiche + ,ISNULL(c.[TotaleAnalogico],0) as ContestazioniTotaleAnalogico + ,ISNULL(c.[TotaleDigitale],0) as ContestazioniTotaleDigitale + ,ISNULL(c.[TotaleNotificheAnalogiche],0) as ContestazioniTotaleNotificheAnalogiche + ,ISNULL(c.[TotaleNotificheDigitali],0) as ContestazioniTotaleNotificheDigitali + ,ISNULL(c.[TotaleNotificheAnalogiche],0) + ISNULL(c.[TotaleNotificheDigitali],0) as ContestazioniNotificheTotale + ,ISNULL(c.[Totale],0) as ContestazioniTotale + ,nc.[TotaleAnalogico] - ISNULL(c.[TotaleAnalogico],0) - ISNULL(r.[TotaleAnalogico],0) - ISNULL(r.[AsseverazioneTotaleAnalogico],0) as DiffTotaleAnalogico + ,nc.[TotaleDigitale] - ISNULL(c.[TotaleDigitale],0) - ISNULL(r.[TotaleDigitale],0)- ISNULL(r.[AsseverazioneTotaleDigitale],0) as DiffTotaleDigitale + ,nc.[TotaleNotificheAnalogiche] - ISNULL(c.[TotaleNotificheAnalogiche],0) - ISNULL(r.[TotaleNotificheAnalogiche],0) - ISNULL(r.[AsseverazioneTotaleNotificheAnalogiche],0) as DiffTotaleNotificheAnalogiche + ,nc.[TotaleNotificheDigitali] - ISNULL(c.[TotaleNotificheDigitali],0) - ISNULL(r.[TotaleNotificheDigitali],0) - ISNULL(r.[AsseverazioneTotaleNotificheDigitali],0) as DiffTotaleNotificheDigitali + ,nc.[Totale] - ISNULL(c.[Totale],0) - ISNULL(r.[Totale],0)- ISNULL(r.[AsseverazioneTotale],0) as DiffTotale + ,nc.TotaleNotificheDigitali + nc.TotaleNotificheAnalogiche - ISNULL(c.TotaleNotificheDigitali,0)- ISNULL(c.TotaleNotificheAnalogiche,0) - ISNULL(r.TotaleNotificheDigitali,0) - ISNULL(r.TotaleNotificheAnalogiche,0) - ISNULL(r.AsseverazioneTotaleNotificheAnalogiche,0) - ISNULL(r.AsseverazioneTotaleNotificheAnalogiche,0) as DiffTotaleNotificheZero + +FROM [pfd].[NotificheCount] as nc +left outer join pfd.Enti as e +ON e.InternalIstitutionId = nc.internal_organization_id +left outer join + (SELECT + [internal_organization_id] + ,[contract_id] + ,[year] + ,[month] + ,SUM(ISNULL([TotaleAnalogico],0)) as [TotaleAnalogico] + ,SUM(ISNULL([TotaleDigitale],0)) as [TotaleDigitale] + ,SUM(ISNULL([TotaleNotificheAnalogiche],0)) as [TotaleNotificheAnalogiche] + ,SUM(ISNULL([TotaleNotificheDigitali],0)) as [TotaleNotificheDigitali] + ,SUM(ISNULL([Totale],0)) as [Totale] + ,SUM(ISNULL([AsseverazioneTotaleAnalogico],0)) as [AsseverazioneTotaleAnalogico] + ,SUM(ISNULL([AsseverazioneTotaleDigitale],0)) as [AsseverazioneTotaleDigitale] + ,SUM(ISNULL([AsseverazioneTotaleNotificheAnalogiche],0)) as [AsseverazioneTotaleNotificheAnalogiche] + ,SUM(ISNULL([AsseverazioneTotaleNotificheDigitali],0)) as [AsseverazioneTotaleNotificheDigitali] + ,SUM(ISNULL([AsseverazioneTotale],0)) as [AsseverazioneTotale] + from pfd.RelTestata + group by [internal_organization_id],[contract_id],[year], [month]) r + ON r.internal_organization_id = nc.internal_organization_id AND r.contract_id = nc.contract_id and r.year = nc.year and r.month = nc.month +left outer join + (SELECT cr.internal_organization_id + ,cr.contract_id + ,cr.year + ,cr.month + ,ISNULL(cr.[TotaleAnalogico],0) as [TotaleAnalogico] + ,ISNULL(cr.[TotaleDigitale],0) as [TotaleDigitale] + ,ISNULL(cr.[TotaleNotificheAnalogiche],0) as [TotaleNotificheAnalogiche] + ,ISNULL(cr.[TotaleNotificheDigitali],0) as [TotaleNotificheDigitali] + ,ISNULL(cr.[Totale],0) as [Totale] + FROM ( SELECT + [internal_organization_id] + ,[contract_id] + ,[year] + ,[month] + ,[TotaleAnalogico] + ,[TotaleDigitale] + ,[TotaleNotificheAnalogiche] + ,[TotaleNotificheDigitali] + ,[Totale] + ,[Iva] + ,[TotaleAnalogicoIva] + ,[TotaleDigitaleIva] + ,[TotaleIva] + ,[TipologiaFattura] + , ROW_NUMBER() OVER (PARTITION BY internal_organization_id, contract_id,year,month ORDER BY + (CASE WHEN TipologiaFattura = 'PRIMO SALDO' THEN 'A' + WHEN TipologiaFattura = 'SECONDO SALDO' THEN 'B' + END) DESC) AS RowNum + FROM [pfd].ContestazioniStorico + ) as cr + WHERE RowNum = 1) c + ON c.internal_organization_id = r.internal_organization_id and c.contract_id = r.contract_id and c.year = r.year and c.month = r.month +"; + private static string _sql = @" +SELECT + nc.[internal_organization_id] as IdEnte + ,e.description as RagioneSociale + ,nc.[contract_id] as IdContratto + ,r.TipologiaFattura as TipologiaFattura + ,nc.[year] as Anno + ,nc.[month] as Mese + ,ISNULL(c.[TotaleAnalogico],0) as ContestazioniTotaleAnalogico + ,ISNULL(c.[TotaleDigitale],0) as ContestazioniTotaleDigitale + ,ISNULL(c.[TotaleNotificheAnalogiche],0) as ContestazioniTotaleNotificheAnalogiche + ,ISNULL(c.[TotaleNotificheDigitali],0) as ContestazioniTotaleNotificheDigitali + ,ISNULL(c.[Totale],0) as ContestazioniTotale + ,ISNULL(c.[TotaleNotificheAnalogiche],0) + ISNULL(c.[TotaleNotificheDigitali],0) as ContestazioniNotificheTotale + ,ISNULL(r.[TotaleAnalogico],0) as RelTotaleAnalogico + ,ISNULL(r.[TotaleDigitale],0) as RelTotaleDigitale + ,ISNULL(r.[TotaleNotificheAnalogiche],0) as RelTotaleNotificheAnalogiche + ,ISNULL(r.[TotaleNotificheDigitali],0) as RelTotaleNotificheDigitali + ,ISNULL(r.[Totale],0) as RelTotale + ,ISNULL(r.[TotaleNotificheAnalogiche],0) + ISNULL(r.[TotaleNotificheDigitali],0) as RelTotaleNotifiche + ,ISNULL([AsseverazioneTotaleAnalogico],0) as RelAsseTotaleAnalogico + ,ISNULL([AsseverazioneTotaleDigitale],0) as RelAsseTotaleDigitale + ,ISNULL([AsseverazioneTotaleNotificheAnalogiche],0) as RelAsseTotaleNotificheAnalogiche + ,ISNULL([AsseverazioneTotaleNotificheDigitali],0) as RelAsseTotaleNotificheDigitali + ,ISNULL([AsseverazioneTotaleNotificheAnalogiche],0) + ISNULL([AsseverazioneTotaleNotificheDigitali],0) as RelAsseTotaleNotifiche + ,ISNULL([AsseverazioneTotale],0) as RelAsseTotale + ,nc.[TotaleAnalogico] as NotificheTotaleAnalogico + ,nc.[TotaleDigitale] as NotificheTotaleDigitale + ,nc.[TotaleNotificheAnalogiche] as NotificheTotaleNotificheAnalogiche + ,nc.[TotaleNotificheDigitali] as NotificheTotaleNotificheDigitali + ,nc.[Totale] as NotificheTotale + ,nc.[TotaleNotificheAnalogiche] + nc.[TotaleNotificheDigitali] as NotificheTotaleNotifiche + ,nc.[TotaleAnalogico] - ISNULL(c.[TotaleAnalogico],0) - ISNULL(r.[TotaleAnalogico],0) - ISNULL(r.[AsseverazioneTotaleAnalogico],0) as DiffTotaleAnalogico + ,nc.[TotaleDigitale] - ISNULL(c.[TotaleDigitale],0) - ISNULL(r.[TotaleDigitale],0)- ISNULL(r.[AsseverazioneTotaleDigitale],0) as DiffTotaleDigitale + ,nc.[TotaleNotificheAnalogiche] - ISNULL(c.[TotaleNotificheAnalogiche],0) - ISNULL(r.[TotaleNotificheAnalogiche],0) - ISNULL(r.[AsseverazioneTotaleNotificheAnalogiche],0) as DiffTotaleNotificheAnalogiche + ,nc.[TotaleNotificheDigitali] - ISNULL(c.[TotaleNotificheDigitali],0) - ISNULL(r.[TotaleNotificheDigitali],0) - ISNULL(r.[AsseverazioneTotaleNotificheDigitali],0) as DiffTotaleNotificheDigitali + ,nc.[Totale] - ISNULL(c.[Totale],0) - ISNULL(r.[Totale],0)- ISNULL(r.[AsseverazioneTotale],0) as DiffTotale + ,nc.TotaleNotificheDigitali + nc.TotaleNotificheAnalogiche - ISNULL(c.TotaleNotificheDigitali,0)- ISNULL(c.TotaleNotificheAnalogiche,0) - ISNULL(r.TotaleNotificheDigitali,0) - ISNULL(r.TotaleNotificheAnalogiche,0) - ISNULL(r.AsseverazioneTotaleNotificheAnalogiche,0) - ISNULL(r.AsseverazioneTotaleNotificheAnalogiche,0) as DiffTotaleNotificheZero + + FROM [pfd].[NotificheCount] as nc + left outer join pfd.Enti as e + ON e.InternalIstitutionId = nc.internal_organization_id + left outer join pfd.RelTestata as r + ON r.internal_organization_id = nc.internal_organization_id + AND r.contract_id = nc.contract_id + AND r.year= nc.year + AND r.month = nc.month + AND r.TipologiaFattura=@TipologiaFattura + left outer join pfd.ContestazioniStorico as c + ON c.internal_organization_id = nc.internal_organization_id + AND c.contract_id = nc.contract_id + AND c.year= nc.year + AND c.month = nc.month + AND c.TipologiaFattura=@TipologiaFattura +"; + + private static string _offSet = " OFFSET (@page-1)*@size ROWS FETCH NEXT @size ROWS ONLY"; + public static string OffSet() + { + return _offSet; + } + + public static string OrderBy() + { + return " ORDER BY r.[Totale] DESC"; + } + + public static string SelectAll() + { + return _sql; + } + public static string SelectAllNoTipologia() + { + return _sqlNoTipologiaFattura; + } + public static string SelectAllCount() + { + return _sqlCount; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataSQLBuilder.cs new file mode 100644 index 0000000..d8991a1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelTestataSQLBuilder.cs @@ -0,0 +1,152 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; + +internal static class RelTestataSQLBuilder +{ + + private static string _sqlDistinctTipologiaFatturaPagoPA = @" +SELECT TipologiaFattura +FROM ( + SELECT DISTINCT + TipologiaFattura, + year, + month, + CASE + WHEN TipologiaFattura LIKE '%PRIMO%' THEN 1 + WHEN TipologiaFattura LIKE '%SECONDO%' THEN 2 + WHEN TipologiaFattura LIKE '%SEMESTRALE%' THEN 3 + ELSE 4 -- Default case + END as ordine + FROM pfd.RelTestata +) AS t +"; + private static string _sqlDistinctTipologiaFattura = @" +SELECT TipologiaFattura +FROM ( + SELECT DISTINCT + TipologiaFattura, + year, + month, + internal_organization_id, + CASE + WHEN TipologiaFattura LIKE '%PRIMO%' THEN 1 + WHEN TipologiaFattura LIKE '%SECONDO%' THEN 2 + WHEN TipologiaFattura LIKE '%SEMESTRALE%' THEN 3 + ELSE 4 -- Default case + END as ordine + FROM pfd.RelTestata +) AS t +"; + + private static string _sqlCount = @" +SELECT Count(internal_organization_id) + FROM [pfd].[RelTestata] t + inner join pfd.Enti e + on e.InternalIstitutionId =t.internal_organization_id +"; + private static string _sql = @" +SELECT [internal_organization_id] as IdEnte + ,[description] as RagioneSociale + ,[contract_id] as IdContratto + ,[TipologiaFattura] + ,[year] as anno + ,[month] as mese + ,[TotaleAnalogico] + ,[TotaleDigitale] + ,[TotaleNotificheAnalogiche] + ,[TotaleNotificheDigitali] + ,[Totale] + ,[Iva] + ,[TotaleAnalogicoIva] + ,[TotaleDigitaleIva] + ,[TotaleIva] + ,[Caricata] + ,[AsseverazioneTotaleAnalogico] + ,[AsseverazioneTotaleDigitale] + ,[AsseverazioneTotaleNotificheAnalogiche] + ,[AsseverazioneTotaleNotificheDigitali] + ,[AsseverazioneTotale] + ,[AsseverazioneTotaleAnalogicoIva] + ,[AsseverazioneTotaleDigitaleIva] + ,[AsseverazioneTotaleIva] + FROM [pfd].[RelTestata] t + inner join pfd.Enti e + on e.InternalIstitutionId =t.internal_organization_id +"; + + private static string _sqlDettaglio = @" +SELECT [internal_organization_id] as IdEnte + ,[description] as RagioneSociale + ,[contract_id] as IdContratto + ,[TipologiaFattura] + ,[year] as anno + ,[month] as mese + ,[TotaleAnalogico] + ,[TotaleDigitale] + ,[TotaleNotificheAnalogiche] + ,[TotaleNotificheDigitali] + ,[Totale] + ,[Iva] + ,[TotaleAnalogicoIva] + ,[TotaleDigitaleIva] + ,[TotaleIva] + ,[AsseverazioneTotaleAnalogico] + ,[AsseverazioneTotaleDigitale] + ,[AsseverazioneTotaleNotificheAnalogiche] + ,[AsseverazioneTotaleNotificheDigitali] + ,[AsseverazioneTotale] + ,[AsseverazioneTotaleAnalogicoIva] + ,[AsseverazioneTotaleDigitaleIva] + ,[AsseverazioneTotaleIva] + ,IdDocumento + ,Cup + ,DataDocumento + ,CASE WHEN f.IdDatiFatturazione IS NULL THEN 0 ELSE 1 END as DatiFatturazione + ,[Caricata] + FROM [pfd].[RelTestata] t + inner join pfd.Enti e + on e.InternalIstitutionId =t.internal_organization_id + left outer join pfw.DatiFatturazione f + on f.FkIdEnte = t.internal_organization_id +"; + + private static string _offSet = " OFFSET (@page-1)*@size ROWS FETCH NEXT @size ROWS ONLY"; + public static string OffSet() + { + return _offSet; + } + + public static string OrderBy() + { + return " ORDER BY year DESC, month, [Totale] DESC"; + } + + public static string SelectAll() + { + return _sql; + } + + public static string SelectDettaglio() + { + return _sqlDettaglio; + } + + public static string SelectAllCount() + { + return _sqlCount; + } + + public static string SelectDistinctTipologiaFattura() + { + return _sqlDistinctTipologiaFattura; + } + + public static string SelectDistinctTipologiaFatturaPagoPA() + { + return _sqlDistinctTipologiaFatturaPagoPA; + } + + public static string OrderByDistinctTipologiaFattura() + { + return " ORDER BY ordine "; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelUploadSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelUploadSQLBuilder.cs new file mode 100644 index 0000000..85e15b3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/Builder/RelUploadSQLBuilder.cs @@ -0,0 +1,25 @@ +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; + +public static class RelUploadSQLBuilder +{ + private static string _sql = @" + SELECT TOP 10 [FkIdEnte] as idEnte + ,[contract_id] as idContratto + ,[TipologiaFattura] + ,[year] as anno + ,[month] as mese + ,[DataEvento] + ,[IdUtente] + ,[Azione] + ,[Hash] + ,description as RagioneSociale + FROM [schema][RelUpload] u + inner join [schema]Enti e + on e.InternalIstitutionId = u.FkIdEnte + "; + + public static string SelectAll() + { + return _sql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelRigheQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelRigheQueryGetByIdPersistence.cs new file mode 100644 index 0000000..e336cda --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelRigheQueryGetByIdPersistence.cs @@ -0,0 +1,70 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + +public class RelRigheQueryGetByIdPersistence(RelRigheQueryGetById command) : DapperBase, IQuery?> +{ + private readonly RelRigheQueryGetById _command = command; + private static readonly string _sqlSelectAll = RelRigheSQLBuilder.SelectAll(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var dati = RelTestataKey.Deserialize(_command.IdTestata!); + var where = string.Empty; + var idEnte = _command.AuthenticationInfo.IdEnte; + + where += " WHERE r.year=@anno"; + + if (!(dati.TipologiaFattura!.ToLower().Contains("var") + || dati.TipologiaFattura!.ToLower().Contains("semestrale") + || dati.TipologiaFattura!.ToLower().Contains("annuale"))) + where += " AND r.month=@mese"; + + + where += " AND r.internal_organization_id=@IdEnte "; + var anno = dati.Anno; + var mese = dati.Mese; + var tipoFattura = dati.TipologiaFattura; + var idContratto = dati.IdContratto; + + if (idEnte != dati.IdEnte) + throw new DomainException(""); + + if (!string.IsNullOrEmpty(tipoFattura)) + if (tipoFattura == TipologiaFattura.PRIMOSALDO) + where += $" AND (TipologiaFattura=@TipologiaFattura OR TipologiaFattura='{TipologiaFattura.ASSEVERAZIONE}')"; + else + where += " AND TipologiaFattura=@TipologiaFattura"; + else + throw new DomainException(""); + + + if (!string.IsNullOrEmpty(idContratto)) + where += " AND contract_id=@IdContratto"; + else + throw new DomainException(""); + + var sqlEnte = _sqlSelectAll; + sqlEnte += where; + + var query = new RelQueryDto + { + Anno = anno, + Mese = mese, + IdEnte = idEnte, + TipologiaFattura = tipoFattura, + IdContratto = idContratto + }; + + return await ((IDatabase)this).SelectAsync( + connection!, + sqlEnte, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdEntePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdEntePersistence.cs new file mode 100644 index 0000000..8b70008 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdEntePersistence.cs @@ -0,0 +1,82 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + +public class RelTestataQueryGetByIdEntePersistence(RelTestataQueryGetByIdEnte command) : DapperBase, IQuery +{ + private readonly RelTestataQueryGetByIdEnte _command = command; + private static readonly string _sqlSelectAll = RelTestataSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllCount = RelTestataSQLBuilder.SelectAllCount(); + private static readonly string _offSet = RelTestataSQLBuilder.OffSet(); + private static readonly string _orderBy = RelTestataSQLBuilder.OrderBy(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var rel = new RelTestataDto(); + var where = string.Empty; + var idEnte = _command.AuthenticationInfo.IdEnte; + var page = _command.Page; + var size = _command.Size; + where += " WHERE internal_organization_id=@IdEnte "; + + var caricata = _command.Caricata; + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura != null ? _command.TipologiaFattura : null; + var idContratto = _command.IdContratto ?? null; + + if (!string.IsNullOrEmpty(tipoFattura)) + where += " AND TipologiaFattura=@TipologiaFattura"; + + if (caricata.HasValue) + where += " AND caricata=@caricata"; + + if (anno.HasValue) + where += " AND year=@anno"; + if (mese.HasValue) + where += " AND month=@mese"; + if (!string.IsNullOrEmpty(idContratto)) + where += " AND contract_id=@IdContratto"; + + var orderBy = _orderBy; + + var sqlEnte = _sqlSelectAll; + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + var sql = string.Join(";", sqlEnte, sqlCount); + + var query = new RelQueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese, + Caricata = caricata, + IdEnte = idEnte + }; + + if (!string.IsNullOrEmpty(tipoFattura)) + query.TipologiaFattura = tipoFattura; + + if (!string.IsNullOrEmpty(idContratto)) + query.IdContratto = idContratto; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + rel.RelTestate = (await values.ReadAsync()).ToList(); + rel.Count = await values.ReadFirstAsync(); + return rel; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdPersistence.cs new file mode 100644 index 0000000..4b25cb6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByIdPersistence.cs @@ -0,0 +1,66 @@ +using System.Data; +using DocumentFormat.OpenXml.Drawing.Charts; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + +public class RelTestataQueryGetByIdPersistence(RelTestataQueryGetById command) : DapperBase, IQuery +{ + private readonly RelTestataQueryGetById _command = command; + private static readonly string _sqlSelectAll = RelTestataSQLBuilder.SelectDettaglio(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var dati = RelTestataKey.Deserialize(_command.IdTestata!); + var where = string.Empty; + var idEnte = _command.AuthenticationInfo.IdEnte; + where += " WHERE internal_organization_id=@IdEnte "; + var anno = dati.Anno; + var mese = dati.Mese; + var tipoFattura = dati.TipologiaFattura; + var idContratto = dati.IdContratto; + + if (_command.AuthenticationInfo.Auth == AuthType.SELFCARE) + { + if (idEnte != dati.IdEnte) + throw new DomainException(""); + } + else + idEnte = dati.IdEnte; + + if (!string.IsNullOrEmpty(tipoFattura)) + where += " AND TipologiaFattura=@TipologiaFattura"; + else + throw new DomainException(""); + + where += " AND year=@anno"; + where += " AND month=@mese"; + + if (!string.IsNullOrEmpty(idContratto)) + where += " AND contract_id=@IdContratto"; + else + throw new DomainException(""); + + var sqlEnte = _sqlSelectAll; + sqlEnte += where; + + var query = new RelQueryDto + { + Anno = anno, + Mese = mese, + IdEnte = idEnte, + TipologiaFattura = tipoFattura, + IdContratto = idContratto + }; + + return await ((IDatabase)this).SingleAsync( + connection!, + sqlEnte, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiPersistence.cs new file mode 100644 index 0000000..bb022fc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiPersistence.cs @@ -0,0 +1,91 @@ +using System.Data; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + +public class RelTestataQueryGetByListaEntiPersistence(RelTestataQueryGetByListaEnti command) : DapperBase, IQuery +{ + private readonly RelTestataQueryGetByListaEnti _command = command; + private static readonly string _sqlSelectAll = RelTestataSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllCount = RelTestataSQLBuilder.SelectAllCount(); + private static readonly string _offSet = RelTestataSQLBuilder.OffSet(); + private static readonly string _orderBy = RelTestataSQLBuilder.OrderBy(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var rel = new RelTestataDto(); + var where = string.Empty; + var page = _command.Page; + var size = _command.Size; + if (!_command.EntiIds.IsNullOrEmpty()) + where += $" WHERE internal_organization_id IN @entiIds"; + else + { + _command.EntiIds = null; + where += $" WHERE 1=1 "; + } + var caricata = _command.Caricata; + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura != null ? _command.TipologiaFattura : null; + var idContratto = _command.IdContratto ?? null; + + if (!string.IsNullOrEmpty(tipoFattura)) + where += " AND TipologiaFattura=@TipologiaFattura"; + + if (anno.HasValue) + where += " AND year=@anno"; + if (mese.HasValue) + where += " AND month=@mese"; + + if (!string.IsNullOrEmpty(idContratto)) + where += " AND contract_id=@IdContratto"; + + if (caricata.HasValue) + where += " AND caricata=@caricata"; + + var orderBy = _orderBy; + + var sqlEnte = _sqlSelectAll; + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + var sql = string.Join(";", sqlEnte, sqlCount); + + var query = new RelQueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese, + Caricata = caricata, + EntiIds = _command.EntiIds + }; + + if (!string.IsNullOrEmpty(tipoFattura)) + query.TipologiaFattura = tipoFattura; + + if (!string.IsNullOrEmpty(idContratto)) + query.IdContratto = idContratto; + + if (!_command.EntiIds.IsNullOrEmpty()) + query.EntiIds = _command.EntiIds; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + rel.RelTestate = (await values.ReadAsync()).ToList(); + rel.Count = await values.ReadFirstAsync(); + return rel; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiQuadraturaPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiQuadraturaPersistence.cs new file mode 100644 index 0000000..e4866a2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTestataQueryGetByListaEntiQuadraturaPersistence.cs @@ -0,0 +1,93 @@ +using System.Data; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + +public class RelTestataQueryGetByListaEntiQuadraturaPersistence(RelTestataQueryGetByListaEntiQuadratura command) : DapperBase, IQuery +{ + private readonly RelTestataQueryGetByListaEntiQuadratura _command = command; + private static readonly string _sqlSelectAll = RelTestataQuadraturaSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllNoTipologia = RelTestataQuadraturaSQLBuilder.SelectAllNoTipologia(); + private static readonly string _sqlSelectAllCount = RelTestataQuadraturaSQLBuilder.SelectAllCount(); + private static readonly string _offSet = RelTestataQuadraturaSQLBuilder.OffSet(); + private static readonly string _orderBy = RelTestataQuadraturaSQLBuilder.OrderBy(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var rel = new RelTestataQuadraturaDto(); + var where = string.Empty; + var page = _command.Page; + var size = _command.Size; + var anno = _command.Anno; + var mese = _command.Mese; + + if (anno.HasValue) + where += " WHERE nc.year=@anno"; + if (mese.HasValue) + where += " AND nc.month=@mese"; + + if (!_command.EntiIds.IsNullOrEmpty()) + where += $" AND nc.internal_organization_id IN @entiIds"; + + var caricata = _command.Caricata; + + var tipoFattura = _command.TipologiaFattura != null ? _command.TipologiaFattura : null; + var idContratto = _command.IdContratto ?? null; + + + if (!string.IsNullOrEmpty(idContratto)) + where += " AND nc.contract_id=@IdContratto"; + + if (caricata.HasValue) + where += " AND r.caricata=@caricata"; + + var orderBy = _orderBy; + + string? sqlEnte; + if (!string.IsNullOrEmpty(tipoFattura)) + sqlEnte = _sqlSelectAll; + else + sqlEnte = _sqlSelectAllNoTipologia; + + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + var sql = string.Join(";", sqlEnte, sqlCount); + + var query = new RelQueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese, + Caricata = caricata, + EntiIds = _command.EntiIds + }; + + if (!string.IsNullOrEmpty(tipoFattura)) + query.TipologiaFattura = tipoFattura; + + if (!string.IsNullOrEmpty(idContratto)) + query.IdContratto = idContratto; + + if (!_command.EntiIds.IsNullOrEmpty()) + query.EntiIds = _command.EntiIds; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + rel.Quadratura = (await values.ReadAsync()).ToList(); + rel.Count = await values.ReadFirstAsync(); + return rel; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByIdEntePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByIdEntePersistence.cs new file mode 100644 index 0000000..9af36bf --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByIdEntePersistence.cs @@ -0,0 +1,43 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + + +public class RelTipologieFattureByIdEntePersistence(RelTipologieFattureByIdEnte command) : DapperBase, IQuery?> +{ + private readonly RelTipologieFattureByIdEnte _command = command; + private static readonly string _sqlSelectAll = RelTestataSQLBuilder.SelectDistinctTipologiaFattura(); + private static readonly string _orderBy = RelTestataSQLBuilder.OrderByDistinctTipologiaFattura(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var where = string.Empty; + var idEnte = _command.AuthenticationInfo.IdEnte; + where += " WHERE internal_organization_id=@IdEnte "; + var anno = _command.Anno; + var mese = _command.Mese; + + where += " AND year=@anno"; + where += " AND month=@mese"; + + var sqlEnte = _sqlSelectAll; + sqlEnte += where + _orderBy; + sqlEnte = sqlEnte.Add(schema); + + var query = new RelQueryDto + { + Anno = anno, + Mese = mese, + IdEnte = idEnte + }; + + return await ((IDatabase)this).SelectAsync( + connection!, + sqlEnte, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByPagoPAPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByPagoPAPersistence.cs new file mode 100644 index 0000000..9d68ee6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelTipologieFattureByPagoPAPersistence.cs @@ -0,0 +1,39 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + + +public class RelTipologieFattureByPagoPAPersistence(RelTipologieFattureByPagoPA command) : DapperBase, IQuery?> +{ + private readonly RelTipologieFattureByPagoPA _command = command; + private static readonly string _sqlSelectAll = RelTestataSQLBuilder.SelectDistinctTipologiaFatturaPagoPA(); + private static readonly string _orderBy = RelTestataSQLBuilder.OrderByDistinctTipologiaFattura(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var anno = _command.Anno; + var mese = _command.Mese; + + var where = " WHERE year=@anno"; + where += " AND month=@mese"; + + var sqlEnte = _sqlSelectAll; + sqlEnte += where + _orderBy; + sqlEnte = sqlEnte.Add(schema); + + var query = new RelQueryDto + { + Anno = anno, + Mese = mese + }; + + return await ((IDatabase)this).SelectAsync( + connection!, + sqlEnte, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelUploadQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelUploadQueryGetByIdPersistence.cs new file mode 100644 index 0000000..bf08ef4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/Persistence/RelUploadQueryGetByIdPersistence.cs @@ -0,0 +1,52 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; + +public class RelUploadQueryGetByIdPersistence(RelUploadGetById command) : DapperBase, IQuery?> +{ + private readonly RelUploadGetById _command = command; + private static readonly string _sqlSelectAll = RelUploadSQLBuilder.SelectAll(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var where = string.Empty; + var idEnte = _command.AuthenticationInfo.IdEnte; + where += " WHERE FkIdEnte=@IdEnte "; + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura; + var idContratto = _command.IdContratto; + var azione = _command.Azione; + + where += " AND TipologiaFattura=@TipologiaFattura"; + where += " AND year=@anno"; + where += " AND month=@mese"; + where += " AND contract_id=@IdContratto"; + where += " AND azione=@azione"; + + var sqlEnte = _sqlSelectAll; + sqlEnte += where; + sqlEnte += " ORDER BY DataEvento DESC"; + sqlEnte = sqlEnte.Add(schema); + + var query = new RelQueryDto + { + Anno = anno, + Mese = mese, + IdEnte = idEnte, + TipologiaFattura = tipoFattura, + IdContratto = idContratto, + Azione = azione, + Size = 10 + }; + + return await ((IDatabase)this).SelectAsync( + connection!, + sqlEnte, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelRigheQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelRigheQueryGetById.cs new file mode 100644 index 0000000..8891bb6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelRigheQueryGetById.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelRigheQueryGetById(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdTestata { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetById.cs new file mode 100644 index 0000000..f3fca1c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetById.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTestataQueryGetById(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdTestata { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByIdEnte.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByIdEnte.cs new file mode 100644 index 0000000..877284b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByIdEnte.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTestataQueryGetByIdEnte(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdEnte { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } + public byte? Caricata { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEnti.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEnti.cs new file mode 100644 index 0000000..650188f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEnti.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTestataQueryGetByListaEnti(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? EntiIds { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } + public byte? Caricata { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEntiQuadratura.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEntiQuadratura.cs new file mode 100644 index 0000000..d1a0603 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTestataQueryGetByListaEntiQuadratura.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTestataQueryGetByListaEntiQuadratura(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? EntiIds { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } + public byte? Caricata { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByIdEnte.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByIdEnte.cs new file mode 100644 index 0000000..f645e06 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByIdEnte.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTipologieFattureByIdEnte(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByPagoPA.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByPagoPA.cs new file mode 100644 index 0000000..5e85ea4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelTipologieFattureByPagoPA.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTipologieFattureByPagoPA(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelUploadGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelUploadGetById.cs new file mode 100644 index 0000000..bf8b8f7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelUploadGetById.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations.Schema; +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelUploadGetById(IAuthenticationInfo authenticationInfo) : IRequest?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + + public string? IdEnte { get; set; } + public string? IdContratto { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? Azione { get; set; } = RelAzioneDocumento.Upload; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelVerificaByIdEnti.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelVerificaByIdEnti.cs new file mode 100644 index 0000000..7bee8b3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Queries/RelVerificaByIdEnti.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelVerificaByIdEnti(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelRigheQueryGetByIdHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelRigheQueryGetByIdHandler.cs new file mode 100644 index 0000000..2f6aac0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelRigheQueryGetByIdHandler.cs @@ -0,0 +1,26 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelRigheQueryGetByIdHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task?> Handle(RelRigheQueryGetById request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelRigheQueryGetByIdPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdEnteHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdEnteHandler.cs new file mode 100644 index 0000000..74b3825 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdEnteHandler.cs @@ -0,0 +1,56 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelTestataQueryGetByIdEnteHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(RelTestataQueryGetByIdEnte request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + var testata = await rs.Query(new RelTestataQueryGetByIdEntePersistence(request), ct); + var testate = new List(); + foreach (var t in testata!.RelTestate!) + { + //if (t.AsseverazioneTotaleIva > 0) + //{ + // var newTestata = new SimpleRelTestata() + // { + // Totale = t.AsseverazioneTotale, + // TotaleIva = t.AsseverazioneTotaleIva, + // TotaleAnalogico = t.AsseverazioneTotaleAnalogico, + // TotaleAnalogicoIva = t.AsseverazioneTotaleAnalogicoIva, + // TotaleDigitale = t.AsseverazioneTotaleDigitale, + // TotaleDigitaleIva = t.AsseverazioneTotaleDigitaleIva, + // TotaleNotificheAnalogiche = t.AsseverazioneTotaleNotificheAnalogiche, + // TotaleNotificheDigitali = t.AsseverazioneTotaleNotificheDigitali, + // TipologiaFattura = TipologiaFattura.ASSEVERAZIONE, + // IdContratto = t.IdContratto, + // Iva = t.Iva, + // IdEnte = t.IdEnte, + // Mese = t.Mese, + // Anno = t.Anno, + // RagioneSociale = t.RagioneSociale + // }; + // testate.Add(newTestata); + // testata.Count += 1; + //} + testate.Add(t); + } + testata.RelTestate = testate; + return testata; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdHandler.cs new file mode 100644 index 0000000..d034043 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByIdHandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelTestataQueryGetByIdHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(RelTestataQueryGetById request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelTestataQueryGetByIdPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiHandler.cs new file mode 100644 index 0000000..d024604 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiHandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelTestataQueryGetByListaEntiHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(RelTestataQueryGetByListaEnti request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelTestataQueryGetByListaEntiPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiQuadraturaHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiQuadraturaHandler.cs new file mode 100644 index 0000000..0aa3675 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTestataQueryGetByListaEntiQuadraturaHandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelTestataQueryGetByListaEntiQuadraturaHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(RelTestataQueryGetByListaEntiQuadratura request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelTestataQueryGetByListaEntiQuadraturaPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByIdEnteQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByIdEnteQueryHandler.cs new file mode 100644 index 0000000..9f01eb0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByIdEnteQueryHandler.cs @@ -0,0 +1,23 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTipologieFattureByIdEnteQueryHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task?> Handle(RelTipologieFattureByIdEnte request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelTipologieFattureByIdEntePersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByPagoPAQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByPagoPAQueryHandler.cs new file mode 100644 index 0000000..acbf023 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelTipologieFattureByPagoPAQueryHandler.cs @@ -0,0 +1,23 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +public class RelTipologieFattureByPagoPAQueryHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task?> Handle(RelTipologieFattureByPagoPA request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelTipologieFattureByPagoPAPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelUploadQueryGetByIdHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelUploadQueryGetByIdHandler.cs new file mode 100644 index 0000000..baa98e3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelUploadQueryGetByIdHandler.cs @@ -0,0 +1,26 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelUploadQueryGetByIdHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task?> Handle(RelUploadGetById request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new RelUploadQueryGetByIdPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelVerificaByIdEntiQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelVerificaByIdEntiQueryHandler.cs new file mode 100644 index 0000000..f07789c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/QueryHandlers/RelVerificaByIdEntiQueryHandler.cs @@ -0,0 +1,26 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.QueryHandlers; + +public class RelVerificaByIdEntiQueryHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(RelVerificaByIdEnti request, CancellationToken ct) + { + var verifica = new RelVerificaDto(); + //using var rs = await _factory.Create(cancellationToken: ct); + //return await rs.Query(new RelUploadQueryGetByIdPersistence(request), ct); + return verifica; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/EmailRelService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/EmailRelService.cs new file mode 100644 index 0000000..938e376 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/EmailRelService.cs @@ -0,0 +1,118 @@ +using System.Data; +using DocumentFormat.OpenXml.Spreadsheet; +using Microsoft.Data.SqlClient; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Services; + +public class EmailRelService(string cn) : IEmailRelService +{ + private readonly string _cn = cn; + private readonly string _sqlSelect = @" + SELECT + [internal_organization_id] as idEnte + ,[contract_id] as idContratto + ,[TipologiaFattura] + ,[year] as anno + ,[month] as mese + ,[PEC] as pec + ,[RagioneSociale] as ragionesociale + FROM [pfd].[EmailRel] + WHERE [year] = @year + AND [month] = @month + AND [TipologiaFattura] = @tipologiaFattura + AND Totale >0;"; + + private readonly string _sqlInsert = @" + INSERT INTO [pfd].[RelEmail] + ([FkIdEnte] + ,[contract_id] + ,[TipologiaFattura] + ,[year] + ,[month] + ,[DataEvento] + ,[Pec] + ,[Messaggio] + ,[RagioneSociale] + ,[Invio]) + VALUES + (@idEnte + ,@idContratto + ,@TipologiaFattura + ,@anno + ,@mese + ,@data + ,@pec + ,@messaggio + ,@RagioneSociale + ,@Invio);"; + + public IEnumerable? GetSenderEmail(int? anno, int? mese, string tipologiaFattura) + { + List emails = []; + try + { + using var conn = new SqlConnection(_cn); + conn.Open(); + using var cmd = new SqlCommand(); + cmd.Connection = conn; + cmd.Parameters.Add("@year", SqlDbType.Int).Value = anno; + cmd.Parameters.Add("@month", SqlDbType.Int).Value = mese; + cmd.Parameters.Add("@tipologiaFattura", SqlDbType.NVarChar).Value = tipologiaFattura; + cmd.CommandText = _sqlSelect; + var reader = cmd.ExecuteReader(); + if (reader.HasRows) + { + while (reader.Read()) + { + emails.Add(new RelEmail() + { + IdEnte = reader.GetString(0), + IdContratto = reader.GetString(1), + TipologiaFattura = reader.GetString(2), + Anno = reader.GetInt32(3), + Mese = reader.GetInt32(4), + Pec = reader.IsDBNull(5) ? string.Empty : reader.GetString(5), + RagioneSociale = reader.GetString(6) + }); + } + } + reader.Close(); + } + catch + { + + + } + return emails; + } + + public bool InsertTracciatoEmail(RelEmailTracking email) + { + try + { + using var conn = new SqlConnection(_cn); + conn.Open(); + using var cmd = new SqlCommand(); + cmd.Connection = conn; + cmd.Parameters.Add("@idEnte", SqlDbType.NVarChar).Value = email.IdEnte; + cmd.Parameters.Add("@idContratto", SqlDbType.NVarChar).Value = email.IdContratto; + cmd.Parameters.Add("@TipologiaFattura", SqlDbType.NVarChar).Value = email.TipologiaFattura; + cmd.Parameters.Add("@anno", SqlDbType.Int).Value = email.Anno; + cmd.Parameters.Add("@mese", SqlDbType.Int).Value = email.Mese; + cmd.Parameters.Add("@data", SqlDbType.NVarChar).Value = email.Data; + cmd.Parameters.Add("@pec", SqlDbType.NVarChar).Value = email.Pec; + cmd.Parameters.Add("@messaggio", SqlDbType.NVarChar).Value = email.Messaggio; + cmd.Parameters.Add("@RagioneSociale", SqlDbType.NVarChar).Value = email.RagioneSociale; + cmd.Parameters.Add("@Invio", SqlDbType.Bit).Value = email.Invio; + cmd.CommandText = _sqlInsert; + var rows = cmd.ExecuteNonQuery(); + return rows == 1; + } + catch + { + + return false; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/IEmailRelService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/IEmailRelService.cs new file mode 100644 index 0000000..859f3e7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/DatiRel/Services/IEmailRelService.cs @@ -0,0 +1,10 @@ +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiRel.Services +{ + public interface IEmailRelService + { + IEnumerable? GetSenderEmail(int? anno, int? mese, string tipologiaFattura); + bool InsertTracciatoEmail(RelEmailTracking email); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/CsvMapper.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/CsvMapper.cs new file mode 100644 index 0000000..11f809e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/CsvMapper.cs @@ -0,0 +1,136 @@ + +using CsvHelper.Configuration; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +public sealed class SimpleNotificaEnteDtoMap : ClassMap +{ + public SimpleNotificaEnteDtoMap() + { + Map(m => m.IdContratto).Name("contract_id").Index(0); + Map(m => m.CodiceFiscale).Name("tax_code").Index(1); + Map(m => m.PIva).Name("vat_number").Index(2); + Map(m => m.CAP).Name("zip_code").Index(3); + Map(m => m.StatoEstero).Name("foreign_state").Index(4); + Map(m => m.CostEuroInCentesimi).Name("cost_eurocent").Index(5); + Map(m => m.TimelineCategory).Name("timeline_category").Index(6); + Map(m => m.TipoNotifica).Name("paper_product_type").Index(7); + Map(m => m.IdNotifica).Name("event_id").Index(8); + Map(m => m.IUN).Name("iun").Index(9); + Map(m => m.Consolidatore).Name("consolidatore").Index(10); + Map(m => m.Recapitista).Name("recapitista").Index(11); + Map(m => m.DataInvio).Name("notification_sent_at").Index(12); + Map(m => m.Data).Name("event_timestamp").Index(13); + Map(m => m.Anno).Name("year").Index(14); + Map(m => m.Mese).Name("month").Index(15); + Map(m => m.AnnoMeseGiorno).Name("daily").Index(16); + Map(m => m.NoteEnte).Name("Note Ente").Index(17); + Map(m => m.RispostaEnte).Name("Risposta Ente").Index(18); + Map(m => m.NoteSend).Name("Risposta Send").Index(19); + Map(m => m.NoteRecapitista).Name("Risposta Recapitista").Index(20); + Map(m => m.NoteConsolidatore).Name("Risposta Consolidatore").Index(21); + Map(m => m.TipoContestazione).Name("Tipo Contestazione").Index(22); + Map(m => m.Contestazione).Name("Contestazione").Index(23); + Map(m => m.TipologiaFattura).Name("Tipologia Fattura").Index(24); + } +} + +public class SimpleNotificaPagoPADtoMap : ClassMap +{ + public SimpleNotificaPagoPADtoMap() + { + Map(m => m.IdContratto).Name("contract_id").Index(0); + Map(m => m.CodiceFiscale).Name("tax_code").Index(1); + Map(m => m.PIva).Name("vat_number").Index(2); + Map(m => m.CAP).Name("zip_code").Index(3); + Map(m => m.StatoEstero).Name("foreign_state").Index(4); + Map(m => m.NumberOfPages).Name("number_of_pages").Index(5); + Map(m => m.GEnvelopeWeight).Name("g_envelope_weight").Index(6); + Map(m => m.CostEuroInCentesimi).Name("cost_eurocent").Index(7); + Map(m => m.TimelineCategory).Name("timeline_category").Index(8); + Map(m => m.TipoNotifica).Name("paper_product_type").Index(9); + Map(m => m.IdNotifica).Name("event_id").Index(10); + Map(m => m.IUN).Name("iun").Index(11); + Map(m => m.Consolidatore).Name("consolidatore").Index(12); + Map(m => m.Recapitista).Name("recapitista").Index(13); + Map(m => m.DataInvio).Name("notification_sent_at").Index(14); + Map(m => m.IdEnte).Name("internal_organization_id").Index(15); + Map(m => m.RagioneSociale).Name("description").Index(16); + Map(m => m.Data).Name("event_timestamp").Index(17); + Map(m => m.RecipientIndex).Name("recipient_index").Index(18); + Map(m => m.RecipientType).Name("recipient_type").Index(19); + Map(m => m.RecipientId).Name("recipient_id").Index(20); + Map(m => m.Anno).Name("year").Index(21); + Map(m => m.Mese).Name("month").Index(22); + Map(m => m.AnnoMeseGiorno).Name("daily").Index(23); + Map(m => m.ItemCode).Name("item_code").Index(24); + Map(m => m.NotificationRequestId).Name("notification_request_id").Index(25); + Map(m => m.RecipientTaxId).Name("recipient_tax_id").Index(26); + Map(m => m.NoteEnte).Name("Note Ente").Index(27); + Map(m => m.RispostaEnte).Name("Risposta Ente").Index(28); + Map(m => m.NoteSend).Name("Risposta Send").Index(29); + Map(m => m.NoteRecapitista).Name("Risposta Recapitista").Index(30); + Map(m => m.NoteConsolidatore).Name("Risposta Consolidatore").Index(31); + Map(m => m.TipoContestazione).Name("Tipo Contestazione").Index(31); + Map(m => m.Contestazione).Name("Contestazione").Index(33); + Map(m => m.StatoContestazione).Name("Stato contestazione").Index(34); + Map(m => m.TipologiaFattura).Name("Tipologia Fattura").Index(35); + } +} + +public class RigheRelDtoEnteMap : ClassMap +{ + public RigheRelDtoEnteMap() + { + Map(m => m.IdContratto).Name("contract_id").Index(0); + Map(m => m.CodiceFiscale).Name("tax_code").Index(1); + Map(m => m.PIva).Name("vat_number").Index(2); + Map(m => m.CAP).Name("zip_code").Index(3); + Map(m => m.StatoEstero).Name("foreign_state").Index(4); + Map(m => m.Cost).Name("costo €").Index(5); + Map(m => m.TimelineCategory).Name("timeline_category").Index(6); + Map(m => m.TipoNotifica).Name("paper_product_type").Index(7); + Map(m => m.IdNotifica).Name("event_id").Index(8); + Map(m => m.IUN).Name("iun").Index(9); + Map(m => m.Recapitista).Name("recapitista").Index(10); + Map(m => m.DataInvio).Name("notification_sent_at").Index(11); + Map(m => m.Data).Name("event_timestamp").Index(12); + Map(m => m.Anno).Name("year").Index(13); + Map(m => m.Mese).Name("month").Index(14); + Map(m => m.AnnoMeseGiorno).Name("daily").Index(15); + } +} + +public class RigheRelDtoPagoPAMap : ClassMap +{ + public RigheRelDtoPagoPAMap() + { + Map(m => m.IdContratto).Name("contract_id").Index(0); + Map(m => m.CodiceFiscale).Name("tax_code").Index(1); + Map(m => m.PIva).Name("vat_number").Index(2); + Map(m => m.CAP).Name("zip_code").Index(3); + Map(m => m.StatoEstero).Name("foreign_state").Index(4); + Map(m => m.NumberOfPages).Name("number_of_pages").Index(5); + Map(m => m.GEnvelopeWeight).Name("g_envelope_weight").Index(6); + Map(m => m.Cost).Name("costo €").Index(7); + Map(m => m.TimelineCategory).Name("timeline_category").Index(8); + Map(m => m.TipoNotifica).Name("paper_product_type").Index(9); + Map(m => m.IdNotifica).Name("event_id").Index(10); + Map(m => m.IUN).Name("iun").Index(11); + Map(m => m.Recapitista).Name("recapitista").Index(13); + Map(m => m.DataInvio).Name("notification_sent_at").Index(14); + Map(m => m.IdEnte).Name("internal_organization_id").Index(15); + Map(m => m.Data).Name("event_timestamp").Index(16); + Map(m => m.RecipientIndex).Name("recipient_index").Index(17); + Map(m => m.RecipientType).Name("recipient_type").Index(18); + Map(m => m.RecipientId).Name("recipient_id").Index(19); + Map(m => m.Anno).Name("year").Index(20); + Map(m => m.Mese).Name("month").Index(21); + Map(m => m.AnnoMeseGiorno).Name("daily").Index(22); + Map(m => m.ItemCode).Name("item_code").Index(23); + Map(m => m.NotificationRequestId).Name("notification_request_id").Index(24); + Map(m => m.RecipientTaxId).Name("recipient_tax_id").Index(25); + Map(m => m.TipologiaFattura).Name("Tipologia Fattura").Index(33); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ExcelExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ExcelExtensions.cs new file mode 100644 index 0000000..23f27dc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ExcelExtensions.cs @@ -0,0 +1,537 @@ +using System.Data; +using ClosedXML.Excel; +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; + +namespace PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +public static class ExcelExtensions +{ + #region simple formats + + internal static string To(this bool? value) + { + if (value.HasValue && value.Value == true) + return "SI"; + else if (value.HasValue && value.Value == false) + return "NO"; + return string.Empty; + } + + #endregion + + internal static ForegroundColor TranslateForeground(System.Drawing.Color fillColor) + { + return new ForegroundColor() + { + Rgb = new HexBinaryValue() + { + Value = String.Format("{0:X2}{1:X2}{2:X2}{3:X3}", fillColor.R, fillColor.G, fillColor.B, fillColor.A) + } + }; + } + internal static WorkbookStylesPart AddStyleSheet(this SpreadsheetDocument spreadsheet) + { + var stylesheet = spreadsheet.WorkbookPart!.AddNewPart(); + var workbookstylesheet = new Stylesheet(); + + #region Number format + uint DATETIME_FORMAT = 164; + uint DIGITS4_FORMAT = 165; + var numberingFormats = new NumberingFormats(); + numberingFormats.Append(new NumberingFormat // Datetime format + { + NumberFormatId = UInt32Value.FromUInt32(DATETIME_FORMAT), + FormatCode = StringValue.FromString("dd/mm/yyyy hh:mm:ss") + }); + numberingFormats.Append(new NumberingFormat // four digits format + { + NumberFormatId = UInt32Value.FromUInt32(DIGITS4_FORMAT), + FormatCode = StringValue.FromString("0000") + }); + numberingFormats.Count = UInt32Value.FromUInt32((uint)numberingFormats.ChildElements.Count); + #endregion + + #region Fonts + var fonts = new Fonts(); + fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font() // Font index 0 - default + { + FontName = new FontName { Val = StringValue.FromString("Calibri") }, + FontSize = new FontSize { Val = DoubleValue.FromDouble(11) } + }); + fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font() // Font index 1 + { + FontName = new FontName { Val = StringValue.FromString("Arial") }, + FontSize = new FontSize { Val = DoubleValue.FromDouble(11) }, + Bold = new Bold() + }); + fonts.Count = UInt32Value.FromUInt32((uint)fonts.ChildElements.Count); + #endregion + + #region Fills + var fills = new Fills(); + fills.Append(new Fill() // Fill index 0 + { + PatternFill = new PatternFill { PatternType = PatternValues.None } + }); + fills.Append(new Fill() // Fill index 1 + { + PatternFill = new PatternFill { PatternType = PatternValues.Gray125 } + }); + fills.Append(new Fill() // Fill index 2 + { + PatternFill = new PatternFill + { + PatternType = PatternValues.Solid, + ForegroundColor = TranslateForeground(System.Drawing.Color.LightBlue), + BackgroundColor = new BackgroundColor { Rgb = TranslateForeground(System.Drawing.Color.LightBlue).Rgb } + } + }); + fills.Append(new Fill() // Fill index 3 + { + PatternFill = new PatternFill + { + PatternType = PatternValues.Solid, + ForegroundColor = TranslateForeground(System.Drawing.Color.LightSkyBlue), + BackgroundColor = new BackgroundColor { Rgb = TranslateForeground(System.Drawing.Color.LightBlue).Rgb } + } + }); + fills.Count = UInt32Value.FromUInt32((uint)fills.ChildElements.Count); + #endregion + + #region Borders + var borders = new Borders(); + borders.Append(new Border // Border index 0: no border + { + LeftBorder = new LeftBorder(), + RightBorder = new RightBorder(), + TopBorder = new TopBorder(), + BottomBorder = new BottomBorder(), + DiagonalBorder = new DiagonalBorder() + }); + borders.Append(new Border //Boarder Index 1: All + { + LeftBorder = new LeftBorder { Style = BorderStyleValues.Thin }, + RightBorder = new RightBorder { Style = BorderStyleValues.Thin }, + TopBorder = new TopBorder { Style = BorderStyleValues.Thin }, + BottomBorder = new BottomBorder { Style = BorderStyleValues.Thin }, + DiagonalBorder = new DiagonalBorder() + }); + borders.Append(new Border // Boarder Index 2: Top and Bottom + { + LeftBorder = new LeftBorder(), + RightBorder = new RightBorder(), + TopBorder = new TopBorder { Style = BorderStyleValues.Thin }, + BottomBorder = new BottomBorder { Style = BorderStyleValues.Thin }, + DiagonalBorder = new DiagonalBorder() + }); + borders.Count = UInt32Value.FromUInt32((uint)borders.ChildElements.Count); + #endregion + + #region Cell Style Format + var cellStyleFormats = new CellStyleFormats(); + cellStyleFormats.Append(new CellFormat // Cell style format index 0: no format + { + NumberFormatId = 0, + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0 + }); + cellStyleFormats.Count = UInt32Value.FromUInt32((uint)cellStyleFormats.ChildElements.Count); + #endregion + + #region Cell format + var cellFormats = new CellFormats(); + cellFormats.Append(new CellFormat() // Cell format index 0 + { + FontId = 0, + FillId = 0, + BorderId = 0, + NumberFormatId = 0, + FormatId = 0 + }); + cellFormats.Append(new CellFormat() + { + Alignment = new Alignment() { WrapText = true } + }); + cellFormats.Append(new CellFormat // CellFormat index 2 + { + NumberFormatId = 14, // 14 = 'mm-dd-yy'. Standard Date format; + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true) + }); + cellFormats.Append(new CellFormat // Cell format index 3: Standard Number format with 2 decimal placing + { + NumberFormatId = 4, // 4 = '#,##0.00'; + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true) + }); + cellFormats.Append(new CellFormat // Cell formt index 4 + { + NumberFormatId = DATETIME_FORMAT, // 164 = 'dd/mm/yyyy hh:mm:ss'. Standard Datetime format; + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true) + }); + cellFormats.Append(new CellFormat // Cell format index 5 + { + NumberFormatId = 3, // 3 #,##0 + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true) + }); + cellFormats.Append(new CellFormat // Cell format index 6 + { + NumberFormatId = 10, // 10 0.00 %, + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true) + }); + cellFormats.Append(new CellFormat // Cell format index 7 + { + NumberFormatId = DIGITS4_FORMAT, // Format cellas 4 digits. If less than 4 digits, prepend 0 in front + FontId = 0, + FillId = 0, + BorderId = 0, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true) + }); + cellFormats.Append(new CellFormat // Cell format header + { + NumberFormatId = 49, + FontId = 1, + FillId = 0, + BorderId = 2, + FormatId = 0, + ApplyNumberFormat = BooleanValue.FromBoolean(true), + Alignment = new Alignment() { WrapText = false, Horizontal = HorizontalAlignmentValues.Center } + }); + cellFormats.Count = UInt32Value.FromUInt32((uint)cellFormats.ChildElements.Count); + #endregion + + + // Append FONTS, FILLS , BORDERS & CellFormats to stylesheet + workbookstylesheet.Append(fonts); + workbookstylesheet.Append(fills); + workbookstylesheet.Append(borders); + workbookstylesheet.Append(cellFormats); + + // Finalize + stylesheet.Stylesheet = workbookstylesheet; + stylesheet.Stylesheet.Save(); + + return stylesheet; + } + + public static bool SheetExist(this SpreadsheetDocument doc, string sheetName) + { + if (doc == null) throw new ArgumentNullException("SpreadsheetDocument"); + if (doc.WorkbookPart == null) throw new ArgumentNullException("WorkbookPart"); + var wbPart = doc.WorkbookPart; + Sheet sheet = wbPart.Workbook.Descendants().FirstOrDefault(s => s.Name == sheetName)!; + return sheet != null; + } + public static bool IsValidDecimal(object input) + { + // Ensure the input is a string + string inputStr = input.ToString(); + + // Check if the input can be parsed as an integer + if (long.TryParse(inputStr, out _)) + return false; + + // Check if the input starts with a leading zero (but not just "0") + if (inputStr.Length > 1 && inputStr.StartsWith("0")) + return false; + + // Try to parse as decimal + if (decimal.TryParse(inputStr, out _)) + return true; + + return false; + } + + public static MemoryStream ToExcel(this DataSet ds) + { + var memoryStream = new MemoryStream(); + using (var workbook = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook)) + { + var workbookPart = workbook.AddWorkbookPart(); + workbook.WorkbookPart!.Workbook = new Workbook(); + workbook.WorkbookPart.Workbook.Sheets = new Sheets(); + + int maxDigitFont = 11; // weight font + + // add styles + workbook.AddStyleSheet(); + + uint sheetId = 1; + + foreach (DataTable table in ds.Tables) + { + var numbersOfChars = new Dictionary(); + for (var j = 0; j < table.Columns.Count; j++) + { + var len = table.Columns[j].Caption.Length; + numbersOfChars.TryGetValue(j, out var value); + if (value == null) + numbersOfChars.TryAdd(j, len); + else if (value < len) + numbersOfChars[j] = len; + } + + int lp = 1; + + var sheetPart = workbook.WorkbookPart.AddNewPart(); + var sheetData = new SheetData(); + sheetPart.Worksheet = new Worksheet(sheetData); + + var sheets = workbook.WorkbookPart.Workbook.GetFirstChild(); + var relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart); + + if (sheets!.Elements().Any()) + sheetId = sheets.Elements().Select(s => s.SheetId!.Value).Max() + 1; + + var sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName }; + + sheets.Append(sheet); + + var headerRow = new Row(); + var columns = new Dictionary(); + var clmns = new Columns(); + var index = 0; + foreach (DataColumn column in table.Columns) + { + columns.Add(column.ColumnName, (XCellStyle)column.ExtendedProperties["Style"]!); + var widthPixels = Math.Truncate(((256 * numbersOfChars[index]!.Value + Math.Truncate(128f / maxDigitFont)) / 256f) * maxDigitFont); + var width = Math.Truncate(((widthPixels - 5f) / maxDigitFont * 100f + 0.5f) / 100f); + var cln = new Column + { + Min = Convert.ToUInt32(index + 1), + Max = Convert.ToUInt32(index + 1), + Width = width + 5, + CustomWidth = true, + Style = Convert.ToUInt32(0), + }; + clmns.Append(cln); + index++; + } + + var sheetdata = sheetPart.Worksheet.GetFirstChild(); + sheetPart.Worksheet.InsertBefore(clmns, sheetdata); + + var freezeRow = lp; + foreach (DataColumn column in table.Columns) + { + var cell = new Cell + { + DataType = CellValues.String, + CellValue = new CellValue(column.Caption), + StyleIndex = Convert.ToUInt32(XCellStyle.Header), + }; + headerRow.AppendChild(cell); + } + sheetData.AppendChild(headerRow); + + foreach (DataRow dsrow in table.Rows) + { + var newRow = new Row(); + foreach (var col in columns) + { + var (cellType, value, type) = TypeFinder.Get(dsrow[col.Key]!); + + CellValue? cellvalue = null; + CellValues cellvalues = cellType; + var styleIndex = Convert.ToUInt32(col.Value); + + if (value == null) + cellvalue = new CellValue(string.Empty); + else if (type == typeof(long)) + cellvalue = new CellValue(Convert.ToDecimal(value)); + else if (type == typeof(string) && IsValidDecimal(value)) + { + cellvalues = CellValues.Number; + styleIndex = 3; + cellvalue = new CellValue(Convert.ToDecimal(value)); + } + else if (type == typeof(DateTime)) + { + cellvalues = CellValues.String; + cellvalue = new CellValue(((DateTime)value).ToString("yyyy/MM/dd HH:mm:ss")); + } + else + cellvalue = new CellValue((dynamic)value); + var cell = new Cell + { + DataType = cellvalues, + CellValue = cellvalue, + StyleIndex = styleIndex, + }; + newRow.AppendChild(cell); + } + sheetData.AppendChild(newRow); + } + } + workbook.Close(); + } + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + public static MemoryStream ToExcelData(this DataSet ds) + { + var memoryStream = new MemoryStream(); + using (var workbook = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook)) + { + var workbookPart = workbook.AddWorkbookPart(); + workbook.WorkbookPart!.Workbook = new Workbook(); + workbook.WorkbookPart.Workbook.Sheets = new Sheets(); + + int maxDigitFont = 11; // weight font + + // add styles + workbook.AddStyleSheet(); + + uint sheetId = 1; + + foreach (DataTable table in ds.Tables) + { + var numbersOfChars = new Dictionary(); + for (var j = 0; j < table.Columns.Count; j++) + { + var len = table.Columns[j].Caption.Length; + numbersOfChars.TryGetValue(j, out var value); + if (value == null) + numbersOfChars.TryAdd(j, len); + else if (value < len) + numbersOfChars[j] = len; + } + + int lp = 1; + + var sheetPart = workbook.WorkbookPart.AddNewPart(); + var sheetData = new SheetData(); + sheetPart.Worksheet = new Worksheet(sheetData); + + var sheets = workbook.WorkbookPart.Workbook.GetFirstChild(); + var relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart); + + if (sheets!.Elements().Any()) + sheetId = sheets.Elements().Select(s => s.SheetId!.Value).Max() + 1; + + var sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName }; + + sheets.Append(sheet); + + var headerRow = new Row(); + var columns = new Dictionary(); + var clmns = new Columns(); + int index = 0; + foreach (DataColumn column in table.Columns) + { + columns.Add(column.ColumnName, (XCellStyle)column.ExtendedProperties["Style"]!); + var widthPixels = Math.Truncate(((256 * numbersOfChars[index]!.Value + Math.Truncate(128f / maxDigitFont)) / 256f) * maxDigitFont); + var width = Math.Truncate(((widthPixels - 5f) / maxDigitFont * 100f + 0.5f) / 100f); + var cln = new Column + { + Min = Convert.ToUInt32(index + 1), + Max = Convert.ToUInt32(index + 1), + Width = width + 5, + CustomWidth = true, + Style = Convert.ToUInt32(0), + }; + clmns.Append(cln); + index++; + } + + var sheetdata = sheetPart.Worksheet.GetFirstChild(); + sheetPart.Worksheet.InsertBefore(clmns, sheetdata); + + var freezeRow = lp; + foreach (DataColumn column in table.Columns) + { + var cell = new Cell + { + DataType = CellValues.String, + CellValue = new CellValue(column.Caption), + StyleIndex = Convert.ToUInt32(XCellStyle.Header), + }; + headerRow.AppendChild(cell); + } + sheetData.AppendChild(headerRow); + + foreach (DataRow dsrow in table.Rows) + { + var newRow = new Row(); + foreach (var col in columns) + { + var (cellType, value, type) = TypeFinder.Get(dsrow[col.Key]!); + CellValue? cellvalue = null; + var cellvalues = cellType; + UInt32 styleIndex = Convert.ToUInt32(col.Value); + if (value == null) + cellvalue = new CellValue(string.Empty); + else if (type == typeof(long)) + cellvalue = new CellValue(Convert.ToDecimal(value)); + else if (type == typeof(DateTime)) + { + cellvalues = CellValues.Date; + cellvalue = new CellValue(((DateTime)value).ToString("yyyy-MM-dd")); + styleIndex = 2; + } + else + cellvalue = new CellValue((dynamic)value); + var cell = new Cell + { + DataType = cellvalues, + CellValue = cellvalue, + StyleIndex = styleIndex, + }; + newRow.AppendChild(cell); + } + sheetData.AppendChild(newRow); + } + } + } + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + public static DataTable ReadAsseverazioneExcel(this MemoryStream stream) + { + var table = new DataTable(); + var workbook = new XLWorkbook(stream); + var ws = workbook.Worksheet(1); + table.Columns.Add(0.ToString()); + table.Columns.Add(1.ToString()); + table.Columns.Add(2.ToString()); + table.Columns.Add(3.ToString()); + table.Columns.Add(4.ToString()); + for (var i = 0; i < ws.Rows().Count(); i++) + { + var tempRow = table.NewRow(); + tempRow[0] = ws.Cell($"A{i + 1}").Value; + tempRow[1] = ws.Cell($"B{i + 1}").Value; + tempRow[2] = ws.Cell($"C{i + 1}").Value; + tempRow[3] = ws.Cell($"D{i + 1}").Value; + tempRow[4] = ws.Cell($"E{i + 1}").Value; + table.Rows.Add(tempRow); + } + table.Rows.RemoveAt(0); + return table; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/HeaderAttribute.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/HeaderAttribute.cs new file mode 100644 index 0000000..c765bb1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/HeaderAttribute.cs @@ -0,0 +1,34 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] +public class HeaderAttribute(string? caption, bool readOnly = false) : Attribute +{ + public string? Caption { get; internal set; } = caption; + public string? Name { get; set; } + public bool ReadOnly { get; internal set; } = readOnly; + public Type? Type { get; set; } + public short Order { get; set; } = 0; + public XCellStyle Style { get; set; } = XCellStyle.None; +} + +[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] +public class HeaderAttributev2(string? caption, bool readOnly = false) : Attribute +{ + public string? Caption { get; internal set; } = caption; + public string? Name { get; set; } + public bool ReadOnly { get; internal set; } = readOnly; + public Type? Type { get; set; } + public short Order { get; set; } = 0; + public XCellStyle Style { get; set; } = XCellStyle.None; +} + +[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] +public class HeaderAttributeRECCON(string? caption, bool readOnly = false) : Attribute +{ + public string? Caption { get; internal set; } = caption; + public string? Name { get; set; } + public bool ReadOnly { get; internal set; } = readOnly; + public Type? Type { get; set; } + public short Order { get; set; } = 0; + public XCellStyle Style { get; set; } = XCellStyle.None; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ReflectionExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ReflectionExtensions.cs new file mode 100644 index 0000000..8e13b80 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/ReflectionExtensions.cs @@ -0,0 +1,308 @@ +using System.Data; +using System.Reflection; +using DocumentFormat.OpenXml.Presentation; + +namespace PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +public static class ReflectionExtensions +{ + internal static List GetHeaderRECCON() + { + var list = new List(); + + var myPropertyInfo = typeof(T).GetProperties(); + for (var i = 0; i < myPropertyInfo.Length; i++) + { + var customAttribute = (HeaderAttributeRECCON)Attribute.GetCustomAttribute(myPropertyInfo[i], typeof(HeaderAttributeRECCON))!; + if (customAttribute != null) + { + customAttribute.Type = myPropertyInfo[i].PropertyType; + customAttribute.Name = myPropertyInfo[i].Name; + list.Add(customAttribute); + } + } + return [.. list.OrderBy(x => x.Order)]; + } + + + internal static List GetHeadersv2() + { + var list = new List(); + + var myPropertyInfo = typeof(T).GetProperties(); + for (var i = 0; i < myPropertyInfo.Length; i++) + { + var customAttribute = (HeaderAttributev2)Attribute.GetCustomAttribute(myPropertyInfo[i], typeof(HeaderAttributev2))!; + if (customAttribute != null) + { + customAttribute.Type = myPropertyInfo[i].PropertyType; + customAttribute.Name = myPropertyInfo[i].Name; + list.Add(customAttribute); + } + } + return [.. list.OrderBy(x => x.Order)]; + } + + internal static List GetHeaders() + { + var list = new List(); + + var myPropertyInfo = typeof(T).GetProperties(); + for (var i = 0; i < myPropertyInfo.Length; i++) + { + var customAttribute = (HeaderAttribute)Attribute.GetCustomAttribute(myPropertyInfo[i], typeof(HeaderAttribute))!; + if (customAttribute != null) + { + customAttribute.Type = myPropertyInfo[i].PropertyType; + customAttribute.Name = myPropertyInfo[i].Name; + list.Add(customAttribute); + } + } + return [.. list.OrderBy(x => x.Order)]; + } + + internal static (DataTable, List) ToTable() + { + var headers = GetHeaders(); + var table = new DataTable(nameof(T)); + + foreach (var hh in headers) + { + var column = new DataColumn + { + DataType = Nullable.GetUnderlyingType(hh.Type!) ?? hh.Type, + ColumnName = hh.Name, + Caption = hh.Caption, + ReadOnly = hh.ReadOnly + }; + column.ExtendedProperties.Add("Style", hh.Style); + table.Columns.Add(column); + } + + return (table, headers); + } + + + public static dynamic CalculateHeaderAttribute(this T model) + { + var selectedProperties = GetPropertiesWithAttribute(); + + dynamic dynamicObject = new System.Dynamic.ExpandoObject(); + foreach (var property in selectedProperties) + { + ((IDictionary)dynamicObject)[property.Name] = property.Name; + } + return dynamicObject; + } + + public static IEnumerable ToHeaderAttributeCsv(this IEnumerable lista) + { + var selectedProperties = GetPropertiesWithAttribute(); + return lista.Select(item => + { + dynamic dynamicObject = new System.Dynamic.ExpandoObject(); + foreach (var property in selectedProperties) + { + ((IDictionary)dynamicObject)[property.Name] = property.GetValue(item)!; + } + return dynamicObject; + }); + } + + public static IEnumerable ToHeaderAttributev2Csv(this IEnumerable lista) + { + var selectedProperties = GetPropertiesWithAttribute(); + return lista.Select(item => + { + dynamic dynamicObject = new System.Dynamic.ExpandoObject(); + foreach (var property in selectedProperties) + { + ((IDictionary)dynamicObject)[property.Name] = property.GetValue(item)!; + } + return dynamicObject; + }); + } + static IEnumerable GetPropertiesWithAttribute() where TAttribute : Attribute + { + return typeof(T).GetProperties() + .Where(prop => prop.GetCustomAttribute() != null); + } + + internal static (DataTable, List) ToTablev2(string? dataTableName = null) + { + var headers = GetHeadersv2(); + var table = new DataTable(dataTableName ?? nameof(T)); + foreach (var hh in headers) + { + var column = new DataColumn + { + DataType = Nullable.GetUnderlyingType(hh.Type!) ?? hh.Type, + ColumnName = hh.Name, + Caption = hh.Caption, + ReadOnly = hh.ReadOnly + }; + column.ExtendedProperties.Add("Style", hh.Style); + table.Columns.Add(column); + } + return (table, headers); + } + + internal static (DataTable, List) ToTableRECCON() + { + var headers = GetHeaderRECCON(); + var table = new DataTable(nameof(T)); + foreach (var hh in headers) + { + var column = new DataColumn + { + DataType = Nullable.GetUnderlyingType(hh.Type!) ?? hh.Type, + ColumnName = hh.Name, + Caption = hh.Caption, + ReadOnly = hh.ReadOnly + }; + column.ExtendedProperties.Add("Style", hh.Style); + table.Columns.Add(column); + } + return (table, headers); + } + + public static DataSet FillOneSheet(this IEnumerable data) + { + var ds = new DataSet(); + var (table, headers) = ToTable(); + DataRow row; + foreach (var d in data) + { + row = table.NewRow(); + foreach (var hh in headers) + row[hh.Name!] = d!.GetType().GetProperty(hh.Name!)!.GetValue(d, null); + + table.Rows.Add(row); + } + ds.Tables.Add(table); + return ds; + } + + public static DataTable FillTableWithTotalsRel(this IEnumerable data, int startToSum = 6, string? dataTableName = null) + { + var (table, headers) = ToTablev2(dataTableName); + DataRow row; + foreach (var d in data) + { + row = table.NewRow(); + foreach (var hh in headers) + row[hh.Name!] = d!.GetType().GetProperty(hh.Name!)!?.GetValue(d, null) ?? DBNull.Value; + table.Rows.Add(row); + } + + table.Rows.Add(table.NewRow()); + var rowTot = table.NewRow(); + for (var i = 0; i < table.Columns.Count; i++) + { + if (i == 0) + { + rowTot[i] = "Totali:"; + } + else + { + if (i >= startToSum) + { + if (table.Columns[i].DataType == typeof(decimal)) + rowTot[i] = table.AsEnumerable().Sum(x => x.Field(table.Columns[i].ColumnName)); + else if (table.Columns[i].DataType == typeof(int)) + rowTot[i] = table.AsEnumerable().Sum(x => x.Field(table.Columns[i].ColumnName)); + else + rowTot[i] = DBNull.Value; + } + else + rowTot[i] = DBNull.Value; + } + } + table.Rows.Add(rowTot); + return table; + } + + public static DataSet FillOneSheetWithTotalsRel(this IEnumerable data, int startToSum = 6) + { + var ds = new DataSet(); + var (table, headers) = ToTablev2(); + DataRow row; + foreach (var d in data) + { + row = table.NewRow(); + foreach (var hh in headers) + row[hh.Name!] = d!.GetType().GetProperty(hh.Name!)!.GetValue(d, null); + + table.Rows.Add(row); + } + + table.Rows.Add(table.NewRow()); + var rowTot = table.NewRow(); + for (var i = 0; i < table.Columns.Count; i++) + { + if (i == 0) + { + rowTot[i] = "Totali:"; + } + else + { + if (i >= startToSum) + { + if (table.Columns[i].DataType == typeof(decimal)) + rowTot[i] = table.AsEnumerable().Sum(x => x.Field(table.Columns[i].ColumnName)); + else if (table.Columns[i].DataType == typeof(int)) + rowTot[i] = table.AsEnumerable().Sum(x => x.Field(table.Columns[i].ColumnName)); + else + rowTot[i] = DBNull.Value; + } + else + rowTot[i] = DBNull.Value; + } + } + table.Rows.Add(rowTot); + ds.Tables.Add(table); + return ds; + } + + public static DataSet FillOneSheetv2(this IEnumerable data) + { + var ds = new DataSet(); + var (table, headers) = ToTablev2(); + DataRow row; + foreach (var d in data) + { + row = table.NewRow(); + foreach (var hh in headers) + row[hh.Name!] = d!.GetType().GetProperty(hh.Name!)!.GetValue(d, null) ?? DBNull.Value; + + table.Rows.Add(row); + } + ds.Tables.Add(table); + return ds; + } + + public static DataSet FillOneSheetRECCON(this IEnumerable data) + { + var ds = new DataSet(); + var (table, headers) = ToTableRECCON(); + DataRow row; + foreach (var d in data) + { + row = table.NewRow(); + foreach (var hh in headers) + row[hh.Name!] = d!.GetType().GetProperty(hh.Name!)!.GetValue(d, null); + + table.Rows.Add(row); + } + ds.Tables.Add(table); + return ds; + } + + public static DataSet FillWorkbook(this IEnumerable dataTables) + { + var ds = new DataSet(); + foreach (var d in dataTables) + ds.Tables.Add(d); + return ds; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/Style.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/Style.cs new file mode 100644 index 0000000..75c1163 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/Style.cs @@ -0,0 +1,14 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +public enum XCellStyle +{ + None = 0, + Wrapper = 1, + StandardDate = 2, + StandardNumberDecimal = 3, + StandardDateTime = 4, + StandardInteger = 5, + Percent = 6, + Digit4 = 7, + Header = 8, +} diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/TypeFinder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/TypeFinder.cs new file mode 100644 index 0000000..8f4d33b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/Common/TypeFinder.cs @@ -0,0 +1,38 @@ +using DocumentFormat.OpenXml.Spreadsheet; + +namespace PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +public class TypeFinder +{ + private static readonly Dictionary _matches = new() + { + { typeof(long?) , CellValues.Number}, + { typeof(double?) , CellValues.Number}, + { typeof(int?) , CellValues.Number}, + { typeof(short?) , CellValues.Number}, + { typeof(decimal?) , CellValues.Number}, + { typeof(byte?) , CellValues.Number}, + { typeof(bool?) , CellValues.Boolean}, + { typeof(DateTime?) , CellValues.Date}, + { typeof(DateTimeOffset?) , CellValues.Date}, + { typeof(string) , CellValues.String}, + { typeof(long) , CellValues.Number}, + { typeof(double) , CellValues.Number}, + { typeof(int) , CellValues.Number}, + { typeof(short) , CellValues.Number}, + { typeof(decimal) , CellValues.Number}, + { typeof(byte) , CellValues.Number}, + { typeof(bool) , CellValues.Boolean}, + { typeof(DateTime) , CellValues.Date}, + { typeof(DateTimeOffset) , CellValues.Date} + }; + + public static (CellValues, T, Type) Get(T value) + { + var type = Nullable.GetUnderlyingType(value!.GetType()!) ?? value!.GetType(); + var check = _matches.TryGetValue(type, out var cellValues); + if (check) + return (cellValues, value, type); + return (CellValues.String, default(T), typeof(string))!; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/DocumentBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/DocumentBuilder.cs new file mode 100644 index 0000000..23b95fa --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/DocumentBuilder.cs @@ -0,0 +1,129 @@ +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Exceptions; +using WkHtmlToPdfDotNet; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; +using PortaleFatture.BE.Core.Entities.DatiRel; + +namespace PortaleFatture.BE.Infrastructure.Common.Documenti; +public class DocumentBuilder : IDocumentBuilder +{ + private static string _fileEmail = $"primo_saldo.html"; + private static string _filePrimoSaldoRel = $"PRIMO_SALDO_rel.html"; + private static string _fileSecondoSaldoRel = $"SECONDO_SALDO_rel.html"; + private static string _fileModuloCommessa = $"daticommessa.html"; + private static string _directory = $"Infrastructure/Documenti/"; + private readonly string _root; + private readonly string _directoryPath; + private static SynchronizedConverter _converter = new(new PdfTools()); + public DocumentBuilder(string root) + { + this._root = root; + this._directoryPath = Path.Combine([_root, _directory]); + } + + public string? CreateEmailHtml(RelEmail dati) + { + var filePath = Path.Combine([_directoryPath, _fileEmail]); + var text = ReadFromFile(filePath); + text = dati.Replace(text!); + return text; + } + + public string? CreateModuloCommessaHtml(ModuloCommessaDocumentoDto dati) + { + var filePath = Path.Combine([_directoryPath, _fileModuloCommessa]); + var moduloCommessaText = ReadFromFile(filePath); + moduloCommessaText = dati.Replace(moduloCommessaText!); + return moduloCommessaText; + } + + public string? CreateModuloRelHtml(RelDocumentoDto dati) + { + string? fileRel; + if (dati.TipologiaFattura == TipologiaFattura.PRIMOSALDO) + { + fileRel = _filePrimoSaldoRel; + } + else if (dati.TipologiaFattura == TipologiaFattura.SECONDOSALDO) + { + fileRel = _fileSecondoSaldoRel; + } + else + { + throw new Exception("Tipologia fattura non valida"); + } + var filePath = Path.Combine([_directoryPath, fileRel]); + var relText = ReadFromFile(filePath); + relText = dati.Replace(relText!); + return relText; + } + + public byte[] CreateModuloRelPdf(RelDocumentoDto dati) + { + string? fileRel; + if (dati.TipologiaFattura == TipologiaFattura.PRIMOSALDO) + { + fileRel = _filePrimoSaldoRel; + } + else if (dati.TipologiaFattura == TipologiaFattura.SECONDOSALDO) + { + fileRel = _fileSecondoSaldoRel; + } + else + { + throw new Exception("Tipologia fattura non valida"); + } + var filePath = Path.Combine([_directoryPath, fileRel]); + var relText = ReadFromFile(filePath); + relText = dati.Replace(relText!); + return CreatePdf(relText!); + } + + public byte[] CreateModuloCommessaPdf(ModuloCommessaDocumentoDto dati) + { + var filePath = Path.Combine([_directoryPath, _fileModuloCommessa]); + var moduloCommessaText = ReadFromFile(filePath); + moduloCommessaText = dati.Replace(moduloCommessaText!); + return CreatePdf(moduloCommessaText!); + } + + private readonly static GlobalSettings _globalSettings = new() + { + ColorMode = ColorMode.Color, + Orientation = Orientation.Portrait, + PaperSize = PaperKind.A4 + }; + + private byte[] CreatePdf(string text) + { + var doc = new HtmlToPdfDocument() + { + GlobalSettings = _globalSettings, + Objects = { + new ObjectSettings() { + PagesCount = true, + HtmlContent = text, + WebSettings = { DefaultEncoding = "utf-8" } + } + } + }; + return _converter.Convert(doc); + } + + private string? ReadFromFile(string filePath) + { + if (File.Exists(filePath)) + return File.ReadAllText(filePath); + + var msg = "Add a pdf template in the document folder!"; + throw new ConfigurationException(msg); + } + + private string? ReadFromFile(string root, string directory, string fileName) + { + string[] paths = [root, directory, fileName]; + var filePath = Path.Combine(paths); + return ReadFromFile(filePath); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/IDocumentBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/IDocumentBuilder.cs new file mode 100644 index 0000000..24e6425 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Documenti/IDocumentBuilder.cs @@ -0,0 +1,14 @@ +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Documenti +{ + public interface IDocumentBuilder + { + string? CreateEmailHtml(RelEmail dati); + string? CreateModuloCommessaHtml(ModuloCommessaDocumentoDto dati); + byte[] CreateModuloCommessaPdf(ModuloCommessaDocumentoDto dati); + string? CreateModuloRelHtml(RelDocumentoDto dati); + byte[] CreateModuloRelPdf(RelDocumentoDto dati); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/DatiGeneraliDocumentoDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/DatiGeneraliDocumentoDto.cs new file mode 100644 index 0000000..4023de3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/DatiGeneraliDocumentoDto.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public class DatiGeneraliDocumentoDto +{ + [JsonPropertyName("tipologia")] + public string? Tipologia { get; set; } + + [JsonPropertyName("riferimentoNumeroLinea")] + public string? RiferimentoNumeroLinea { get; set; } + + [JsonPropertyName("idDocumento")] + public string? IdDocumento { get; set; } + + [JsonPropertyName("data")] + public string? Data { get; set; } + + [JsonPropertyName("numItem")] + public string? NumItem { get; set; } + + [JsonPropertyName("codiceCommessaConvenzione")] + public string? CodiceCommessaConvenzione { get; set; } + + [JsonPropertyName("CUP")] + public string? CUP { get; set; } + + [JsonPropertyName("CIG")] + public string? CIG { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FatturaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FatturaDto.cs new file mode 100644 index 0000000..4f28c70 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FatturaDto.cs @@ -0,0 +1,7 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +public class FatturaDto +{ + public TitoloFatturaDto? fattura { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureAccontoExcelDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureAccontoExcelDto.cs new file mode 100644 index 0000000..4396361 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureAccontoExcelDto.cs @@ -0,0 +1,95 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public sealed class FattureAccontoExcelDto +{ + [HeaderAttributev2(caption: "identificativo SC", Order = 1)] + public string? IdEnte { get; set; } + + [HeaderAttributev2(caption: "ragione sociale ente", Order = 2)] + public string? RagioneSociale { get; set; } + + [HeaderAttributev2(caption: "codice fiscale", Order = 3)] + public string? CodiceFiscale { get; set; } + + [HeaderAttributev2(caption: "prodotto", Order = 4)] + public string? Prodotto { get; set; } + + [HeaderAttributev2(caption: "Anno", Order = 5)] + public string? Anno { get; set; } + + public int Mese { get; set; } + + [HeaderAttributev2(caption: "Mese", Order = 6)] + public string? MeseValidita + { + get + { + + return Mese.GetMonth(); + } + } + + [HeaderAttributev2(caption: "Tipo Spedizione", Order = 7)] + public string? TipoSpedizioneDigitale { get; set; } = "Digitale"; + + [HeaderAttributev2(caption: "N. Notifiche Digitali", Order = 8)] + public int TotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "Tipo Spedizione", Order = 9)] + public string? TipoSpedizioneAnalogicoAR { get; set; } = "Analogico"; + + [HeaderAttributev2(caption: "N. Notifiche Analogiche", Order = 10)] + public int TotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile Analogico", Order = 11)] + public decimal TotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile Digitale", Order = 12)] + public decimal TotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile", Order = 13)] + public decimal Totale { get; set; } + + //-fattura + [HeaderAttributev2(caption: "IdFattura", Order = 14)] + + [Column("IdFattura")] + public string? IdFattura { get; set; } + + public int IdTipoContratto { get; set; } + + [HeaderAttributev2(caption: "Tipo Contratto", Order = 15)] + public string? TipoContratto { get; set; } + + public decimal Percentuale { get; set; } + + [HeaderAttributev2(caption: "Percentuale Acconto", Order = 16)] + public string? ValorePercentuale + { + get + { + return $"{Percentuale} %"; + } + } + + [HeaderAttributev2(caption: "Totale Imponibile Acconto Analogico", Order = 17)] + public decimal ImponibileAccontoAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile Acconto Digitale", Order = 18)] + public decimal ImponibileAccontoDigitale { get; set; } + + [HeaderAttributev2(caption: "Storno Anticipo Analogico (50%)", Order = 19)] + public decimal ImponibileStornoAnalogico { get; set; } + + + [HeaderAttributev2(caption: "Storno Anticipo Digitale (50%)", Order = 20)] + public decimal ImponibileStornoDigitale { get; set; } + + + [HeaderAttributev2(caption: "Totale imponibile Fattura di Acconto", Order = 21)] + public decimal TotaleFattura { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureCommessaExcelDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureCommessaExcelDto.cs new file mode 100644 index 0000000..dc315be --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureCommessaExcelDto.cs @@ -0,0 +1,146 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public sealed class FattureCommessaExcelDto +{ + [HeaderAttributev2(caption: "identificativo SC", Order = 1)] + public string? FkIdEnte { get; set; } + + [HeaderAttributev2(caption: "ragione sociale ente", Order = 2)] + public string? RagioneSociale { get; set; } + + [HeaderAttributev2(caption: "codice fiscale", Order = 3)] + public string? CodiceFiscale { get; set; } + + [HeaderAttributev2(caption: "prodotto", Order = 4)] + public string? Prodotto { get; set; } + + [HeaderAttributev2(caption: "Tipo Spedizione", Order = 5)] + public string? TipoSpedizioneDigitale { get; set; } = "Digitale"; + + [HeaderAttributev2(caption: "N. Notifiche NZ", Order = 6)] + public int NumeroNotificheNazionaliDigitali { get; set; } + + [HeaderAttributev2(caption: "N. Notifiche INT", Order = 7)] + public int NumeroNotificheInternazionaliDigitali { get; set; } + + [HeaderAttributev2(caption: "Tipo Spedizione", Order = 8)] + public string? TipoSpedizioneAnalogicoAR { get; set; } = "analogico AR"; + + [HeaderAttributev2(caption: "N. Notifiche NZ", Order = 9)] + public int NumeroNotificheNazionaliAR { get; set; } + + [HeaderAttributev2(caption: "N. Notifiche INT", Order = 10)] + public int NumeroNotificheInternazionaliAR { get; set; } + + [HeaderAttributev2(caption: "Tipo Spedizione", Order = 11)] + public string? TipoSpedizioneAnalogico890 { get; set; } = "analogico 890"; + + [HeaderAttributev2(caption: "N. Notifiche NZ", Order = 12)] + public int NumeroNotificheNazionali890 { get; set; } + + [HeaderAttributev2(caption: "N. Notifiche INT", Order = 13)] + public int NumeroNotificheInternazionali890 { get; set; } + + //-fattura + [HeaderAttributev2(caption: "IdFattura", Order = 14)] + + [Column("IdFattura")] + public string? IdFattura { get; set; } + + + [HeaderAttributev2(caption: "Totale imponibile anticipo analogico", Order = 15)] + public decimal ImponibileAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale imponibile anticipo analogico", Order = 16)] + public decimal ImponibileDigitale { get; set; } + + [HeaderAttributev2(caption: "Totale Fattura anticipo", Order = 17)] + public decimal TotaleFattura { get; set; } + + //-- + [HeaderAttributev2(caption: "Anno", Order = 18)] + public string? AnnoValidita { get; set; } + + public int MeseValidita { get; set; } + [HeaderAttributev2(caption: "Mese", Order = 19)] + public string? Mese + { + get + { + + return MeseValidita.GetMonth(); + } + } + + [HeaderAttributev2(caption: "Percentuale analogico", Order = 20)] + public decimal PercentualeA { get; set; } + + [HeaderAttributev2(caption: "Percentuale digitale", Order = 21)] + public decimal PercentualeD { get; set; } + + + [HeaderAttributev2(caption: "Totale commessa analogico", Order = 22)] + public decimal TotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale commessa digitale", Order = 23)] + public decimal TotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "Totale Commessa", Order = 24)] + public decimal Totale { get; set; } + public int IdTipoContratto { get; set; } + + [HeaderAttributev2(caption: "Tipo Contratto", Order = 25)] + public string? TipoContratto { get; set; } + + [HeaderAttributev2(caption: "N. totale notifiche analogiche", Order = 26)] + public int TotaleNotificheAnalogico { get; set; } + + [HeaderAttributev2(caption: "N. totale notifiche digitali", Order = 27)] + public int TotaleNotificheDigitale { get; set; } + + + public bool Fatturabile { get; set; } + + [HeaderAttributev2(caption: "Fattura (si/no)", Order = 28)] + public string? IsFattura + { + get + { + + if (IdFattura is not null) + return "SI"; + else + return "NO"; + } + } + + public bool? Asseverazione { get; set; } + + [HeaderAttributev2(caption: "asseverazione (si/no)", Order = 29)] + public string? IsAsseverazione + { + get + { + + if (Asseverazione is not null && Asseverazione == true) + return "SI"; + else + return "NO"; + } + } + + [HeaderAttributev2(caption: "data uscita asseverazione", Order = 30)] + public DateTime? DataUscitaAsseverazione { get; set; } + + [HeaderAttributev2(caption: "totale notifiche", Order = 31)] + public int TotaleNotifiche { get; set; } + + + [HeaderAttributev2(caption: "Stato", Order = 32)] + public string? FkIdStato { get; set; } + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureExcel.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureExcel.cs new file mode 100644 index 0000000..c705e68 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureExcel.cs @@ -0,0 +1,94 @@ +using System.Text.Json.Serialization; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public class FattureExcel +{ + [HeaderAttributev2(caption: "Posizione", Order = 17)] + public string? Posizione { get; set; } + + [HeaderAttributev2(caption: "Totale €", Order = 18)] + public string? Totale { get; set; } + + [HeaderAttributev2(caption: "Numero", Order = 7)] + + [JsonPropertyName("numero")] + public int? Numero { get; set; } + + [HeaderAttributev2(caption: "DataFattura", Order = 8)] + + [JsonPropertyName("dataFattura")] + public string? DataFattura { get; set; } + + [HeaderAttributev2(caption: "Prodotto", Order = 4)] + + [JsonPropertyName("prodotto")] + public string? Prodotto { get; set; } + + [HeaderAttributev2(caption: "Identificativo", Order = 4)] + + [JsonPropertyName("identificativo")] + public string? Identificativo { get; set; } + + [HeaderAttributev2(caption: "Tipologia Fattura", Order = 6)] + + [JsonPropertyName("tipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [HeaderAttributev2(caption: "Id Ente", Order = 2)] + + [JsonPropertyName("istitutioID")] + public string? IstitutioID { get; set; } + + [HeaderAttributev2(caption: "Onboarding Token Id", Order = 3)] + + [JsonPropertyName("onboardingTokenID")] + public string? OnboardingTokenID { get; set; } + + + [HeaderAttributev2(caption: "Ragione Sociale", Order = 1)] + + [JsonPropertyName("ragionesociale")] + public string? RagioneSociale { get; set; } + + [HeaderAttributev2(caption: "Tipo Contratto", Order = 9)] + + [JsonPropertyName("tipocontratto")] + public string? TipoContratto { get; set; } + + [HeaderAttributev2(caption: "Id Contratto", Order = 10)] + + [JsonPropertyName("idcontratto")] + public string? IdContratto { get; set; } + + [HeaderAttributev2(caption: "Tipo Documento", Order = 11)] + + [JsonPropertyName("tipoDocumento")] + public string? TipoDocumento { get; set; } + + [HeaderAttributev2(caption: "Divisa", Order = 12)] + + [JsonPropertyName("divisa")] + public string? Divisa { get; set; } + + [HeaderAttributev2(caption: "Metodo Pagamento", Order = 13)] + + [JsonPropertyName("metodoPagamento")] + public string? MetodoPagamento { get; set; } + + [HeaderAttributev2(caption: "Causale", Order = 14)] + + [JsonPropertyName("causale")] + public string? Causale { get; set; } + + [HeaderAttributev2(caption: "Split", Order = 15)] + + [JsonPropertyName("split")] + public bool? Split { get; set; } + + [HeaderAttributev2(caption: "Sollecito", Order = 16)] + + [JsonPropertyName("sollecito")] + public string? Sollecito { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureListaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureListaDto.cs new file mode 100644 index 0000000..17a4dbd --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureListaDto.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public class FattureListaDto : List +{ + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureRelExcelDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureRelExcelDto.cs new file mode 100644 index 0000000..88acf9c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/FattureRelExcelDto.cs @@ -0,0 +1,137 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Core.Entities.DatiRel; + +public class FattureRelExcelDto +{ + [Column("IdEnte")] + [HeaderAttributev2(caption: "IdEnte", Order = 1)] + public string? IdEnte { get; set; } + + + [HeaderAttributev2(caption: "Ragione Sociale", Order = 2)] + + [Column("RagioneSociale")] + public string? RagioneSociale { get; set; } + + [HeaderAttributev2(caption: "IdContratto", Order = 3)] + + [Column("IdContratto")] + public string? IdContratto { get; set; } + + + [HeaderAttributev2(caption: "Tipologia Fattura", Order = 4)] + + [Column("TipologiaFattura")] + public string? TipologiaFattura { get; set; } + + + [HeaderAttributev2(caption: "IdFattura", Order = 4)] + + [Column("IdFattura")] + public string? IdFattura { get; set; } + + + [HeaderAttributev2(caption: "TipoDocumento", Order = 4)] + + [Column("TipoDocumento")] + public string? TipoDocumento { get; set; } + + + [HeaderAttributev2(caption: "DataFattura", Order = 4)] + + [Column("DataFattura")] + public string? DataFattura { get; set; } + + + [HeaderAttributev2(caption: "Anno", Order = 5)] + + [Column("Anno")] + public int? Anno { get; set; } + + [HeaderAttributev2(caption: "Mese", Order = 6)] + + [Column("Mese")] + public int? Mese { get; set; } + + + //rel -init + [HeaderAttributev2(caption: "N. Notifiche Analogiche", Order = 7)] + [Column("RelTotaleNotificheAnalogiche")] + public int RelTotaleNotificheAnalogiche { get; set; } + + [HeaderAttributev2(caption: "N. Notifiche Digitali", Order = 8)] + [Column("RelTotaleNotificheDigitali")] + public int RelTotaleNotificheDigitali { get; set; } + + [HeaderAttributev2(caption: "N. Totale Notifiche", Order = 9)] + [Column("RelTotaleNotifiche")] + public int RelTotaleNotifiche { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile Analogico €", Order = 10)] + [Column("RelTotaleAnalogico")] + public decimal RelTotaleAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile Digitale €", Order = 11)] + [Column("RelTotaleDigitale")] + public decimal RelTotaleDigitale { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile €", Order = 12)] + [Column("RelTotale")] + public decimal RelTotale { get; set; } + + [HeaderAttributev2(caption: "Totale Ivato Analogico €", Order = 13)] + [Column("RelTotaleIvatoAnalogico")] + public decimal RelTotaleIvatoAnalogico { get; set; } + + [HeaderAttributev2(caption: "Totale Imponibile Digitale €", Order = 14)] + [Column("RelTotaleIvatoDigitale")] + public decimal RelTotaleIvatoDigitale { get; set; } + + [HeaderAttributev2(caption: "Totale Ivato Digitale €", Order = 15)] + [Column("RelTotaleIvato")] + public decimal RelTotaleIvato { get; set; } + + [HeaderAttributev2(caption: "Firmata", Order = 16)] + public string Firmata + { + get + { + return Caricata.MapRelTestata(); + } + } + + [Column("Caricata")] + public byte Caricata { get; set; } + //rel -end + + //storno fatture -init + [HeaderAttributev2(caption: "Storno Anticipo Analogico €", Order = 17)] + [Column("StornoAnticipoAnalogico")] + public decimal StornoAnticipoAnalogico { get; set; } + + [HeaderAttributev2(caption: "Storno Anticipo Digitale €", Order = 18)] + [Column("StornoAnticipoDigitale")] + public decimal StornoAnticipoDigitale { get; set; } + + [HeaderAttributev2(caption: "Storno Acconto Analogico €", Order = 19)] + [Column("StornoAccontoAnalogico")] + public decimal StornoAccontoAnalogico { get; set; } + + [HeaderAttributev2(caption: "Storno Acconto Digitale €", Order = 20)] + [Column("StornoAccontoDigitale")] + public decimal StornoAccontoDigitale { get; set; } + + [HeaderAttributev2(caption: "Totale Fattura Imponibile €", Order = 21)] + [Column("TotaleFatturaImponibile")] + public decimal TotaleFatturaImponibile { get; set; } + + [Column("CodiceMateriale")] + public string? CodiceMateriale { get; set; } + + [Column("RigaImponibile")] + public decimal RigaImponibile { get; set; } + //storno fatture -end +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/PosizioniDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/PosizioniDto.cs new file mode 100644 index 0000000..a09a6fe --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/PosizioniDto.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public class PosizioniDto +{ + [JsonPropertyName("numerolinea")] + public int NumeroLinea { get; set; } + + [JsonPropertyName("testo")] + public string? Testo { get; set; } + + [JsonPropertyName("codiceMateriale")] + public string? CodiceMateriale { get; set; } + + [JsonPropertyName("quantita")] + public int? Quantita { get; set; } + + [JsonPropertyName("prezzoUnitario")] + public double PrezzoUnitario { get; set; } + + [JsonPropertyName("imponibile")] + public double Imponibile { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/TitoloFatturaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/TitoloFatturaDto.cs new file mode 100644 index 0000000..15b44d7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Dto/TitoloFatturaDto.cs @@ -0,0 +1,63 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +public class TitoloFatturaDto +{ + [JsonPropertyName("totale")] + public decimal Totale { get; set; } + + [JsonPropertyName("numero")] + public int Numero { get; set; } + + [JsonPropertyName("dataFattura")] + public string? DataFattura { get; set; } + + [JsonPropertyName("prodotto")] + public string? Prodotto { get; set; } + + [JsonPropertyName("identificativo")] + public string? Identificativo { get; set; } + + [JsonPropertyName("tipologiaFattura")] + public string? TipologiaFattura { get; set; } + + [JsonPropertyName("istitutioID")] + public string? IstitutioID { get; set; } + + [JsonPropertyName("onboardingTokenID")] + public string? OnboardingTokenID { get; set; } + + [JsonPropertyName("ragionesociale")] + public string? RagioneSociale { get; set; } + + [JsonPropertyName("tipocontratto")] + public string? TipoContratto { get; set; } + + [JsonPropertyName("idcontratto")] + public string? IdContratto { get; set; } + + [JsonPropertyName("tipoDocumento")] + public string? TipoDocumento { get; set; } + + [JsonPropertyName("divisa")] + public string? Divisa { get; set; } + + [JsonPropertyName("metodoPagamento")] + public string? MetodoPagamento { get; set; } + + [JsonPropertyName("causale")] + public string? Causale { get; set; } + + [JsonPropertyName("split")] + public bool? Split { get; set; } + + [JsonPropertyName("sollecito")] + public string? Sollecito { get; set; } + + [JsonPropertyName("datiGeneraliDocumento")] + public List? DatiGeneraliDocumento { get; set; } + + [JsonPropertyName("posizioni")] + public List? Posizioni { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureAccontoExcelQuery.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureAccontoExcelQuery.cs new file mode 100644 index 0000000..cae5f41 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureAccontoExcelQuery.cs @@ -0,0 +1,13 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; + +public class FattureAccontoExcelQuery(IAuthenticationInfo authenticationInfo) : IRequest>?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? IdEnti { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureCommessaExcelQuery.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureCommessaExcelQuery.cs new file mode 100644 index 0000000..40b3740 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureCommessaExcelQuery.cs @@ -0,0 +1,13 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; + +public class FattureCommessaExcelQuery(IAuthenticationInfo authenticationInfo) : IRequest>?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? IdEnti { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureQueryRicerca.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureQueryRicerca.cs new file mode 100644 index 0000000..adb8de8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureQueryRicerca.cs @@ -0,0 +1,14 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; + +public class FattureQueryRicerca(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? IdEnti { get; set; } + public string[]? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureRelExcelQuery.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureRelExcelQuery.cs new file mode 100644 index 0000000..d5c7469 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/FattureRelExcelQuery.cs @@ -0,0 +1,15 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; + +public class FattureRelExcelQuery(IAuthenticationInfo authenticationInfo) : IRequest>?> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public string[]? IdEnti { get; set; } + public string? TipologiaFattura { get; set; } + public int? Anno { get; set; } + public int? Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureAccontoFatturaExcelBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureAccontoFatturaExcelBuilder.cs new file mode 100644 index 0000000..8b28c67 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureAccontoFatturaExcelBuilder.cs @@ -0,0 +1,17 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; + +public static class FattureAccontoFatturaExcelBuilder +{ + private static string _sqlAcconto = @" +SELECT f.*, n.* + FROM [pfd].[vFattureAcconto] f +left outer join pfd.NotificheCount n +ON n.internal_organization_id = f.IdEnte +AND n.year = f.Anno and n.month = f.Mese +"; + + public static string SelectAcconto() + { + return _sqlAcconto; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureModuloCommessaExcelBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureModuloCommessaExcelBuilder.cs new file mode 100644 index 0000000..a0ed447 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureModuloCommessaExcelBuilder.cs @@ -0,0 +1,37 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; + +public static class FattureModuloCommessaExcelBuilder +{ + private static string _sqlCommesse = @" +SELECT * from +pfd.vModuloCommessaTotali t +inner join +pfd.vModuloCommessaParziali p +ON t.FKIdEnte = p.FKIdEnte +AND t.AnnoValidita= p.AnnoValidita +AND t.MeseValidita = p.MeseValidita +left outer join +pfd.vFattureAnticipo f +ON f.Anno = t.AnnoValidita +AND f.Mese = t.MeseValidita +AND f.IdEnte = t.FKIdEnte +"; + + public static string SelectCommesse() + { + return _sqlCommesse; + } + + private static string _sqlORderBy = @" + ORDER BY + CASE + WHEN f.IdFattura IS NULL THEN 1 + ELSE 0 + END, + f.IdFattura, Totale desc;"; + + public static string OrderBy() + { + return _sqlCommesse; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureQueryRicercaBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureQueryRicercaBuilder.cs new file mode 100644 index 0000000..4de2777 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureQueryRicercaBuilder.cs @@ -0,0 +1,74 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; + +public static class FattureQueryRicercaBuilder +{ + private static string _sqlStored = @"pfd.GenerateJsonSAP"; + private static string _sqlView = @"SELECT + listaFatture = ( + + SELECT + CAST(FT.TotaleFattura AS DECIMAL(10, 2)) AS 'fattura.totale', + FT.Progressivo AS 'fattura.numero', + CONVERT(VARCHAR, FT.DataFattura, 23) AS 'fattura.dataFattura', + FT.FkProdotto AS 'fattura.prodotto', + CAST(FT.MeseRiferimento as varchar(2)) + '/' + CAST(FT.AnnoRiferimento as VARCHAR(4)) AS 'fattura.identificativo', + FT.FkTipologiaFattura AS 'fattura.tipologiaFattura', -- Changed this line + FT.FkIdEnte AS 'fattura.istitutioID', + FT.CodiceContratto AS 'fattura.onboardingTokenID', + FT.FkIdTipoDocumento AS 'fattura.tipoDocumento', + FT.Divisa AS 'fattura.divisa', + FT.MetodoPagamento AS 'fattura.metodoPagamento', + CONCAT(REPLACE( ftc.Causale,'[percentuale]', ISNULL(ftc.PercentualeAnticipo,'')),' ' ,CAST(FT.MeseRiferimento as varchar(2)), '/' , CAST(FT.AnnoRiferimento as VARCHAR(4))) as 'fattura.causale', + FT.SplitPayment AS 'fattura.split', + ISNULL(FT.Sollecito, '') AS 'fattura.sollecito', + ( + SELECT + ISNULL(tC.[Descrizione],'') AS 'tipologia', + '' AS 'riferimentoNumeroLinea', + ISNULL(FTn.IdDocumento,'') AS 'idDocumento', + CONVERT(VARCHAR,FTn.DataDocumento, 23) AS 'data', + ISNULL(FTn.NumItem,'') AS 'numItem', + ISNULL(FTn.CodCommessa,'') AS 'codiceCommessaConvenzione', + ISNULL(FTn.Cup,'') AS 'CUP', + ISNULL(FTn.Cig,'') AS 'CIG' + FROM [pfd].[FattureTestata] FTn + LEFT JOIN [pfw].[DatiFatturazione] dF ON ISNULL(FTn.FkIdDatiFatturazione,'') = ISNULL(dF.IdDatiFatturazione,'') + LEFT JOIN [pfw].[TipoCommessa] tC ON dF.[FkTipoCommessa] = tC.[TipoCommessa] + where FTn.IdFattura = FT.IdFattura + FOR JSON PATH + ) AS 'fattura.datiGeneraliDocumento', + ( + SELECT + FR.NumeroLinea AS 'numerolinea', + ISNULL(FR.Testo,'') AS 'testo', + FR.CodiceMateriale AS 'codiceMateriale', + FR.Quantita AS 'quantita', + CAST(FR.PrezzoUnitario AS DECIMAL(10, 2)) AS 'prezzoUnitario', + CAST(FR.Imponibile AS DECIMAL(10, 2)) AS 'imponibile' + FROM [pfd].[FattureRighe] FR + LEFT JOIN [pfw].[CodiciMateriali] CM + ON FR.CodiceMateriale = CM.CodiceMateriale + WHERE FT.IdFattura = FR.FkIdFattura + ORDER BY CM.Ordinamento + FOR JSON PATH + ) AS 'fattura.posizioni' + FROM + [pfd].[FattureTestata] FT + INNER JOIN pfd.Contratti c ON c.onboardingtokenid = FT.CodiceContratto + INNER JOIN pfw.FatturaTestataConfig ftc ON ftc.FkTipologiaFattura = FT.FkTipologiaFattura AND ftc.FKIdTipoContratto = c.FkIdTipoContratto + where FT.AnnoRiferimento = @AnnoRiferimento + and FT.MeseRiferimento = @MeseRiferimento + and FT.FkTipologiaFattura IN @TipologiaFattura + and FT.FkIdEnte <> '4a4149af-172e-4950-9cc8-63ccc9a6d865' --esclusione pagopa + ORDER BY FT.FkTipologiaFattura, FT.Progressivo + FOR JSON PATH, INCLUDE_NULL_VALUES )"; + public static string SelectStored() + { + return _sqlStored; + } + + public static string SelectView() + { + return _sqlView; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureRelExcelBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureRelExcelBuilder.cs new file mode 100644 index 0000000..97d288a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/Builder/FattureRelExcelBuilder.cs @@ -0,0 +1,111 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; + +public static class FattureRelExcelBuilder +{ + private static string _sqlNoteSenzaRel = @" +SELECT +t.IdFattura as IdFattura, +e.description as RagioneSociale, +t.FkIdTipoDocumento as TipoDocumento, +t.FkIdEnte as IdEnte, +t.DataFattura as DataFattura, +-t.TotaleFattura as TotaleFatturaImponibile, +r.CodiceMateriale as CodiceMateriale, +r.Imponibile as RigaImponibile, +t.CodiceContratto as IdContratto, +t.AnnoRiferimento as Anno, +t.MeseRiferimento as Mese, +@tipologiafattura as TipologiaFattura, +0 as RelTotaleAnalogico, +0 as RelTotaleDigitale, +0 as RelTotaleNotificheAnalogiche, +0 as RelTotaleNotificheDigitali, +0 as RelTotaleNotifiche, +0 as RelTotale, +0 as RelTotaleIvatoAnalogico, +0 as RelTotaleIvatoDigitale, +0 as RelTotaleIvato, +NULL as Caricata, +NULL as RelFatturata +FROM pfd.FattureTestata t +LEFT OUTER join pfd.Enti e +ON e.InternalIstitutionId = t.FkIdEnte +INNER JOIN pfd.FattureRighe r +ON t.IdFattura = r.FkIdFattura +where +t.AnnoRiferimento=@anno and +t.MeseRiferimento=@mese and +t.FkTipologiaFattura=@tipologiafattura and +r.CodiceMateriale like '%STORNO%' +and t.FkIdEnte NOT IN +(SELECT rr.internal_organization_id from pfd.RelTestata rr +WHERE rr.month= @mese and rr.year=@anno and rr.TipologiaFattura=@tipologiafattura) +"; + + private static string _sqlRel = @" +SELECT +t.IdFattura as IdFattura, +e.description as RagioneSociale, +t.FkIdTipoDocumento as TipoDocumento, +t.FkIdEnte as IdEnte, +t.DataFattura as DataFattura, +CAST( + CASE + WHEN t.FkIdTipoDocumento = 'TD04' + THEN -t.TotaleFattura + ELSE t.TotaleFattura + END AS decimal(18,2)) as TotaleFatturaImponibile, +r.CodiceMateriale as CodiceMateriale, +r.Imponibile as RigaImponibile, +t.CodiceContratto as IdContratto, +t.AnnoRiferimento as Anno, +t.MeseRiferimento as Mese, +rr.[TipologiaFattura], +ISNULL(rr.[TotaleAnalogico],0) as RelTotaleAnalogico, +ISNULL(rr.[TotaleDigitale],0) as RelTotaleDigitale, +ISNULL(rr.[TotaleNotificheAnalogiche],0) as RelTotaleNotificheAnalogiche, +ISNULL(rr.[TotaleNotificheDigitali],0) as RelTotaleNotificheDigitali, +ISNULL(rr.[TotaleNotificheAnalogiche],0) + ISNULL(rr.[TotaleNotificheDigitali],0) as RelTotaleNotifiche, +ISNULL(rr.[Totale],0) as RelTotale, +ISNULL(rr.[TotaleAnalogicoIva],0) as RelTotaleIvatoAnalogico, +ISNULL(rr.[TotaleDigitaleIva],0) as RelTotaleIvatoDigitale, +ISNULL(rr.[TotaleIva],0) as RelTotaleIvato, +rr.[Caricata] as Caricata, +rr.[RelFatturata] +FROM pfd.FattureTestata t +LEFT OUTER join pfd.Enti e +ON e.InternalIstitutionId = t.FkIdEnte +INNER JOIN pfd.FattureRighe r +ON t.IdFattura = r.FkIdFattura +INNER JOIN [pfd].[RelTestata] rr +ON rr.year = t.AnnoRiferimento +AND rr.month = t.MeseRiferimento +AND rr.TipologiaFattura = t.FkTipologiaFattura +AND rr.internal_organization_id = t.FkIdEnte +AND rr.contract_id = t.CodiceContratto +WHERE rr.month= @mese and rr.year=@anno and rr.TipologiaFattura=@tipologiafattura +"; + + + public static string SelectRel() + { + return _sqlRel; + } + + public static string SelectNoteSenzaRel() + { + return _sqlNoteSenzaRel; + } + + private static readonly string _orderByRel = @" +order by CAST( + CASE + WHEN t.FkIdTipoDocumento = 'TD04' + THEN -t.TotaleFattura + ELSE t.TotaleFattura + END AS decimal(18,2)) desc"; + public static string OrderByRel() + { + return _orderByRel; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelBuilderPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelBuilderPersistence.cs new file mode 100644 index 0000000..a56bd86 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelBuilderPersistence.cs @@ -0,0 +1,37 @@ +using System.Data; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; + +public class FattureAccontoFatturaExcelBuilderPersistence(FattureAccontoExcelQuery command) : DapperBase, IQuery?> +{ + private readonly FattureAccontoExcelQuery _command = command; + private static readonly string _sql = FattureAccontoFatturaExcelBuilder.SelectAcconto(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var anno = _command.Anno; + var mese = _command.Mese; + var where = " where n.year= @anno and n.month=@mese "; + + if (!_command.IdEnti!.IsNullNotAny()) + where = " AND t.FKIdEnte in @IdEnti "; + + var sql = _sql + where; + + var query = new + { + Anno = anno, + Mese = mese, + IdEnti = _command.IdEnti + }; + + return await ((IDatabase)this).SelectAsync( + connection!, + sql, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureModuloCommessaExcelBuilderPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureModuloCommessaExcelBuilderPersistence.cs new file mode 100644 index 0000000..b7d548a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureModuloCommessaExcelBuilderPersistence.cs @@ -0,0 +1,39 @@ +using System.Data; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; + +public class FattureModuloCommessaExcelBuilderPersistence(FattureCommessaExcelQuery command) : DapperBase, IQuery?> +{ + private readonly FattureCommessaExcelQuery _command = command; + private static readonly string _sqlSelect = FattureModuloCommessaExcelBuilder.SelectCommesse(); + private static readonly string _sqlOrderby = FattureModuloCommessaExcelBuilder.OrderBy(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var anno = _command.Anno; + var mese = _command.Mese; + + var where = " WHERE t.AnnoValidita=@anno and t.MeseValidita=@mese "; + + if(!_command.IdEnti!.IsNullNotAny()) + where = where + " AND t.FKIdEnte in @IdEnti "; + + var sql = _sqlSelect + where + _sqlOrderby; + + var query = new + { + Anno = anno, + Mese = mese, + IdEnti = _command.IdEnti + }; + + return await ((IDatabase)this).SelectAsync( + connection!, + sql, + query, + transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureNotaNoRelExcelBuilderPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureNotaNoRelExcelBuilderPersistence.cs new file mode 100644 index 0000000..4ce3b8c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureNotaNoRelExcelBuilderPersistence.cs @@ -0,0 +1,67 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; + +public class FattureNotaNoRelExcelBuilderPersistence(FattureRelExcelQuery command) : DapperBase, IQuery?> +{ + private readonly FattureRelExcelQuery _command = command; + private static readonly string _sql = FattureRelExcelBuilder.SelectNoteSenzaRel(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var computedFatture = new Dictionary(); + + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura; + var where = string.Empty; + + if (!_command.IdEnti!.IsNullNotAny()) + where = " AND t.FKIdEnte in @IdEnti "; + + var sql = _sql + where; + var query = new + { + Anno = anno, + Mese = mese, + TipologiaFattura = tipoFattura, + IdEnti = _command.IdEnti + }; + + var values = await ((IDatabase)this).SelectAsync( + connection!, + sql, + query, + transaction); + + foreach (var r in values) + { + + var key = r.IdEnte + r.TipologiaFattura; + computedFatture.TryAdd(key, r); + var item = computedFatture[key]; + + if (r.CodiceMateriale!.Contains("STORNO")) + { + if (r.CodiceMateriale!.Contains("ANT.") || r.CodiceMateriale!.Contains("ANTICIPO")) + { + if (r.CodiceMateriale!.Contains("NA")) + item.StornoAnticipoAnalogico += r.RigaImponibile; + else + item.StornoAnticipoDigitale += r.RigaImponibile; + } + else if (r.CodiceMateriale!.Contains("ACCONTO")) + { + if (r.CodiceMateriale!.Contains("NA")) + item.StornoAccontoAnalogico += r.RigaImponibile; + else + item.StornoAccontoDigitale += r.RigaImponibile; + } + } + } + return computedFatture.Select(x => x.Value).OrderBy(x => x.TotaleFatturaImponibile); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureQueryRicercaPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureQueryRicercaPersistence.cs new file mode 100644 index 0000000..c1cca72 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureQueryRicercaPersistence.cs @@ -0,0 +1,62 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.SelfCare.Dto; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; + +public class FattureQueryRicercaPersistence(FattureQueryRicerca command) : DapperBase, IQuery +{ + private readonly FattureQueryRicerca _command = command; + private static readonly string _sqlSelectAll = FattureQueryRicercaBuilder.SelectView(); + private static readonly string _sqlSelectEnti = EnteSQLBuilder.SelectAll(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var computedFatture = new List(); + + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura; + + var sqlFatture = _sqlSelectAll; + var sqlEnti = _sqlSelectEnti.Add(schema); + var sql = String.Join(";", sqlEnti, sqlFatture); + + var query = new + { + AnnoRiferimento = anno, + MeseRiferimento = mese, + TipologiaFattura = tipoFattura, + }; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + var enti = await values.ReadAsync(); + var fatture = await values.ReadFirstAsync(); + + if (!_command.IdEnti!.IsNullNotAny()) + enti = enti.Where(x => _command.IdEnti!.Contains(x.IdEnte)).ToList(); + + foreach (var f in fatture) + { + var ente = enti.Where(x => x.IdEnte == f.fattura!.IstitutioID).FirstOrDefault(); + if (ente != null) + { + computedFatture.Add(f); + f.fattura!.RagioneSociale = ente.RagioneSociale; + f.fattura!.TipoContratto = ente.TipoContratto; + f.fattura!.IdContratto = ente.IdContratto; + } + } + var fattData = new FattureListaDto(); + fattData.AddRange(computedFatture); + return fattData; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureRelExcelBuilderPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureRelExcelBuilderPersistence.cs new file mode 100644 index 0000000..40cb442 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureRelExcelBuilderPersistence.cs @@ -0,0 +1,71 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using static Dapper.SqlMapper; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; + +public class FattureRelExcelBuilderPersistence(FattureRelExcelQuery command) : DapperBase, IQuery?> +{ + private readonly FattureRelExcelQuery _command = command; + private static readonly string _sql = FattureRelExcelBuilder.SelectRel(); + private static readonly string _order = FattureRelExcelBuilder.OrderByRel(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var computedFatture = new Dictionary(); + + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura; + + var where = string.Empty; + + if (!_command.IdEnti!.IsNullNotAny()) + where = " AND t.FKIdEnte in @IdEnti "; + + var sql = _sql + where + _order; + + var query = new + { + Anno = anno, + Mese = mese, + TipologiaFattura = tipoFattura, + IdEnti = _command.IdEnti + }; + + var values = await ((IDatabase)this).SelectAsync( + connection!, + sql, + query, + transaction); + + foreach (var r in values) + { + + var key = r.IdEnte + r.TipologiaFattura; + computedFatture.TryAdd(key, r); + var item = computedFatture[key]; + + if (r.CodiceMateriale!.Contains("STORNO")) + { + if (r.CodiceMateriale!.Contains("ANT.") || r.CodiceMateriale!.Contains("ANTICIPO")) + { + if (r.CodiceMateriale!.Contains("NA")) + item.StornoAnticipoAnalogico += r.RigaImponibile; + else + item.StornoAnticipoDigitale += r.RigaImponibile; + } + else if (r.CodiceMateriale!.Contains("ACCONTO")) + { + if (r.CodiceMateriale!.Contains("NA")) + item.StornoAccontoAnalogico += r.RigaImponibile; + else + item.StornoAccontoDigitale += r.RigaImponibile; + } + } + } + return computedFatture.Select(x => x.Value).OrderByDescending(x => x.TotaleFatturaImponibile); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureUnionRelExcelBuilderPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureUnionRelExcelBuilderPersistence.cs new file mode 100644 index 0000000..15decf1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureUnionRelExcelBuilderPersistence.cs @@ -0,0 +1,72 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; + +public class FattureUnionRelExcelBuilderPersistence(FattureRelExcelQuery command) : DapperBase, IQuery?> +{ + private readonly FattureRelExcelQuery _command = command; + private static readonly string _sqlNo = FattureRelExcelBuilder.SelectNoteSenzaRel(); + private static readonly string _sqlRel = FattureRelExcelBuilder.SelectRel(); + private static readonly string _order = FattureRelExcelBuilder.OrderByRel(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var computedFatture = new Dictionary(); + + var anno = _command.Anno; + var mese = _command.Mese; + var tipoFattura = _command.TipologiaFattura; + var where = string.Empty; + + if (!_command.IdEnti!.IsNullNotAny()) + where = " AND t.FKIdEnte in @IdEnti "; + + var sql = _sqlRel + where + " UNION " + _sqlNo + where + _order; + + + var query = new + { + Anno = anno, + Mese = mese, + TipologiaFattura = tipoFattura, + IdEnti = _command.IdEnti + }; + + var values = await ((IDatabase)this).SelectAsync( + connection!, + sql, + query, + transaction); + + foreach (var r in values) + { + + var key = r.IdEnte + r.TipologiaFattura; + computedFatture.TryAdd(key, r); + var item = computedFatture[key]; + + if (r.CodiceMateriale!.Contains("STORNO")) + { + if (r.CodiceMateriale!.Contains("ANT.") || r.CodiceMateriale!.Contains("ANTICIPO")) + { + if (r.CodiceMateriale!.Contains("NA")) + item.StornoAnticipoAnalogico += r.RigaImponibile; + else + item.StornoAnticipoDigitale += r.RigaImponibile; + } + else if (r.CodiceMateriale!.Contains("ACCONTO")) + { + if (r.CodiceMateriale!.Contains("NA")) + item.StornoAccontoAnalogico += r.RigaImponibile; + else + item.StornoAccontoDigitale += r.RigaImponibile; + } + //item.TotaleFatturaImponibile = item.TotaleFatturaImponibile - r.RigaImponibile; + } + } + return computedFatture.Select(x => x.Value).OrderByDescending(x => x.TotaleFatturaImponibile); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureAccontoFatturaExcelHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureAccontoFatturaExcelHandler.cs new file mode 100644 index 0000000..c38ea07 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureAccontoFatturaExcelHandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.QueryHandlers; +public class FattureAccontoFatturaExcelHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler>?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task>?> Handle(FattureAccontoExcelQuery request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + var fTotale = await rs.Query(new FattureAccontoFatturaExcelBuilderPersistence(request), ct); + return new List> { fTotale!}; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureModuloCommessaExcelHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureModuloCommessaExcelHandler.cs new file mode 100644 index 0000000..3c888cb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureModuloCommessaExcelHandler.cs @@ -0,0 +1,31 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Core.Entities.Fattura; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.QueryHandlers; +public class FattureModuloCommessaExcelHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler>?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task>?> Handle(FattureCommessaExcelQuery request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + var fTotale = await rs.Query(new FattureModuloCommessaExcelBuilderPersistence(request), ct); + var fStimate = from p in fTotale where (p.FkIdStato == FatturaExtensions.ChiusaStimato) select p; + var fFattureStimate = from p in fTotale where (p.FkIdStato == FatturaExtensions.ChiusaStimato && p.IdFattura is not null) select p; + var fFatture = from p in fTotale where (p.IdFattura is not null) select p; + var fModuli = from p in fTotale where (p.IdFattura is null) select p; + fTotale = from q in fTotale orderby q.TotaleFattura descending select q; + return new List> { fTotale!, fStimate!, fFattureStimate!, fFatture!, fModuli! }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureQueryRicercaHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureQueryRicercaHandler.cs new file mode 100644 index 0000000..55650f4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureQueryRicercaHandler.cs @@ -0,0 +1,24 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.QueryHandlers; +public class FattureQueryRicercaHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(FattureQueryRicerca request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new FattureQueryRicercaPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureRelExcelHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureRelExcelHandler.cs new file mode 100644 index 0000000..4597f38 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/QueryHandlers/FattureRelExcelHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Fatture.QueryHandlers; +public class FattureRelExcelHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler>?> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task>?> Handle(FattureRelExcelQuery request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + var rel = await rs.Query(new FattureRelExcelBuilderPersistence(request), ct); + + using var rsn = await _factory.Create(cancellationToken: ct); + var relno = await rsn.Query(new FattureNotaNoRelExcelBuilderPersistence(request), ct); + + using var rsu = await _factory.Create(cancellationToken: ct); + var relsu = await rsu.Query(new FattureUnionRelExcelBuilderPersistence(request), ct); + + return new List> { rel!, relsu!, relno! }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/DisplayNameRole.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/DisplayNameRole.cs new file mode 100644 index 0000000..cfcd232 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/DisplayNameRole.cs @@ -0,0 +1,13 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Identity; + +public static class DisplayNameRole +{ + public const string OPERATORE = "Operatore"; + public const string AMMINISTRATORE = "Amministratore"; +} + +public static class DisplayContextAuthentication +{ + public const string SELFCARE = "SELFCARE"; + public const string PAGOPA = "PAGOPA"; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/Extensions/IdentityExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/Extensions/IdentityExtensions.cs new file mode 100644 index 0000000..9e92bda --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/Extensions/IdentityExtensions.cs @@ -0,0 +1,13 @@ +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity.Extensions; + +public static class IdentityExtensions +{ + public static string Map(this string product) + { + if (product == Product.ProdSendino) + return Product.ProdPN; + else return product; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityExtensions.cs new file mode 100644 index 0000000..cfc4526 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityExtensions.cs @@ -0,0 +1,56 @@ +using System.Runtime.CompilerServices; +using System.Security; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity; + + +public static class IdentityExtensions +{ + public static AuthenticationInfo GetAuthInfo(this HttpContext context) + { + var identity = context.User.Identity as ClaimsIdentity ?? throw new SecurityException(); + if (!identity.IsAuthenticated) + throw new SecurityException(); + return identity.Claims.Mapper(); + } + + public static ProfileInfo Mapper(this IList authClaims, string jwt, DateTime validTo) + { + return new ProfileInfo() + { + DescrizioneRuolo = authClaims.FirstOrDefault(c => c.Type == CustomClaim.DescrizioneRuolo)!.Value, + Email = authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Email) == null ? null : authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Email)!.Value, + IdEnte = authClaims.FirstOrDefault(c => c.Type == CustomClaim.IdEnte)!.Value, + JWT = jwt, + Prodotto = authClaims.FirstOrDefault(c => c.Type == CustomClaim.Prodotto)!.Value, + Profilo = authClaims.FirstOrDefault(c => c.Type == CustomClaim.Profilo)!.Value, + Ruolo = authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Role)!.Value, + Valido = validTo, + Id = authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Name)!.Value, + IdTipoContratto = authClaims.FirstOrDefault(c => c.Type == CustomClaim.IdTipoContratto) == null ? null : Convert.ToInt64(authClaims.FirstOrDefault(c => c.Type == CustomClaim.IdTipoContratto)!.Value), + GruppoRuolo = authClaims.FirstOrDefault(c => c.Type == CustomClaim.GruppoRuolo)!.Value, + Auth = authClaims.FirstOrDefault(c => c.Type == CustomClaim.Auth)!.Value, + }; + } + + public static AuthenticationInfo Mapper(this IEnumerable authClaims) + { + return new AuthenticationInfo() + { + DescrizioneRuolo = authClaims.FirstOrDefault(c => c.Type == CustomClaim.DescrizioneRuolo)!.Value, + Email = authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Email) == null ? null : authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Email)!.Value, + IdEnte = authClaims.FirstOrDefault(c => c.Type == CustomClaim.IdEnte)!.Value, + Prodotto = authClaims.FirstOrDefault(c => c.Type == CustomClaim.Prodotto)!.Value, + Profilo = authClaims.FirstOrDefault(c => c.Type == CustomClaim.Profilo)!.Value, + Ruolo = authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Role)!.Value, + Id = authClaims.FirstOrDefault(c => c.Type == ClaimTypes.Name)!.Value, + NomeEnte = authClaims.FirstOrDefault(c => c.Type == CustomClaim.NomeEnte)!.Value, + IdTipoContratto = authClaims.FirstOrDefault(c => c.Type == CustomClaim.IdTipoContratto) == null ? null : Convert.ToInt64(authClaims.FirstOrDefault(c => c.Type == CustomClaim.IdTipoContratto)!.Value), + GruppoRuolo = authClaims.FirstOrDefault(c => c.Type == CustomClaim.GruppoRuolo)!.Value, + Auth = authClaims.FirstOrDefault(c => c.Type == CustomClaim.Auth)!.Value, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityUsersService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityUsersService.cs new file mode 100644 index 0000000..7486511 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/IdentityUsersService.cs @@ -0,0 +1,77 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security; +using System.Security.Claims; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity; + +public class IdentityUsersService : IIdentityUsersService +{ + public List> GetListUserClaimsFromUserAsync(List? authInfos) + { + var list = new List>(); + if (authInfos!.IsNullNotAny()) + throw new SecurityException(); + + foreach (var authInfo in authInfos!) + { + var claimList = GetUserClaimsFromSelfCareUserAsync(authInfo); + list.Add(claimList); + } + return list; + } + + public IList GetUserClaimsFromPagoPAUserAsync(AuthenticationInfo? authInfo) + { + if (authInfo == null) + throw new SecurityException(); + + var claimList = new List + { + new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new(ClaimTypes.Name, authInfo.Id ?? throw new SecurityException()), + new(ClaimTypes.Role, authInfo.Ruolo ?? throw new SecurityException()), + new(CustomClaim.DescrizioneRuolo, authInfo.DescrizioneRuolo! ?? throw new SecurityException()), + new(CustomClaim.Profilo, authInfo.Profilo!), + new(CustomClaim.Prodotto, string.Empty), + new(CustomClaim.IdEnte, string.Empty), + new(CustomClaim.NomeEnte, string.Empty), + new(CustomClaim.GruppoRuolo, authInfo.GruppoRuolo ?? throw new SecurityException()), + new(CustomClaim.Auth, authInfo.Auth ?? throw new SecurityException()) + }; + + if (authInfo.IdTipoContratto != null) + claimList.Add(new Claim(CustomClaim.IdTipoContratto, authInfo.IdTipoContratto.Value.ToString())); + if (authInfo.Email != null) + claimList.Add(new(ClaimTypes.Email, authInfo.Email)); + return claimList; + } + + public IList GetUserClaimsFromSelfCareUserAsync(AuthenticationInfo? authInfo) + { + if (authInfo == null) + throw new SecurityException(); + + var claimList = new List + { + new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new(ClaimTypes.Name, authInfo.Id ?? throw new SecurityException()), + new(ClaimTypes.Role, authInfo.Ruolo ?? throw new SecurityException()), + new(CustomClaim.DescrizioneRuolo, authInfo.DescrizioneRuolo! ?? throw new SecurityException()), + new(CustomClaim.Profilo, authInfo.Profilo ?? throw new SecurityException()), + new(CustomClaim.Prodotto, authInfo.Prodotto ?? throw new SecurityException()), + new(CustomClaim.IdEnte, authInfo.IdEnte ?? throw new SecurityException()), + new(CustomClaim.NomeEnte, authInfo.NomeEnte ?? throw new SecurityException()), + new(CustomClaim.GruppoRuolo, authInfo.GruppoRuolo ?? throw new SecurityException()), + new(CustomClaim.Auth, authInfo.Auth ?? throw new SecurityException()) + }; + + if (authInfo.IdTipoContratto != null) + claimList.Add(new Claim(CustomClaim.IdTipoContratto, authInfo.IdTipoContratto.Value.ToString())); + if (authInfo.Email != null) + claimList.Add(new(ClaimTypes.Email, authInfo.Email)); + + return claimList; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/JwtTokenService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/JwtTokenService.cs new file mode 100644 index 0000000..01f84b8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/JwtTokenService.cs @@ -0,0 +1,72 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity; + +public class JwtTokenService : ITokenService +{ + private readonly string _audience; + private readonly string _issuer; + private readonly byte[] _tokenKey; + private const int HOURS = 4; + public JwtTokenService(string audience, string issuer, string secret) + { + _tokenKey = Encoding.UTF8.GetBytes(secret); + _audience = audience; + _issuer = issuer; + } + + public JwtTokenService(JwtConfiguration conf) + { + _tokenKey = Encoding.UTF8.GetBytes(conf.Secret!); + _audience = conf.ValidAudience!; + _issuer = conf.ValidIssuer!; + } + public ProfileInfo GenerateJwtToken(IList authClaims) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var validTo = DateTime.UtcNow.ItalianTime().AddHours(HOURS); + var tokenDescriptor = new SecurityTokenDescriptor + { + Audience = _audience, + Issuer = _issuer, + Subject = new ClaimsIdentity(authClaims), + Expires = validTo, + SigningCredentials = new SigningCredentials( + new SymmetricSecurityKey(_tokenKey), + SecurityAlgorithms.HmacSha256Signature) + }; + var token = tokenHandler.CreateToken(tokenDescriptor); + var jwt = tokenHandler.WriteToken(token); + + return authClaims.Mapper(jwt, validTo); + } + + public ClaimsPrincipal GetPrincipalFromExpiredToken(string token) + { + var tokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = false, + ValidateAudience = false, + ValidateLifetime = false, + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(_tokenKey), + ClockSkew = TimeSpan.Zero + }; + + var tokenHandler = new JwtSecurityTokenHandler(); + var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken); + if (securityToken is not JwtSecurityToken jwtSecurityToken || + !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, + StringComparison.InvariantCultureIgnoreCase)) + { + throw new SecurityTokenException("Invalid token"); + } + + return principal; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/ProfileService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/ProfileService.cs new file mode 100644 index 0000000..4aa5659 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Identity/ProfileService.cs @@ -0,0 +1,183 @@ +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Security; +using MediatR; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Auth.PagoPA; +using PortaleFatture.BE.Core.Auth.SelfCare; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Identity.Extensions; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; +using PortaleFatture.BE.Infrastructure.Gateway; + +namespace PortaleFatture.BE.Infrastructure.Common.Identity; + +public class ProfileService( + ISelfCareTokenService selfCareTokenService, + IPagoPATokenService pagoPATokenService, + IMediator handler, + IPortaleFattureOptions options, + ILogger logger) : IProfileService +{ + private readonly ISelfCareTokenService _selfCareTokenService = selfCareTokenService; + private readonly IPagoPATokenService _pagoPATokenService = pagoPATokenService; + private readonly ILogger _logger = logger; + private readonly IMediator _handler = handler; + private readonly IPortaleFattureOptions _options = options; + public async Task?> GetSelfCareInfo(string? selfcareToken) + { + if (selfcareToken == null) + { + var msg = "Fatal error with self care exchange token. SelfcareToken missing!"; + _logger.LogError(msg); + throw new SecurityException(msg); + } + var selfcare = await _selfCareTokenService.ValidateContent(selfcareToken, Convert.ToBoolean(_options.SelfCareTimeOut!)); + return await Mapper(selfcare!); + } + + public async Task GetPagoPAInfo(string? pagoPAIdToken, string? azureADAccessToken) + { + if (pagoPAIdToken == null) + { + var msg = "Fatal error with pagoPA AzureAD token! AzureAD token missing!"; + _logger.LogError(msg); + throw new SecurityException(msg); + } + var pagoPA = await _pagoPATokenService.ValidateContent(pagoPAIdToken, azureADAccessToken!, Convert.ToBoolean(_options.SelfCareTimeOut!)); + return Mapper(pagoPA!); + } + + private string Mapper(string mapper) + { + return mapper switch + { + nameof(Ruolo.OPERATOR) => Ruolo.OPERATOR, + _ => Ruolo.ADMIN, + }; + } + + private string MapperGruppi(string gruppo) + { + if (gruppo.Contains(GroupRoles.APPROVIGIONAMENTO)) + return Profilo.Approvigionamento; + else if (gruppo.Contains(GroupRoles.FINANZA)) + return Profilo.Finanza; + else if (gruppo.Contains(GroupRoles.ASSISTENZA)) + return Profilo.Assistenza; + else + throw new DomainException("Gruppo AD sconosciuto!"); + } + + private string MapperGruppoRuolo(string descrizioneRuolo) + { + return descrizioneRuolo; + } + + private string MapperRuolo(string descrizioneRuolo) + { + if (descrizioneRuolo.Equals("operator", StringComparison.CurrentCultureIgnoreCase)) + return DisplayNameRole.OPERATORE; + else + return DisplayNameRole.AMMINISTRATORE; + } + + private AuthenticationInfo? Mapper(PagoPADto model) + { + try + { + var allowedGroups = GroupRoles.GetRoles(_options.AzureAd!.AdGroup!); + var groups = model.Groups!.Where(x => x != null && x.Contains(_options.AzureAd!.AdGroup!)).ToList(); + var portaleGroup = allowedGroups.Where(x => x.Value == true).FirstOrDefault(); + var allowedToPortale = groups.Where(x => portaleGroup.Key == x).FirstOrDefault(); + if (String.IsNullOrEmpty(allowedToPortale)) + throw new SecurityException("You are not allowed in Portale Fatture. There is no group valid Portale Fatture."); + groups.Remove(allowedToPortale); + + var group = groups.Where(x => allowedGroups.Select(x => x.Key).Contains(x)).FirstOrDefault(); + if (groups.IsNullNotAny() || string.IsNullOrEmpty(group)) + throw new SecurityException("Azure Ad roles not valid."); + + return new AuthenticationInfo() + { + Email = model.Email, + Id = model.Uid, + Ruolo = Mapper(DisplayNameRole.AMMINISTRATORE), + IdEnte = null, + DescrizioneRuolo = DisplayNameRole.AMMINISTRATORE, + NomeEnte = null, + GruppoRuolo = group, + Auth = AuthType.PAGOPA, + Profilo = MapperGruppi(group) + }; + } + catch (Exception ex) + { + _logger.LogError(ex, $"Errore autenticazione {ex.InnerException}"); + } + return null; + } + + private async Task?> Mapper(SelfCareDto model) + { + try + { + List infos = []; + var roles = model.Organization!.Roles!.OrderByDescending(x => x.Product); + foreach (var org in roles) + { + var auhtInfo = new AuthenticationInfo() + { + Email = model.Email, + Id = model.Uid, + Prodotto = org.Product!.Map(), + Ruolo = Mapper(org.PartyRole!), + IdEnte = model.Organization!.Id, + DescrizioneRuolo = MapperRuolo(org.PartyRole!), + IdTipoContratto = 0, + Profilo = string.Empty, + GruppoRuolo = MapperGruppoRuolo(org.PartyRole!), + Auth = AuthType.SELFCARE + }; + + // recupero dati db selfcare + var contratto = await _handler.Send(new ContrattoQueryGetById(auhtInfo)); + var ente = await _handler.Send(new EnteQueryGetById(auhtInfo)); + if (contratto != null && ente != null && ente!.Profilo != null && (ente.Profilo == Profilo.Recapitista || ente.Profilo == Profilo.Consolidatore)) + { + auhtInfo.Profilo = ente.Profilo; + auhtInfo.NomeEnte = ente!.Descrizione; + auhtInfo.IdTipoContratto = contratto.IdTipoContratto; + infos.Add(auhtInfo); + } + else if (contratto == null || ente == null || contratto.Prodotto == null || ente.Profilo == null) + { + var msg = "There is no reference in contratti o ente related to id:{idEnte} name:{Name}"; + _logger.LogError(msg, model.Organization!.Id, model.Organization.Name); + throw new ConfigurationException(string.Format("There is no reference in contratti o ente related to id:{0} name:{1}", model.Organization!.Id, model.Organization.Name)); + } + else + { + auhtInfo.Profilo = ente!.Profilo; + auhtInfo.NomeEnte = ente!.Descrizione; + auhtInfo.IdTipoContratto = contratto.IdTipoContratto; + infos.Add(auhtInfo); + } + } + return infos; + } + catch (ConfigurationException ex) + { + _logger.LogError(ex, $"Errore autenticazione {ex.InnerException}"); + throw; + } + catch (Exception ex) + { + _logger.LogError(ex, $"Errore autenticazione {ex.InnerException}"); + } + return null; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/JsonTypeHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/JsonTypeHandler.cs new file mode 100644 index 0000000..7b486c8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/JsonTypeHandler.cs @@ -0,0 +1,22 @@ +using System.Data; +using Dapper; +using DocumentFormat.OpenXml.Drawing.Charts; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common; + +public class JsonTypeHandler : SqlMapper.ITypeHandler +{ + public void SetValue(IDbDataParameter parameter, object value) + { + parameter.Value = ((FattureListaDto)value).Serialize(); // inutile + } + + public object Parse(Type destinationType, object value) + { + if(value is null || String.IsNullOrEmpty(value.ToString()) || value.ToString() == "{}") + return new FattureListaDto(); + return value!.ToString()!.Deserialize(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneCreateCommandHandler.cs new file mode 100644 index 0000000..c120558 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneCreateCommandHandler.cs @@ -0,0 +1,107 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class ContestazioneCreateCommandHandler( + IFattureDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IMediator _handler = handler; + + public async Task Handle(ContestazioneCreateCommand command, CancellationToken ct) + { + if (command.AuthenticationInfo!.Profilo != Profilo.PubblicaAmministrazione && + command.AuthenticationInfo!.Profilo != Profilo.GestorePubblicoServizio && + command.AuthenticationInfo!.Profilo != Profilo.SocietaControlloPubblico && + command.AuthenticationInfo!.Profilo != Profilo.PrestatoreServiziPagamento && + command.AuthenticationInfo!.Profilo != Profilo.AssicurazioniIVASS && + command.AuthenticationInfo!.Profilo != Profilo.StazioneAppaltanteANAC && + command.AuthenticationInfo!.Profilo != Profilo.PartnerTecnologico + ) + throw new SecurityException(); //401 + + Notifica? notifica; + using var read = await _factory.Create(cancellationToken: ct); + { + notifica = await read.Query(new NotificaQueryGetByIdPersistence(new NotificaQueryGetById(command.AuthenticationInfo!, command.IdNotifica)), ct); + } + + + if (notifica == null + || notifica.StatoContestazione != (short)StatoContestazione.NonContestata + || notifica.Fatturata != null && notifica.Fatturata == true + || notifica.TipologiaFattura != null) + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + command.Anno = Convert.ToInt32(notifica.Anno); + command.Mese = Convert.ToInt32(notifica.Mese); + + var azione = await _handler.Send(new AzioneContestazioneQueryGetByIdNotifica(command.AuthenticationInfo, notifica.IdNotifica)); + + if (azione == null || azione.CreazionePermessa == false) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + var adesso = azione.Calendario!.Adesso; + command.DataInserimentoEnte = adesso; + command.StatoContestazione = (short)StatoContestazione.ContestataEnte; + command.Anno = Convert.ToInt32(notifica.Anno); + command.Mese = Convert.ToInt32(notifica.Mese); + + using var uow = await _factory.Create(true, cancellationToken: ct); + var id = await uow.Execute(new ContestazioneCreateCommandPersistence(command, _localizer), ct); + if (id > 0) + { + var cont = new Contestazione() + { + DataInserimentoEnte = command.DataInserimentoEnte, + Id = id, + IdNotifica = command.IdNotifica, + NoteEnte = command.NoteEnte, + StatoContestazione = command.StatoContestazione, + TipoContestazione = command.TipoContestazione, + Anno = command.Anno, + Mese = command.Mese + }; + var rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.Contestazione, + cont.Serialize())), ct); + if (rowAffected == 1) + { + uow.Commit(); + return cont; + } + else + { + uow.Rollback(); + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } + } + else + uow.Rollback(); + + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateCommandHandler.cs new file mode 100644 index 0000000..7ed8735 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateCommandHandler.cs @@ -0,0 +1,140 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class ContestazioneUpdateCommandHandler( + IFattureDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(ContestazioneUpdateCommand command, CancellationToken ct) + { + if (command.AuthenticationInfo!.Profilo != Profilo.PubblicaAmministrazione && + command.AuthenticationInfo!.Profilo != Profilo.GestorePubblicoServizio && + command.AuthenticationInfo!.Profilo != Profilo.SocietaControlloPubblico && + command.AuthenticationInfo!.Profilo != Profilo.PrestatoreServiziPagamento && + command.AuthenticationInfo!.Profilo != Profilo.AssicurazioniIVASS && + command.AuthenticationInfo!.Profilo != Profilo.StazioneAppaltanteANAC && + command.AuthenticationInfo!.Profilo != Profilo.PartnerTecnologico + ) + throw new SecurityException(); //401 + + var azioneCommand = new AzioneContestazioneQueryGetByIdNotifica(command.AuthenticationInfo, command.IdNotifica); + var azione = await _handler.Send(azioneCommand, ct); + var notifica = azione!.Notifica; + var contestazione = azione!.Contestazione; + + if (contestazione == null + || notifica!.Fatturata != null + || notifica.TipologiaFattura != null) + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + if (azione == null + || (azione.CreazionePermessa == false + && azione.RispostaPermessa == false + && azione.ChiusuraPermessa == false + )) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + var adesso = DateTime.UtcNow.ItalianTime(); + command.DataModificaEnte = adesso; + + if (command.StatoContestazione == (short)StatoContestazione.ContestataEnte) // posso solo modificare la nota + { + if(!azione.CreazionePermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + if (notifica.StatoContestazione == (short)StatoContestazione.ContestataEnte) + command.ExpectedStatoContestazione = (short)StatoContestazione.ContestataEnte; + command.RispostaEnte = null; + } + else if (command.StatoContestazione == (short)StatoContestazione.Annullata) + { + if (!azione.CreazionePermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + if (notifica.StatoContestazione == (short)StatoContestazione.ContestataEnte) + command.ExpectedStatoContestazione = (short)StatoContestazione.ContestataEnte; + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + command.RispostaEnte = null; + command.NoteEnte = contestazione.NoteEnte; + } + else if (command.StatoContestazione == (short)StatoContestazione.Chiusa) + { + if (!azione.ChiusuraPermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + command.ExpectedStatoContestazione = notifica.StatoContestazione; + command.NoteEnte = contestazione.NoteEnte; + command.DataChiusura = adesso; // vale stesso campo per tutti + command.Onere = SoggettiContestazione.OnereContestazioneChiusuraEnte(command.Onere!, command.AuthenticationInfo.Profilo); + } + else if (command.StatoContestazione == (short)StatoContestazione.RispostaEnte) + { + if (!azione.RispostaPermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + if (notifica.StatoContestazione == (short)StatoContestazione.RispostaSend + || notifica.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || notifica.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || notifica.StatoContestazione == (short)StatoContestazione.RispostaEnte) + { + command.ExpectedStatoContestazione = notifica.StatoContestazione; + command.NoteEnte = contestazione.NoteEnte; + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + + using var uow = await _factory.Create(true, cancellationToken: ct); + { + var id = await uow.Execute(new ContestazioneUpdateCommandPersistence(command, _localizer), ct); + if (id > 0) + { + var cont = await uow.Query(new ContestazioneQueryGetByIdNotificaPersistence(new ContestazioneQueryGetByIdNotifica(command.AuthenticationInfo, command.IdNotifica)), ct); + var rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.Contestazione, + cont.Serialize())), ct); + + if (rowAffected == 1) + { + uow.Commit(); + return cont; + } + else + uow.Rollback(); + } + else + uow.Rollback(); + } + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateConsolidatoreCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateConsolidatoreCommandHandler.cs new file mode 100644 index 0000000..c817564 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateConsolidatoreCommandHandler.cs @@ -0,0 +1,112 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class ContestazioneUpdateConsolidatoreCommandHandler( + IFattureDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(ContestazioneUpdateConsolidatoreCommand command, CancellationToken ct) + { + var azioneCommand = new AzioneContestazioneQueryGetByIdNotifica(command.AuthenticationInfo!, command.IdNotifica); + var azione = await _handler.Send(azioneCommand, ct); + var notifica = azione!.Notifica; + var contestazione = azione!.Contestazione; + + if (contestazione == null + || notifica!.Fatturata != null + || notifica.TipologiaFattura != null) + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + if (azione == null + || (azione.CreazionePermessa == false + && azione.RispostaPermessa == false + && azione.ChiusuraPermessa == false + )) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + if (notifica.Consolidatore != command.AuthenticationInfo!.IdEnte) + throw new DomainException(_localizer["NotificaContestazioneValidationError", command.IdNotifica!]); + + var adesso = DateTime.UtcNow.ItalianTime(); + if (contestazione.DataInserimentoConsolidatore == null) + command.DataInserimentoConsolidatore = adesso; + else + { + command.DataInserimentoConsolidatore = contestazione.DataInserimentoConsolidatore; + command.DataModificaConsolidatore = adesso; + } + + + if (contestazione.StatoContestazione == (short)StatoContestazione.ContestataEnte + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaEnte + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaSend) // posso rispondere + { + if (command.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore && azione.RispostaPermessa) + { + command.ExpectedStatoContestazione = notifica.StatoContestazione; + } + else if (command.StatoContestazione == (short)StatoContestazione.Accettata && azione.RispostaPermessa) + { + command.Onere = Profilo.Consolidatore; + command.NoteConsolidatore ??= contestazione.NoteConsolidatore; + command.ExpectedStatoContestazione = notifica.StatoContestazione; + command.DataChiusura = adesso; + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + + using var uow = await _factory.Create(true, cancellationToken: ct); + { + var id = await uow.Execute(new ContestazioneUpdateConsolidatoreCommandPersistence(command, _localizer), ct); + if (id > 0) + { + var cont = await uow.Query(new ContestazioneQueryGetByIdNotificaPersistence(new ContestazioneQueryGetByIdNotifica(command.AuthenticationInfo, command.IdNotifica)), ct); + var rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.Contestazione, + cont.Serialize())), ct); + + if (rowAffected == 1) + { + uow.Commit(); + return cont; + } + else + uow.Rollback(); + } + else + uow.Rollback(); + } + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdatePagoPaCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdatePagoPaCommandHandler.cs new file mode 100644 index 0000000..5fa3074 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdatePagoPaCommandHandler.cs @@ -0,0 +1,134 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class ContestazioneUpdatePagoPaCommandHandler( + IFattureDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(ContestazioneUpdatePagoPACommand command, CancellationToken ct) + { + var authInfo = command.AuthenticationInfo!; + + if (!(authInfo.Profilo == Profilo.Approvigionamento + || authInfo.Profilo == Profilo.Finanza + || authInfo.Profilo == Profilo.Assistenza)) + throw new SecurityException(); //401 + + var azioneCommand = new AzioneContestazioneQueryGetByIdNotifica(authInfo, command.IdNotifica); + var azione = await _handler.Send(azioneCommand, ct); + var notifica = azione!.Notifica; + var contestazione = azione!.Contestazione; + + if (contestazione == null + || notifica == null + || notifica!.Fatturata != null + || notifica.TipologiaFattura != null) + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + if (azione == null + || (azione.CreazionePermessa == false + && azione.RispostaPermessa == false + && azione.ChiusuraPermessa == false + )) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + var adesso = DateTime.UtcNow.ItalianTime(); + + if(contestazione.DataInserimentoSend == null) + command.DataInserimentoSend = adesso; + else + { + command.DataInserimentoSend = contestazione.DataInserimentoSend; + command.DataModificaSend = adesso; + } + + + if (command.StatoContestazione == (short)StatoContestazione.Accettata) + { + if (!azione.ChiusuraPermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + command.ExpectedStatoContestazione = notifica.StatoContestazione; + command.DataChiusura = adesso; // vale stesso campo per tutti + command.Onere = SoggettiContestazione.OnereContestazioneAccettazionePA(command.Onere!); + } + else if (command.StatoContestazione == (short)StatoContestazione.Chiusa) + { + if (!azione.ChiusuraPermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + command.ExpectedStatoContestazione = notifica.StatoContestazione; + command.DataChiusura = adesso; // vale stesso campo per tutti + command.Onere = SoggettiContestazione.OnereContestazioneChiusuraPA(command.Onere!); + } + else if (command.StatoContestazione == (short)StatoContestazione.RispostaSend) + { + if (!azione.RispostaPermessa) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + if (notifica.StatoContestazione == (short)StatoContestazione.RispostaSend + || notifica.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || notifica.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || notifica.StatoContestazione == (short)StatoContestazione.RispostaEnte + || notifica.StatoContestazione == (short)StatoContestazione.ContestataEnte) + { + command.ExpectedStatoContestazione = notifica.StatoContestazione; + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + + using var uow = await _factory.Create(true, cancellationToken: ct); + { + var id = await uow.Execute(new ContestazioneUpdatePagoPACommandPersistence(command, _localizer), ct); + if (id > 0) + { + var contest = await uow.Query(new ContestazioneQueryGetByIdNotificaPersistence(new ContestazioneQueryGetByIdNotifica(command.AuthenticationInfo!, command.IdNotifica)), ct); + command.AuthenticationInfo!.IdEnte = notifica.IdEnte; + var rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo!, + adesso, + TipoStorico.Contestazione, + contest.Serialize())), ct); + + if (rowAffected == 1) + { + uow.Commit(); + return contest; + } + else + uow.Rollback(); + } + else + uow.Rollback(); + } + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateRecapitistaCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateRecapitistaCommandHandler.cs new file mode 100644 index 0000000..17dd299 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/CommandHandlers/ContestazioneUpdateRecapitistaCommandHandler.cs @@ -0,0 +1,110 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Storici; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands; +using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.CommandHandlers; + +public class ContestazioneUpdateRecapitistaCommandHandler( + IFattureDbContextFactory factory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(ContestazioneUpdateRecapitistaCommand command, CancellationToken ct) + { + var azioneCommand = new AzioneContestazioneQueryGetByIdNotifica(command.AuthenticationInfo!, command.IdNotifica); + var azione = await _handler.Send(azioneCommand, ct); + var notifica = azione!.Notifica; + var contestazione = azione!.Contestazione; + + if (contestazione == null + || notifica!.Fatturata != null + || notifica.TipologiaFattura != null) + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + if (azione == null + || (azione.CreazionePermessa == false + && azione.RispostaPermessa == false + && azione.ChiusuraPermessa == false + )) + throw new ValidationException(_localizer["NotificaContestazioneValidationError", $"{notifica.Anno}-{notifica.Mese}"]); + + if (notifica.Recapitista != command.AuthenticationInfo!.IdEnte) + throw new DomainException(_localizer["NotificaContestazioneValidationError", command.IdNotifica!]); + + var adesso = DateTime.UtcNow.ItalianTime(); + if (contestazione.DataInserimentoRecapitista == null) + command.DataInserimentoRecapitista = adesso; + else + { + command.DataInserimentoRecapitista = contestazione.DataInserimentoRecapitista; + command.DataModificaRecapitista = adesso; + } + + if (contestazione.StatoContestazione == (short)StatoContestazione.ContestataEnte + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaEnte + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || contestazione.StatoContestazione == (short)StatoContestazione.RispostaSend) // posso rispondere + { + if (command.StatoContestazione == (short)StatoContestazione.RispostaRecapitista && azione.RispostaPermessa) + { + command.ExpectedStatoContestazione = notifica.StatoContestazione; + } + else if (command.StatoContestazione == (short)StatoContestazione.Accettata && azione.RispostaPermessa) + { + command.Onere = Profilo.Recapitista; + command.NoteRecapitista = command.NoteRecapitista??contestazione.NoteRecapitista; + command.ExpectedStatoContestazione = notifica.StatoContestazione; + command.DataChiusura = adesso; + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } + else + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + + using var uow = await _factory.Create(true, cancellationToken: ct); + { + var id = await uow.Execute(new ContestazioneUpdateRecapitistaCommandPersistence(command, _localizer), ct); + if (id > 0) + { + var cont = await uow.Query(new ContestazioneQueryGetByIdNotificaPersistence(new ContestazioneQueryGetByIdNotifica(command.AuthenticationInfo, command.IdNotifica)), ct); + var rowAffected = await uow.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand( + command.AuthenticationInfo, + adesso, + TipoStorico.Contestazione, + cont.Serialize())), ct); + + if (rowAffected == 1) + { + uow.Commit(); + return cont; + } + else + uow.Rollback(); + } + else + uow.Rollback(); + } + throw new DomainException(_localizer["CreazioneContestazioneError", command.IdNotifica!]); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneCreateCommand.cs new file mode 100644 index 0000000..ba0e15e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneCreateCommand.cs @@ -0,0 +1,17 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class ContestazioneCreateCommand(IAuthenticationInfo? authenticationInfo) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public int TipoContestazione { get; set; } + public string? IdNotifica { get; set; } + public string? NoteEnte { get; set; } + public DateTime DataInserimentoEnte { get; set; } + public short StatoContestazione { get; set; } + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateCommand.cs new file mode 100644 index 0000000..6e809c5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateCommand.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class ContestazioneUpdateCommand(IAuthenticationInfo? authenticationInfo, string? IdNotifica) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdNotifica { get; internal set; } = IdNotifica; + public string? NoteEnte { get; set; } + public string? RispostaEnte { get; set; } + public string? Onere { get; set; } + public DateTime DataModificaEnte { get; set; } + public DateTime? DataChiusura { get; set; } + public short StatoContestazione { get; set; } + public short ExpectedStatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateConsolidatoreCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateConsolidatoreCommand.cs new file mode 100644 index 0000000..7f5ce0a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateConsolidatoreCommand.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class ContestazioneUpdateConsolidatoreCommand(IAuthenticationInfo? authenticationInfo, string? IdNotifica) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdNotifica { get; internal set; } = IdNotifica; + public string? NoteConsolidatore { get; set; } + public DateTime? DataModificaConsolidatore{ get; set; } + public DateTime? DataInserimentoConsolidatore { get; set; } + public short ExpectedStatoContestazione { get; set; } + public string? Onere { get; set; } + public DateTime? DataChiusura { get; set; } + public short StatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdatePagoPACommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdatePagoPACommand.cs new file mode 100644 index 0000000..777b673 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdatePagoPACommand.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class ContestazioneUpdatePagoPACommand(IAuthenticationInfo? authenticationInfo, string? IdNotifica) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdNotifica { get; internal set; } = IdNotifica; + public string? Onere { get; set; } + public DateTime? DataInserimentoSend { get; set; } + public DateTime? DataModificaSend { get; set; } + public DateTime? DataChiusura { get; set; } + public string? NoteSend { get; set; } + public short StatoContestazione { get; set; } + public short ExpectedStatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateRecapitistaCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateRecapitistaCommand.cs new file mode 100644 index 0000000..cddc103 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/ContestazioneUpdateRecapitistaCommand.cs @@ -0,0 +1,18 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +public class ContestazioneUpdateRecapitistaCommand(IAuthenticationInfo? authenticationInfo, string? IdNotifica) : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? IdNotifica { get; internal set; } = IdNotifica; + public string? NoteRecapitista { get; set; } + public DateTime? DataModificaRecapitista { get; set; } + public DateTime? DataInserimentoRecapitista { get; set; } + public string? Onere { get; set; } + public DateTime? DataChiusura { get; set; } + public short StatoContestazione { get; set; } + public short ExpectedStatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneCreateCommandPersistence.cs new file mode 100644 index 0000000..a295c19 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneCreateCommandPersistence.cs @@ -0,0 +1,51 @@ +using System.Data; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class ContestazioneCreateCommandPersistence(ContestazioneCreateCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly ContestazioneCreateCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlInsert = @" +INSERT INTO [schema][Contestazioni] + ([FkIdTipoContestazione] + ,[NoteEnte] + ,[FkIdFlagContestazione] + ,[DataInserimentoEnte] + ,[FkIdNotifica] + ,[Anno] + ,[Mese]) + VALUES + (@TipoContestazione, + @NoteEnte, + @StatoContestazione, + @DataInserimentoEnte, + @IdNotifica, + @Anno, + @Mese); +Select SCOPE_IDENTITY() 'SCOPE_IDENTITY'; +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + try + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), _command, transaction); + } + catch (SqlException ex) + { + if (ex.Number == 2627) // 2627 - Violation in unique constraint + throw new DomainException(_localizer["CreazioneContestazioneDuplicate", _command.IdNotifica!]); + else + throw new DomainException(_localizer["CreazioneContestazioneError", _command.IdNotifica!]); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateCommandPersistence.cs new file mode 100644 index 0000000..254395e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateCommandPersistence.cs @@ -0,0 +1,32 @@ +using System.Data; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class ContestazioneUpdateCommandPersistence(ContestazioneUpdateCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly ContestazioneUpdateCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlUpdate = @" +UPDATE [schema][Contestazioni] + SET [NoteEnte] = @NoteEnte + ,[RispostaEnte] = @RispostaEnte + ,[FkIdFlagContestazione] = @StatoContestazione + ,[Onere] = @Onere + ,[DataModificaEnte] = @DataModificaEnte + ,[DataChiusura] = @DataChiusura + WHERE FkIdNotifica=@IdNotifica AND FkIdFlagContestazione=@ExpectedStatoContestazione +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdate.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateConsolidatoreCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateConsolidatoreCommandPersistence.cs new file mode 100644 index 0000000..e943ca8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateConsolidatoreCommandPersistence.cs @@ -0,0 +1,30 @@ +using System.Data; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class ContestazioneUpdateConsolidatoreCommandPersistence(ContestazioneUpdateConsolidatoreCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly ContestazioneUpdateConsolidatoreCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlUpdate = @" +UPDATE [schema][Contestazioni] + SET [NoteConsolidatore] = @NoteConsolidatore + ,[DataInserimentoConsolidatore] = @DataInserimentoConsolidatore + ,[DataModificaConsolidatore] = @DataModificaConsolidatore + ,[FkIdFlagContestazione]= @StatoContestazione + ,[Onere]= @Onere + ,[DataChiusura]= @DataChiusura + WHERE FkIdNotifica=@IdNotifica AND FkIdFlagContestazione=@ExpectedStatoContestazione +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdate.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdatePagoPACommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdatePagoPACommandPersistence.cs new file mode 100644 index 0000000..67496cf --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdatePagoPACommandPersistence.cs @@ -0,0 +1,32 @@ +using System.Data; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class ContestazioneUpdatePagoPACommandPersistence(ContestazioneUpdatePagoPACommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly ContestazioneUpdatePagoPACommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlUpdate = @" +UPDATE [schema][Contestazioni] + SET [NoteSend] = @NoteSend + ,[FkIdFlagContestazione] = @StatoContestazione + ,[Onere] = @Onere + ,[DataInserimentoSend] = @DataInserimentoSend + ,[DataModificaSend] = @DataModificaSend + ,[DataChiusura] = @DataChiusura + WHERE FkIdNotifica=@IdNotifica AND FkIdFlagContestazione=@ExpectedStatoContestazione +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdate.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateRecapitistaCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateRecapitistaCommandPersistence.cs new file mode 100644 index 0000000..472f0d7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Commands/Persistence/ContestazioneUpdateRecapitistaCommandPersistence.cs @@ -0,0 +1,32 @@ +using System.Data; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Commands.Persistence; + +public class ContestazioneUpdateRecapitistaCommandPersistence(ContestazioneUpdateRecapitistaCommand command, IStringLocalizer localizer) : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly ContestazioneUpdateRecapitistaCommand _command = command; + IStringLocalizer _localizer = localizer; + + private static readonly string _sqlUpdate = @" +UPDATE [schema][Contestazioni] + SET [NoteRecapitista] = @NoteRecapitista + ,[DataInserimentoRecapitista] = @DataInserimentoRecapitista + ,[DataModificaRecapitista] = @DataModificaRecapitista + ,[FkIdFlagContestazione]= @StatoContestazione + ,[Onere]= @Onere + ,[DataChiusura]= @DataChiusura + WHERE FkIdNotifica=@IdNotifica AND FkIdFlagContestazione=@ExpectedStatoContestazione +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlUpdate.Add(schema), _command, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/NotificaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/NotificaDto.cs new file mode 100644 index 0000000..1772182 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/NotificaDto.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +public sealed class NotificaDto +{ + [JsonPropertyOrder(-1)] + public IEnumerable? Notifiche { get; set; } + [JsonPropertyOrder(-2)] + public int Count { get; set; } +} + +public sealed class NotificaRECCONDto +{ + [JsonPropertyOrder(-1)] + public IEnumerable? Notifiche { get; set; } + [JsonPropertyOrder(-2)] + public int Count { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/QueryDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/QueryDto.cs new file mode 100644 index 0000000..fddfa8c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/QueryDto.cs @@ -0,0 +1,23 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +public class QueryDto +{ + public string? IdEnte { get; set; } = null; + public int? Anno { get; set; } + public int? Mese { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } + public string? Prodotto { get; set; } + + public string? Cap { get; set; } + public string? Profilo { get; set; } + public string? TipoNotifica { get; set; } + public int[]? Contestazione { get; set; } + public string? Iun { get; set; } + public string[]? EntiIds { get; set; } = null; + public string? RecipientId { get; set; } + public string? Recapitista { get; set; } + public string? Consolidatore { get; set; } + public string[]? Recapitisti { get; set; } + public string[]? Consolidatori { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/RECCONNotificaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/RECCONNotificaDto.cs new file mode 100644 index 0000000..a9cab89 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/RECCONNotificaDto.cs @@ -0,0 +1,140 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +public class RECCONNotificaDto +{ + [Column("internal_organization_id")] + [HeaderAttributeRECCON(caption: "internal_organization_id", Order = 16)] + public string? IdEnte { get; set; } + + [Column("institutionType")] + [HeaderAttributeRECCON(caption: "institutionType", Order = 28)] + public string? Profilo { get; set; } + + [Column("contract_id")] + [HeaderAttributeRECCON(caption: "contract_id", Order = 1)] + public string? IdContratto { get; set; } + + [Column("zip_code")] + [HeaderAttributeRECCON(caption: "zip_code", Order = 4)] + public string? CAP { get; set; } + + [Column("foreign_state")] + [HeaderAttributeRECCON(caption: "foreign_state", Order = 5)] + public string? StatoEstero { get; set; } + + [Column("number_of_pages")] + [HeaderAttributeRECCON(caption: "number_of_pages", Order = 6)] + public string? NumberOfPages { get; set; } + + [Column("g_envelope_weight")] + [HeaderAttributeRECCON(caption: "g_envelope_weight", Order = 7)] + public string? GEnvelopeWeight { get; set; } + + [Column("cost_eurocent")] + [HeaderAttributeRECCON(caption: "cost_eurocent", Order = 8)] + public string? CostEuroInCentesimi { get; set; } + + [Column("timeline_category")] + [HeaderAttributeRECCON(caption: "timeline_category", Order = 9)] + public string? TimelineCategory { get; set; } + + [Column("contestazione")] + [HeaderAttribute(caption: "contestazione", Order = 18)] + public string? Contestazione { get; set; } + + [Column("idContestazione")] + public short StatoContestazione { get; set; } + + [Column("notificationtype")] + [HeaderAttributeRECCON(caption: "paper_product_type", Order = 10)] + public string? TipoNotifica { get; set; } + + [Column("event_id")] + [HeaderAttributeRECCON(caption: "event_id", Order = 11)] + public string? IdNotifica { get; set; } + + [Column("iun")] + [HeaderAttributeRECCON(caption: "iun", Order = 12)] + public string? IUN { get; set; } + + [Column("notification_sent_at")] + [HeaderAttributeRECCON(caption: "notification_sent_at", Order = 15)] + public string? DataInvio { get; set; } + + [Column("event_timestamp")] + [HeaderAttributeRECCON(caption: "event_timestamp", Order = 17)] + public string? Data { get; set; } + + [Column("recipient_index")] + [HeaderAttributeRECCON(caption: "recipient_index", Order = 18)] + public string? RecipientIndex { get; set; } + + [Column("recipient_type")] + [HeaderAttributeRECCON(caption: "recipient_type", Order = 19)] + public string? RecipientType { get; set; } + + [Column("recipient_id")] + [HeaderAttributeRECCON(caption: "recipient_id", Order = 20)] + public string? RecipientId { get; set; } + + [Column("year")] + [HeaderAttributeRECCON(caption: "year", Order = 21)] + public string? Anno { get; set; } + + [Column("month")] + [HeaderAttributeRECCON(caption: "month", Order = 22)] + public string? Mese { get; set; } + + [Column("daily")] + [HeaderAttributeRECCON(caption: "daily", Order = 23)] + public string? AnnoMeseGiorno { get; set; } + + [Column("item_code")] + [HeaderAttributeRECCON(caption: "item_code", Order = 24)] + public string? ItemCode { get; set; } + + [Column("notification_request_id")] + [HeaderAttributeRECCON(caption: "notification_request_id", Order = 25)] + public string? NotificationRequestId { get; set; } + + [Column("recipient_tax_id")] + [HeaderAttributeRECCON(caption: "recipient_tax_id", Order = 26)] + public string? RecipientTaxId { get; set; } + + [Column("Fatturabile")] + public bool? Fatturata { get; set; } + + [Column("onere")] + public string? Onere { get; set; } + + [Column("NoteEnte")] + [HeaderAttributeRECCON(caption: "Note Ente", Order = 30)] + public string? NoteEnte { get; set; } + + [Column("RispostaEnte")] + [HeaderAttributeRECCON(caption: "Risposta Ente", Order = 31)] + public string? RispostaEnte { get; set; } + + [Column("NoteSend")] + [HeaderAttributeRECCON(caption: "Risposta Send", Order = 32)] + public string? NoteSend { get; set; } + + [Column("NoteRecapitista")] + [HeaderAttributeRECCON(caption: "Risposta Recapitista", Order = 33)] + public string? NoteRecapitista { get; set; } + + [Column("NoteConsolidatore")] + [HeaderAttributeRECCON(caption: "Risposta Consolidatore", Order = 35)] + public string? NoteConsolidatore { get; set; } + + [Column("TipoContestazione")] + [HeaderAttributeRECCON(caption: "Tipo Contestazione", Order = 40)] + public string? TipoContestazione { get; set; } + + [Column("TipologiaFattura")] + [HeaderAttributeRECCON(caption: "Tipologia Fattura", Order = 41)] + public string? TipologiaFattura { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/SimpleNotificaDto.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/SimpleNotificaDto.cs new file mode 100644 index 0000000..c6457e2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Dto/SimpleNotificaDto.cs @@ -0,0 +1,184 @@ +using System.ComponentModel.DataAnnotations.Schema; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +public class SimpleNotificaDto +{ + [Column("internal_organization_id")] + [HeaderAttributev2(caption: "internal_organization_id", Order = 16)] + public string? IdEnte { get; set; } + + [Column("description")] + [HeaderAttributev2(caption: "description", Order = 27)] + public string? RagioneSociale { get; set; } + + [Column("institutionType")] + [HeaderAttributev2(caption: "institutionType", Order = 28)] + public string? Profilo { get; set; } + + [Column("contract_id")] + [HeaderAttribute(caption: "contract_id", Order = 1)] + [HeaderAttributev2(caption: "contract_id", Order = 1)] + public string? IdContratto { get; set; } + + [Column("tax_code")] + [HeaderAttribute(caption: "tax_code", Order = 2)] + [HeaderAttributev2(caption: "tax_code", Order = 2)] + public string? CodiceFiscale { get; set; } + + [Column("vat_number")] + [HeaderAttribute(caption: "vat_number", Order = 3)] + [HeaderAttributev2(caption: "vat_number", Order = 3)] + public string? PIva { get; set; } + + [Column("zip_code")] + [HeaderAttribute(caption: "zip_code", Order = 4)] + [HeaderAttributev2(caption: "zip_code", Order = 4)] + public string? CAP { get; set; } + + [Column("foreign_state")] + [HeaderAttribute(caption: "foreign_state", Order = 5)] + [HeaderAttributev2(caption: "foreign_state", Order = 5)] + public string? StatoEstero { get; set; } + + [Column("number_of_pages")] + [HeaderAttributev2(caption: "number_of_pages", Order = 6)] + public string? NumberOfPages { get; set; } + + [Column("g_envelope_weight")] + [HeaderAttributev2(caption: "g_envelope_weight", Order = 7)] + public string? GEnvelopeWeight { get; set; } + + [Column("cost_eurocent")] + [HeaderAttribute(caption: "cost_eurocent", Order = 6)] + [HeaderAttributev2(caption: "cost_eurocent", Order = 8)] + public string? CostEuroInCentesimi { get; set; } + + [Column("timeline_category")] + [HeaderAttribute(caption: "timeline_category", Order = 7)] + [HeaderAttributev2(caption: "timeline_category", Order = 9)] + public string? TimelineCategory { get; set; } + + [Column("contestazione")] + [HeaderAttribute(caption: "contestazione", Order = 18)] + public string? Contestazione { get; set; } + + [Column("idContestazione")] + public short StatoContestazione { get; set; } + + [Column("notificationtype")] + [HeaderAttribute(caption: "paper_product_type", Order = 8)] + [HeaderAttributev2(caption: "paper_product_type", Order = 10)] + public string? TipoNotifica { get; set; } + + [Column("event_id")] + [HeaderAttribute(caption: "event_id", Order = 9)] + [HeaderAttributev2(caption: "event_id", Order = 11)] + public string? IdNotifica { get; set; } + + [Column("iun")] + [HeaderAttribute(caption: "iun", Order = 10)] + [HeaderAttributev2(caption: "iun", Order = 12)] + public string? IUN { get; set; } + + [Column("consolidatore")] + [HeaderAttribute(caption: "consolidatore", Order = 11)] + [HeaderAttributev2(caption: "consolidatore", Order = 13)] + public string? Consolidatore { get; set; } + + [Column("recapitista")] + [HeaderAttribute(caption: "recapitista", Order = 12)] + [HeaderAttributev2(caption: "recapitista", Order = 14)] + public string? Recapitista { get; set; } + + [Column("notification_sent_at")] + [HeaderAttribute(caption: "notification_sent_at", Order = 13)] + [HeaderAttributev2(caption: "notification_sent_at", Order = 15)] + public string? DataInvio { get; set; } + + [Column("event_timestamp")] + [HeaderAttribute(caption: "event_timestamp", Order = 14)] + [HeaderAttributev2(caption: "event_timestamp", Order = 17)] + public string? Data { get; set; } + + [Column("recipient_index")] + [HeaderAttributev2(caption: "recipient_index", Order = 18)] + public string? RecipientIndex { get; set; } + + [Column("recipient_type")] + [HeaderAttributev2(caption: "recipient_type", Order = 19)] + public string? RecipientType { get; set; } + + [Column("recipient_id")] + [HeaderAttributev2(caption: "recipient_id", Order = 20)] + public string? RecipientId { get; set; } + + [Column("year")] + [HeaderAttribute(caption: "year", Order = 15)] + [HeaderAttributev2(caption: "year", Order = 21)] + public string? Anno { get; set; } + + [Column("month")] + [HeaderAttribute(caption: "month", Order = 16)] + [HeaderAttributev2(caption: "month", Order = 22)] + public string? Mese { get; set; } + + [Column("daily")] + [HeaderAttribute(caption: "daily", Order = 17)] + [HeaderAttributev2(caption: "daily", Order = 23)] + public string? AnnoMeseGiorno { get; set; } + + [Column("item_code")] + [HeaderAttributev2(caption: "item_code", Order = 24)] + public string? ItemCode { get; set; } + + [Column("notification_request_id")] + [HeaderAttributev2(caption: "notification_request_id", Order = 25)] + public string? NotificationRequestId { get; set; } + + [Column("recipient_tax_id")] + [HeaderAttributev2(caption: "recipient_tax_id", Order = 26)] + public string? RecipientTaxId { get; set; } + + [Column("Fatturabile")] + public bool? Fatturata { get; set; } + + [Column("onere")] + public string? Onere { get; set; } + + [Column("NoteEnte")] + [HeaderAttribute(caption: "Note Ente", Order = 18)] + [HeaderAttributev2(caption: "Note Ente", Order = 27)] + public string? NoteEnte { get; set; } + + [Column("RispostaEnte")] + [HeaderAttribute(caption: "Risposta Ente", Order = 19)] + [HeaderAttributev2(caption: "Risposta Ente", Order = 28)] + public string? RispostaEnte { get; set; } + + [Column("NoteSend")] + [HeaderAttribute(caption: "Risposta Send", Order = 20)] + [HeaderAttributev2(caption: "Risposta Send", Order = 29)] + public string? NoteSend { get; set; } + + [Column("NoteRecapitista")] + [HeaderAttribute(caption: "Risposta Recapitista", Order = 21)] + [HeaderAttributev2(caption: "Risposta Recapitista", Order = 30)] + public string? NoteRecapitista { get; set; } + + [Column("NoteConsolidatore")] + [HeaderAttribute(caption: "Risposta Consolidatore", Order = 22)] + [HeaderAttributev2(caption: "Risposta Consolidatore", Order = 31)] + public string? NoteConsolidatore { get; set; } + + [Column("TipoContestazione")] + [HeaderAttribute(caption: "Tipo Contestazione", Order = 23)] + [HeaderAttributev2(caption: "Tipo Contestazione", Order = 32)] + public string? TipoContestazione { get; set; } + + [Column("TipologiaFattura")] + [HeaderAttribute(caption: "Tipologia Fattura", Order = 24)] + [HeaderAttributev2(caption: "Tipologia Fattura", Order = 33)] + public string? TipologiaFattura { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/AzioneContestazioneQueryGetByIdNotifica.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/AzioneContestazioneQueryGetByIdNotifica.cs new file mode 100644 index 0000000..17a94e0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/AzioneContestazioneQueryGetByIdNotifica.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class AzioneContestazioneQueryGetByIdNotifica(IAuthenticationInfo authenticationInfo, string? idNotifica) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + + public string? IdNotifica { get; internal set; } = idNotifica; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/ContestazioneQueryGetByIdNotifica.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/ContestazioneQueryGetByIdNotifica.cs new file mode 100644 index 0000000..c8df990 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/ContestazioneQueryGetByIdNotifica.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class ContestazioneQueryGetByIdNotifica(IAuthenticationInfo authenticationInfo, string? idNotifica) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + + public string? IdNotifica { get; internal set; } = idNotifica; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByConsolidatore.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByConsolidatore.cs new file mode 100644 index 0000000..a400532 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByConsolidatore.cs @@ -0,0 +1,22 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class NotificaQueryGetByConsolidatore(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } + public string? Prodotto { get; set; } + public string? Cap { get; set; } + public string? Profilo { get; set; } + public TipoNotifica? TipoNotifica { get; set; } + public string? Iun { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } + public int[]? StatoContestazione { get; set; } + public string? RecipientId { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetById.cs new file mode 100644 index 0000000..568701a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetById.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class NotificaQueryGetById(IAuthenticationInfo authenticationInfo, string? idNotifica) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + + public string? IdNotifica { get; internal set; } = idNotifica; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByIdEnte.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByIdEnte.cs new file mode 100644 index 0000000..1f2b1cc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByIdEnte.cs @@ -0,0 +1,22 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class NotificaQueryGetByIdEnte(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } + public string? Prodotto { get; set; } + public string? Cap { get; set; } + public string? Profilo { get; set; } + public string? RecipientId { get; set; } + public TipoNotifica? TipoNotifica { get; set; } + public string? Iun { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } + public int[]? StatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByListaEnti.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByListaEnti.cs new file mode 100644 index 0000000..9d029c0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByListaEnti.cs @@ -0,0 +1,25 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class NotificaQueryGetByListaEnti(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } + public string? Prodotto { get; set; } + public string? Cap { get; set; } + public string? Profilo { get; set; } + public TipoNotifica? TipoNotifica { get; set; } + public string? Iun { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } + public int[]? StatoContestazione { get; set; } + public string[]? EntiIds { get; set; } + public string? RecipientId { get; set; } + public string[]? Consolidatori { get; set; } + public string[]? Recapitisti { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByRecapitista.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByRecapitista.cs new file mode 100644 index 0000000..8c2403d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/NotificaQueryGetByRecapitista.cs @@ -0,0 +1,22 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +public class NotificaQueryGetByRecapitista(IAuthenticationInfo authenticationInfo) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int? AnnoValidita { get; set; } + public int? MeseValidita { get; set; } + public string? Prodotto { get; set; } + public string? Cap { get; set; } + public string? Profilo { get; set; } + public string? RecipientId { get; set; } + public TipoNotifica? TipoNotifica { get; set; } + public string? Iun { get; set; } + public int? Page { get; set; } + public int? Size { get; set; } + public int[]? StatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/ContestazioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/ContestazioneSQLBuilder.cs new file mode 100644 index 0000000..ac504db --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/ContestazioneSQLBuilder.cs @@ -0,0 +1,57 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; + +internal static class ContestazioneSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + Contestazione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.TipoContestazione).GetAsColumn()); + builder.Select(nameof(@obj.IdNotifica).GetAsColumn()); + builder.Select(nameof(@obj.NoteEnte).GetAsColumn()); + builder.Select(nameof(@obj.NoteSend).GetAsColumn()); + builder.Select(nameof(@obj.NoteRecapitista).GetAsColumn()); + builder.Select(nameof(@obj.NoteConsolidatore).GetAsColumn()); + builder.Select(nameof(@obj.RispostaEnte).GetAsColumn()); + builder.Select(nameof(@obj.StatoContestazione).GetAsColumn()); + builder.Select(nameof(@obj.Onere).GetAsColumn()); + builder.Select(nameof(@obj.DataInserimentoEnte).GetAsColumn()); + builder.Select(nameof(@obj.DataModificaEnte).GetAsColumn()); + builder.Select(nameof(@obj.DataInserimentoSend).GetAsColumn()); + builder.Select(nameof(@obj.DataModificaSend).GetAsColumn()); + builder.Select(nameof(@obj.DataInserimentoRecapitista).GetAsColumn()); + builder.Select(nameof(@obj.DataModificaRecapitista).GetAsColumn()); + builder.Select(nameof(@obj.DataInserimentoConsolidatore).GetAsColumn()); + builder.Select(nameof(@obj.DataModificaConsolidatore).GetAsColumn()); + builder.Select(nameof(@obj.DataChiusura).GetAsColumn()); + builder.Select(nameof(@obj.Anno).GetAsColumn()); + builder.Select(nameof(@obj.Mese).GetAsColumn()); + return builder; + } + + private static string WhereByIdNotifica() + { + Contestazione? obj; + var fieldId = nameof(@obj.IdNotifica).GetColumn(); + return $"{fieldId} = @{nameof(@obj.IdNotifica)}"; + } + + + public static string SelectByIdNotifica() + { + var tableName = nameof(Contestazione); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereByIdNotifica(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/NotificaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/NotificaSQLBuilder.cs new file mode 100644 index 0000000..f517a6b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/Builder/NotificaSQLBuilder.cs @@ -0,0 +1,89 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; + +internal static class NotificaSQLBuilder +{ + private static string _sqlCount = @" +SELECT Count(n.internal_organization_id) +FROM pfd.[Notifiche] n +INNER JOIN pfd.Enti e ON e.InternalIstitutionId = n.internal_organization_id +INNER JOIN pfd.Contratti c ON e.InternalIstitutionId = c.internalistitutionid +LEFT JOIN pfw.Contestazioni t ON t.FkIdNotifica = n.event_id +INNER JOIN pfw.FlagContestazione f ON f.IdFlagContestazione = ISNULL(t.FkIdFlagContestazione, 1) +LEFT JOIN pfw.TipoContestazione a ON a.IdTipoContestazione = t.FkIdTipoContestazione +"; + private static string _sql = @" +SELECT [contract_id] AS IdContratto, + [tax_code] AS CodiceFiscale, + [vat_number] AS PIva, + [zip_code] AS CAP, + [foreign_state] AS StatoEstero, + [number_of_pages] AS NumberOfPages, + [g_envelope_weight] AS GEnvelopeWeight, + [cost_eurocent] AS CostEuroInCentesimi, + [timeline_category] AS TimelineCategory, + [notificationtype] AS TipoNotifica, + [event_id] AS IdNotifica, + [iun] AS Iun, + [notification_sent_at] AS DataInvio , + [internal_organization_id] AS IdEnte , + [event_timestamp] AS DATA , + [recipient_index] AS RecipientIndex, + [recipient_type] AS RecipientType, + [recipient_id] AS RecipientId, + n.[year] AS anno, + n.[month] AS mese, + n.[daily] AS AnnoMeseGiorno, + [item_code] AS ItemCode, + [notification_request_id] AS NotificationRequestId, + [recipient_tax_id] AS RecipientTaxId, + [Recapitista] AS Recapitista, + [Consolidatore] AS Consolidatore, + e.description AS RagioneSociale, + e.institutionType AS Profilo, + c.product AS Prodotto, + f.FlagContestazione AS Contestazione, + f.IdFlagContestazione AS StatoContestazione, + a.TipoContestazione AS TipoContestazione, + n.Fatturabile as Fatturata, + CAST( + CASE + WHEN n.[TipologiaFattura] = 'ASSEVERAZIONE' + THEN 'Notifica di ente aderente al bando PNRR in cui è prevista la fase di asseverazione' + ELSE n.[TipologiaFattura] + END AS nvarchar(300)) as TipologiaFattura, + t.onere AS Onere, + t.NoteEnte AS NoteEnte, + t.RispostaEnte AS RispostaEnte, + t.NoteSend AS NoteSend, + t.NoteRecapitista AS NoteRecapitista, + t.NoteConsolidatore AS NoteConsolidatore + +FROM pfd.[Notifiche] n +INNER JOIN pfd.Enti e ON e.InternalIstitutionId = n.internal_organization_id +INNER JOIN pfd.Contratti c ON e.InternalIstitutionId = c.internalistitutionid +LEFT JOIN pfw.Contestazioni t ON t.FkIdNotifica = n.event_id +INNER JOIN pfw.FlagContestazione f ON f.IdFlagContestazione = ISNULL(t.FkIdFlagContestazione, 1) +LEFT JOIN pfw.TipoContestazione a ON a.IdTipoContestazione = t.FkIdTipoContestazione +"; + + private static string _offSet = " OFFSET (@page-1)*@size ROWS FETCH NEXT @size ROWS ONLY"; + public static string OffSet() + { + return _offSet; + } + + public static string OrderBy() + { + return " ORDER BY n.year, n.month"; + } + + public static string SelectAll() + { + return _sql; + } + + public static string SelectAllCount() + { + return _sqlCount; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/ContestazioneQueryGetByIdNotificaPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/ContestazioneQueryGetByIdNotificaPersistence.cs new file mode 100644 index 0000000..98b243f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/ContestazioneQueryGetByIdNotificaPersistence.cs @@ -0,0 +1,26 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class ContestazioneQueryGetByIdNotificaPersistence(ContestazioneQueryGetByIdNotifica command) : DapperBase, IQuery +{ + private readonly ContestazioneQueryGetByIdNotifica _command = command; + private static readonly string _sql = ContestazioneSQLBuilder.SelectByIdNotifica(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + try + { + var contestazione = await ((IDatabase)this).SingleAsync( + connection!, _sql.Add(schema), _command, transaction); + return contestazione; + } + catch + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByConsolidatorePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByConsolidatorePersistence.cs new file mode 100644 index 0000000..2bfc3ca --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByConsolidatorePersistence.cs @@ -0,0 +1,125 @@ +using System.Data; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +public class NotificaQueryGetByConsolidatorePersistence(NotificaQueryGetByConsolidatore command) : DapperBase, IQuery +{ + private readonly NotificaQueryGetByConsolidatore _command = command; + private static readonly string _sqlSelectAll = NotificaSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllCount = NotificaSQLBuilder.SelectAllCount(); + private static readonly string _offSet = NotificaSQLBuilder.OffSet(); + private static readonly string _orderBy = NotificaSQLBuilder.OrderBy(); + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var notifiche = new NotificaRECCONDto(); + var where = string.Empty; + var page = _command.Page; + var size = _command.Size; + var anno = _command.AnnoValidita; + var mese = _command.MeseValidita; + + if (anno.HasValue) + where += " WHERE n.year=@anno"; + if (mese.HasValue) + where += " AND n.month=@mese"; + + where += $" AND Consolidatore = @consolidatore "; + + var consolidatore = _command.AuthenticationInfo.IdEnte; + + var prodotto = string.IsNullOrEmpty(_command.Prodotto) ? null : _command.Prodotto; + var cap = string.IsNullOrEmpty(_command.Cap) ? null : _command.Cap; + var profilo = string.IsNullOrEmpty(_command.Profilo) ? null : _command.Profilo; + var tipoNotifica = _command.TipoNotifica != null ? _command.TipoNotifica : null; + var contestazione = _command.StatoContestazione ?? null; + var iun = string.IsNullOrEmpty(_command.Iun) ? null : _command.Iun; + var recipientId = string.IsNullOrEmpty(_command.RecipientId) ? null : _command.RecipientId; + + if (!string.IsNullOrEmpty(iun)) + where += " AND iun=@iun"; + + if (!string.IsNullOrEmpty(recipientId)) + where += " AND recipient_id=@recipientId"; + + + if (!string.IsNullOrEmpty(prodotto)) + where += " AND c.product=@prodotto"; + if (!string.IsNullOrEmpty(cap)) + where += " AND zip_code=@cap"; + if (!string.IsNullOrEmpty(profilo)) + where += " AND e.institutionType=@profilo"; + var tnot = tipoNotifica.Map(); + if (tnot != null) + { + if (string.IsNullOrEmpty(tnot)) + where += " AND paper_product_type is NULL"; + else + where += " AND paper_product_type=@TipoNotifica"; + } + + if (!contestazione.IsNullOrEmpty() && Enumerable.SequenceEqual(contestazione!, [1])) + where += " and t.FKIdFlagContestazione is NULL"; + else if (!contestazione.IsNullOrEmpty() && contestazione!.Contains(1)) + where += " and (t.FKIdFlagContestazione is NULL OR t.FKIdFlagContestazione IN @contestazione)"; + else if (!contestazione.IsNullOrEmpty()) + where += " and t.FKIdFlagContestazione IN @contestazione"; + + var orderBy = _orderBy; + + var sqlEnte = _sqlSelectAll; + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + var sql = String.Join(";", sqlEnte, sqlCount); + + var query = new QueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese, + Consolidatore = consolidatore + }; + + if(!string.IsNullOrEmpty(prodotto)) + query.Prodotto = prodotto; + + if (!string.IsNullOrEmpty(cap)) + query.Cap = cap; + + if (!string.IsNullOrEmpty(profilo)) + query.Profilo = profilo; + + if (!string.IsNullOrEmpty(tnot)) + query.TipoNotifica = tnot; + + if (contestazione != null) + query.Contestazione = contestazione; + + if (!string.IsNullOrEmpty(iun)) + query.Iun = iun; + + if (!string.IsNullOrEmpty(recipientId)) + query.RecipientId = recipientId; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + notifiche.Notifiche = await values.ReadAsync(); + notifiche.Count = await values.ReadFirstAsync(); + return notifiche; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdEntePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdEntePersistence.cs new file mode 100644 index 0000000..ef27b06 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdEntePersistence.cs @@ -0,0 +1,122 @@ +using System.Data; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class NotificaQueryGetByIdEntePersistence(NotificaQueryGetByIdEnte command) : DapperBase, IQuery +{ + private readonly NotificaQueryGetByIdEnte _command = command; + private static readonly string _sqlSelectAll = NotificaSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllCount = NotificaSQLBuilder.SelectAllCount(); + private static readonly string _offSet = NotificaSQLBuilder.OffSet(); + private static readonly string _orderBy = NotificaSQLBuilder.OrderBy(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var notifiche = new NotificaDto(); + var where = string.Empty; + var idEnte = _command.AuthenticationInfo.IdEnte; + var page = _command.Page; + var size = _command.Size; + where += " WHERE internal_organization_id=@IdEnte "; + + + var anno = _command.AnnoValidita; + var mese = _command.MeseValidita; + var prodotto = string.IsNullOrEmpty(_command.Prodotto) ? null : _command.Prodotto; + var cap = string.IsNullOrEmpty(_command.Cap) ? null : _command.Cap; + var profilo = string.IsNullOrEmpty(_command.Profilo) ? null : _command.Profilo; + var tipoNotifica = _command.TipoNotifica != null ? _command.TipoNotifica : null; + var contestazione = _command.StatoContestazione??null; + var iun = string.IsNullOrEmpty(_command.Iun) ? null : _command.Iun; + var recipientId = string.IsNullOrEmpty(_command.RecipientId) ? null : _command.RecipientId; + + if (!string.IsNullOrEmpty(iun)) + where += " AND iun=@iun"; + + if (!string.IsNullOrEmpty(recipientId)) + where += " AND recipient_id=@recipientId"; + + if (anno.HasValue) + where += " AND n.year=@anno"; + if (mese.HasValue) + where += " AND n.month=@mese"; + if (!string.IsNullOrEmpty(prodotto)) + where += " AND c.product=@prodotto"; + if (!string.IsNullOrEmpty(cap)) + where += " AND zip_code=@cap"; + if (!string.IsNullOrEmpty(profilo)) + where += " AND e.institutionType=@profilo"; + var tnot = tipoNotifica.Map(); + if (tnot != null) + { + if (string.IsNullOrEmpty(tnot)) + where += " AND paper_product_type is NULL"; + else + where += " AND paper_product_type=@TipoNotifica"; + } + + if (!contestazione.IsNullOrEmpty() && Enumerable.SequenceEqual(contestazione!, [1])) + where += " and t.FKIdFlagContestazione is NULL"; + else if (!contestazione.IsNullOrEmpty() && contestazione!.Contains(1)) + where += " and (t.FKIdFlagContestazione is NULL OR t.FKIdFlagContestazione IN @contestazione)"; + else if (!contestazione.IsNullOrEmpty()) + where += " and t.FKIdFlagContestazione IN @contestazione"; + + var orderBy = _orderBy; + + var sqlEnte = _sqlSelectAll; + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + var sql = String.Join(";", sqlEnte, sqlCount); + + var query = new QueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese, + IdEnte = idEnte + }; + + if (!string.IsNullOrEmpty(prodotto)) + query.Prodotto = prodotto; + + if (!string.IsNullOrEmpty(cap)) + query.Cap = cap; + + if (!string.IsNullOrEmpty(profilo)) + query.Profilo = profilo; + + if (!string.IsNullOrEmpty(tnot)) + query.TipoNotifica = tnot; + + if (contestazione != null) + query.Contestazione = contestazione; + + if (!string.IsNullOrEmpty(iun)) + query.Iun = iun; + + if (!string.IsNullOrEmpty(recipientId)) + query.RecipientId = recipientId; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + notifiche.Notifiche = await values.ReadAsync(); + notifiche.Count = await values.ReadFirstAsync(); + return notifiche; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdPersistence.cs new file mode 100644 index 0000000..175c6e4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByIdPersistence.cs @@ -0,0 +1,28 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class NotificaQueryGetByIdPersistence(NotificaQueryGetById command) : DapperBase, IQuery +{ + private readonly NotificaQueryGetById _command = command; + private static readonly string _sqlAll = NotificaSQLBuilder.SelectAll(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var sql = _sqlAll + " WHERE event_id=@IdNotifica "; + try + { + var notifica = await ((IDatabase)this).SingleAsync( + connection!, sql.Add(schema), _command, transaction); + + return notifica; + } + catch + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByListEntiPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByListEntiPersistence.cs new file mode 100644 index 0000000..7752089 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByListEntiPersistence.cs @@ -0,0 +1,141 @@ +using System.Data; +using DocumentFormat.OpenXml.Drawing; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +public class NotificaQueryGetByListEntiPersistence(NotificaQueryGetByListaEnti command) : DapperBase, IQuery +{ + private readonly NotificaQueryGetByListaEnti _command = command; + private static readonly string _sqlSelectAll = NotificaSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllCount = NotificaSQLBuilder.SelectAllCount(); + private static readonly string _offSet = NotificaSQLBuilder.OffSet(); + private static readonly string _orderBy = NotificaSQLBuilder.OrderBy(); + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var notifiche = new NotificaDto(); + var where = string.Empty; + var page = _command.Page; + var size = _command.Size; + var anno = _command.AnnoValidita; + var mese = _command.MeseValidita; + + if (anno.HasValue) + where += " WHERE n.year=@anno"; + if (mese.HasValue) + where += " AND n.month=@mese"; + + if (!_command.EntiIds.IsNullOrEmpty()) + where += $" AND internal_organization_id IN @entiIds"; + + if (!_command.Recapitisti.IsNullOrEmpty()) + where += $" AND Recapitista IN @Recapitisti"; + + if (!_command.Consolidatori.IsNullOrEmpty()) + where += $" AND Consolidatore IN @Consolidatori"; + + var prodotto = string.IsNullOrEmpty(_command.Prodotto) ? null : _command.Prodotto; + var cap = string.IsNullOrEmpty(_command.Cap) ? null : _command.Cap; + var profilo = string.IsNullOrEmpty(_command.Profilo) ? null : _command.Profilo; + var tipoNotifica = _command.TipoNotifica != null ? _command.TipoNotifica : null; + var contestazione = _command.StatoContestazione ?? null; + var iun = string.IsNullOrEmpty(_command.Iun) ? null : _command.Iun; + var recipientId = string.IsNullOrEmpty(_command.RecipientId) ? null : _command.RecipientId; + + if (!string.IsNullOrEmpty(iun)) + where += " AND iun=@iun"; + + if (!string.IsNullOrEmpty(recipientId)) + where += " AND recipient_id=@recipientId"; + + if (!string.IsNullOrEmpty(prodotto)) + where += " AND c.product=@prodotto"; + if (!string.IsNullOrEmpty(cap)) + where += " AND zip_code=@cap"; + if (!string.IsNullOrEmpty(profilo)) + where += " AND e.institutionType=@profilo"; + var tnot = tipoNotifica.Map(); + if (tnot != null) + { + if (string.IsNullOrEmpty(tnot)) + where += " AND paper_product_type is NULL"; + else + where += " AND paper_product_type=@TipoNotifica"; + } + + if (!contestazione.IsNullOrEmpty() && Enumerable.SequenceEqual(contestazione!, [1])) + where += " and t.FKIdFlagContestazione is NULL"; + else if (!contestazione.IsNullOrEmpty() && contestazione!.Contains(1)) + where += " and (t.FKIdFlagContestazione is NULL OR t.FKIdFlagContestazione IN @contestazione)"; + else if (!contestazione.IsNullOrEmpty()) + where += " and t.FKIdFlagContestazione IN @contestazione"; + else if (contestazione.IsNullOrEmpty()) + contestazione = null; + + var orderBy = _orderBy; + + var sqlEnte = _sqlSelectAll; + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + + var sql = String.Join(";", sqlEnte, sqlCount); + var query = new QueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese + }; + + if(!string.IsNullOrEmpty(prodotto)) + query.Prodotto = prodotto; + + if (!string.IsNullOrEmpty(cap)) + query.Cap = cap; + + if (!string.IsNullOrEmpty(profilo)) + query.Profilo = profilo; + + if (!string.IsNullOrEmpty(tnot)) + query.TipoNotifica = tnot; + + if (contestazione != null) + query.Contestazione = contestazione; + + if (!string.IsNullOrEmpty(iun)) + query.Iun = iun; + + if (!_command.EntiIds.IsNullOrEmpty()) + query.EntiIds = _command.EntiIds; + + if (!_command.Recapitisti.IsNullOrEmpty()) + query.Recapitisti = _command.Recapitisti; + + if (!_command.Consolidatori.IsNullOrEmpty()) + query.Consolidatori = _command.Consolidatori; + + if (!string.IsNullOrEmpty(recipientId)) + query.RecipientId = recipientId; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + notifiche.Notifiche = await values.ReadAsync(); + notifiche.Count = await values.ReadFirstAsync(); + + return notifiche; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByRecapitistaPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByRecapitistaPersistence.cs new file mode 100644 index 0000000..954a839 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/Queries/Persistence/NotificaQueryGetByRecapitistaPersistence.cs @@ -0,0 +1,124 @@ +using System.Data; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; + +public class NotificaQueryGetByRecapitistaPersistence(NotificaQueryGetByRecapitista command) : DapperBase, IQuery +{ + private readonly NotificaQueryGetByRecapitista _command = command; + private static readonly string _sqlSelectAll = NotificaSQLBuilder.SelectAll(); + private static readonly string _sqlSelectAllCount = NotificaSQLBuilder.SelectAllCount(); + private static readonly string _offSet = NotificaSQLBuilder.OffSet(); + private static readonly string _orderBy = NotificaSQLBuilder.OrderBy(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var notifiche = new NotificaRECCONDto(); + var where = string.Empty; + var idRecapitista = _command.AuthenticationInfo.IdEnte; + var page = _command.Page; + var size = _command.Size; + var anno = _command.AnnoValidita; + var mese = _command.MeseValidita; + + if (anno.HasValue) + where += " WHERE n.year=@anno"; + if (mese.HasValue) + where += " AND n.month=@mese"; + + where += " AND Recapitista=@Recapitista"; + + + var prodotto = string.IsNullOrEmpty(_command.Prodotto) ? null : _command.Prodotto; + var cap = string.IsNullOrEmpty(_command.Cap) ? null : _command.Cap; + var profilo = string.IsNullOrEmpty(_command.Profilo) ? null : _command.Profilo; + var tipoNotifica = _command.TipoNotifica != null ? _command.TipoNotifica : null; + var contestazione = _command.StatoContestazione??null; + var iun = string.IsNullOrEmpty(_command.Iun) ? null : _command.Iun; + var recipientId = string.IsNullOrEmpty(_command.RecipientId) ? null : _command.RecipientId; + + if (!string.IsNullOrEmpty(iun)) + where += " AND iun=@iun"; + + if (!string.IsNullOrEmpty(recipientId)) + where += " AND recipient_id=@recipientId"; + + if (!string.IsNullOrEmpty(prodotto)) + where += " AND c.product=@prodotto"; + if (!string.IsNullOrEmpty(cap)) + where += " AND zip_code=@cap"; + if (!string.IsNullOrEmpty(profilo)) + where += " AND e.institutionType=@profilo"; + var tnot = tipoNotifica.Map(); + if (tnot != null) + { + if (string.IsNullOrEmpty(tnot)) + where += " AND paper_product_type is NULL"; + else + where += " AND paper_product_type=@TipoNotifica"; + } + + if (!contestazione.IsNullOrEmpty() && Enumerable.SequenceEqual(contestazione!, [1])) + where += " and t.FKIdFlagContestazione is NULL"; + else if (!contestazione.IsNullOrEmpty() && contestazione!.Contains(1)) + where += " and (t.FKIdFlagContestazione is NULL OR t.FKIdFlagContestazione IN @contestazione)"; + else if (!contestazione.IsNullOrEmpty()) + where += " and t.FKIdFlagContestazione IN @contestazione"; + + var orderBy = _orderBy; + + var sqlEnte = _sqlSelectAll; + var sqlCount = _sqlSelectAllCount; + if (page == null && size == null) + sqlEnte += where + orderBy; + else + sqlEnte += where + orderBy + _offSet; + + sqlCount += where; + var sql = String.Join(";", sqlEnte, sqlCount); + + var query = new QueryDto + { + Size = size, + Page = page, + Anno = anno, + Mese = mese, + Recapitista = idRecapitista + }; + + if (!string.IsNullOrEmpty(prodotto)) + query.Prodotto = prodotto; + + if (!string.IsNullOrEmpty(cap)) + query.Cap = cap; + + if (!string.IsNullOrEmpty(profilo)) + query.Profilo = profilo; + + if (!string.IsNullOrEmpty(tnot)) + query.TipoNotifica = tnot; + + if (contestazione != null) + query.Contestazione = contestazione; + + if (!string.IsNullOrEmpty(iun)) + query.Iun = iun; + + if (!string.IsNullOrEmpty(recipientId)) + query.RecipientId = recipientId; + + var values = await ((IDatabase)this).QueryMultipleAsync( + connection!, + sql, + query, + transaction); + + notifiche.Notifiche = await values.ReadAsync(); + notifiche.Count = await values.ReadFirstAsync(); + return notifiche; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/AzioneContestazioneQueryGetByIdNotificaHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/AzioneContestazioneQueryGetByIdNotificaHandler.cs new file mode 100644 index 0000000..f3082a3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/AzioneContestazioneQueryGetByIdNotificaHandler.cs @@ -0,0 +1,225 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Notifiche.Dto; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class AzioneContestazioneQueryGetByIdNotificaHandler( + ISelfCareDbContextFactory factory, + IFattureDbContextFactory fattureFactory, + IMediator handler, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly IFattureDbContextFactory _fattureFactory = fattureFactory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IMediator _handler = handler; + public async Task Handle(AzioneContestazioneQueryGetByIdNotifica request, CancellationToken ct) + { + using var nt = await _factory.Create(cancellationToken: ct); + var notifica = await nt.Query(new NotificaQueryGetByIdPersistence(new NotificaQueryGetById( + request.AuthenticationInfo, + request.IdNotifica + )), ct); + + if (notifica == null) + { + var msg = string.Format("Non esiste la notifica con codice: {0}", request.IdNotifica); + _logger.LogError(msg); + throw new DomainException(msg); + } + + using var cz = await _fattureFactory.Create(cancellationToken: ct); + var contestazione = await cz.Query(new ContestazioneQueryGetByIdNotificaPersistence(new ContestazioneQueryGetByIdNotifica( + request.AuthenticationInfo, + request.IdNotifica + )), ct); + + var annoNotifica = Convert.ToInt16(notifica.Anno); + var meseNotifica = Convert.ToInt16(notifica.Mese); + + var calendario = await _handler.Send(new CalendarioContestazioneQueryGet(request.AuthenticationInfo, annoNotifica, meseNotifica)); + + var authInfo = request.AuthenticationInfo; + bool? chiusuraPermessa = null; + bool? creazionePermessa = null; + bool? rispostaPermessa = null; + + if (authInfo.Profilo == Profilo.Recapitista + || authInfo.Profilo == Profilo.Consolidatore) + { + if ((notifica.Fatturata != null && notifica.Fatturata == true) || (notifica.TipologiaFattura != null)) + { + chiusuraPermessa = false; + creazionePermessa = false; // sempre false, già calcolata + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.NonContestata) + { + chiusuraPermessa = false; + creazionePermessa = true; // valuta dopo il calendario + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.Annullata + || notifica.StatoContestazione == (short)StatoContestazione.Accettata + || notifica.StatoContestazione == (short)StatoContestazione.Chiusa) + { + chiusuraPermessa = false; + creazionePermessa = false; + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.ContestataEnte) + { + chiusuraPermessa = false; + creazionePermessa = false; + rispostaPermessa = true; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || notifica.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || notifica.StatoContestazione == (short)StatoContestazione.RispostaSend + || notifica.StatoContestazione == (short)StatoContestazione.RispostaEnte) + { + chiusuraPermessa = false; + creazionePermessa = false; + rispostaPermessa = true; + } + else + { + var msg = string.Format("Non esiste stato valido associato a notifica con codice: {0}", request.IdNotifica); + _logger.LogError(msg); + throw new DomainException(msg); + } + return new AzioneNotificaDto() + { + ChiusuraPermessa = false, + CreazionePermessa = false, + RispostaPermessa = rispostaPermessa!.Value && calendario.ValidVerifica && authInfo.Ruolo == Ruolo.ADMIN, + Contestazione = contestazione, + Calendario = calendario, + Notifica = notifica + }; + } + else if ( + authInfo.Profilo == Profilo.PubblicaAmministrazione + || authInfo.Profilo == Profilo.GestorePubblicoServizio + || authInfo.Profilo == Profilo.SocietaControlloPubblico + || authInfo.Profilo == Profilo.PrestatoreServiziPagamento + || authInfo.Profilo == Profilo.AssicurazioniIVASS + || authInfo.Profilo == Profilo.StazioneAppaltanteANAC + || authInfo.Profilo == Profilo.PartnerTecnologico) + { + if ((notifica.Fatturata != null && notifica.Fatturata == true) || (notifica.TipologiaFattura != null)) + { + chiusuraPermessa = false; + creazionePermessa = false; // sempre false, già calcolata + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.NonContestata) + { + chiusuraPermessa = false; + creazionePermessa = true; // valuta dopo il calendario + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.Annullata + || notifica.StatoContestazione == (short)StatoContestazione.Accettata + || notifica.StatoContestazione == (short)StatoContestazione.Chiusa) + { + chiusuraPermessa = false; + creazionePermessa = false; + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.ContestataEnte) + { + chiusuraPermessa = true; + creazionePermessa = true; // modifica di nota contestataEnte + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || notifica.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || notifica.StatoContestazione == (short)StatoContestazione.RispostaSend + || notifica.StatoContestazione == (short)StatoContestazione.RispostaEnte) + { + chiusuraPermessa = true; + creazionePermessa = false; + rispostaPermessa = true; + } + else + { + var msg = string.Format("Non esiste stato valido associato a notifica con codice: {0}", request.IdNotifica); + _logger.LogError(msg); + throw new DomainException(msg); + } + return new AzioneNotificaDto() + { + ChiusuraPermessa = chiusuraPermessa!.Value && calendario.ValidVerifica && authInfo.Ruolo == Ruolo.ADMIN, + CreazionePermessa = creazionePermessa!.Value && calendario.Valid && authInfo.Ruolo == Ruolo.ADMIN, + RispostaPermessa = rispostaPermessa!.Value && calendario.ValidVerifica && authInfo.Ruolo == Ruolo.ADMIN, + Contestazione = contestazione, + Calendario = calendario, + Notifica = notifica + }; + } + else if (authInfo.Profilo == Profilo.Approvigionamento + || authInfo.Profilo == Profilo.Finanza + || authInfo.Profilo == Profilo.Assistenza) + { + if ((notifica.Fatturata != null && notifica.Fatturata == true) || (notifica.TipologiaFattura != null)) + { + chiusuraPermessa = false; + creazionePermessa = false; // sempre false, già calcolata + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.NonContestata + || notifica.StatoContestazione == (short)StatoContestazione.Annullata + || notifica.StatoContestazione == (short)StatoContestazione.Accettata + || notifica.StatoContestazione == (short)StatoContestazione.Chiusa) + { + chiusuraPermessa = false; + creazionePermessa = false; + rispostaPermessa = false; + } + else if (notifica.StatoContestazione == (short)StatoContestazione.ContestataEnte + || notifica.StatoContestazione == (short)StatoContestazione.RispostaRecapitista + || notifica.StatoContestazione == (short)StatoContestazione.RispostaConsolidatore + || notifica.StatoContestazione == (short)StatoContestazione.RispostaSend + || notifica.StatoContestazione == (short)StatoContestazione.RispostaEnte) + { + chiusuraPermessa = true; + creazionePermessa = false; + rispostaPermessa = true; + } + else + { + var msg = string.Format("Non esiste stato valido associato a notifica con codice: {0}", request.IdNotifica); + _logger.LogError(msg); + throw new DomainException(msg); + } + return new AzioneNotificaDto() + { + ChiusuraPermessa = chiusuraPermessa!.Value && calendario.ValidVerifica && request.AuthenticationInfo.Ruolo == Ruolo.ADMIN, + CreazionePermessa = creazionePermessa!.Value && calendario.ValidVerifica && request.AuthenticationInfo.Ruolo == Ruolo.ADMIN, + RispostaPermessa = rispostaPermessa!.Value && calendario.ValidVerifica && request.AuthenticationInfo.Ruolo == Ruolo.ADMIN, + Contestazione = contestazione, + Calendario = calendario, + Notifica = notifica + }; + } + else + { + var msg = string.Format("Non esiste il profilo associato alle notifiche: {0}", authInfo.Profilo); + _logger.LogError(msg); + throw new DomainException(msg); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/ContestazioneQueryGetByIdNotificaHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/ContestazioneQueryGetByIdNotificaHandler.cs new file mode 100644 index 0000000..3b77451 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/ContestazioneQueryGetByIdNotificaHandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class ContestazioneQueryGetByIdNotificaHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(ContestazioneQueryGetByIdNotifica request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new ContestazioneQueryGetByIdNotificaPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByConsolidatoreHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByConsolidatoreHandler.cs new file mode 100644 index 0000000..f492fc2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByConsolidatoreHandler.cs @@ -0,0 +1,42 @@ +using System.Reflection.Metadata; +using System.Runtime.InteropServices; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class NotificaQueryGetByConsolidatoreHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + IMediator handler, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IMediator _handler = handler; + public async Task Handle(NotificaQueryGetByConsolidatore request, CancellationToken ct) + { + var annoNotifica = request.AnnoValidita!.Value; + var meseNotifica = request.MeseValidita!.Value; + + var calendario = await _handler.Send(new CalendarioContestazioneQueryGet(request.AuthenticationInfo, annoNotifica, meseNotifica)); + + if (!calendario.ValidVisualizzazione) + return new NotificaRECCONDto() + { + Count = 0, + Notifiche = [] + }; + + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new NotificaQueryGetByConsolidatorePersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdEnteHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdEnteHandler.cs new file mode 100644 index 0000000..9e11de1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdEnteHandler.cs @@ -0,0 +1,41 @@ +using System.Reflection.Metadata; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class NotificaQueryGetByIdEnteHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + IMediator handler, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IMediator _handler = handler; + public async Task Handle(NotificaQueryGetByIdEnte request, CancellationToken ct) + { + var annoNotifica = request.AnnoValidita!.Value; + var meseNotifica = request.MeseValidita!.Value; + + var calendario = await _handler.Send(new CalendarioContestazioneQueryGet(request.AuthenticationInfo, annoNotifica, meseNotifica)); + + if (!calendario.ValidVisualizzazione) + return new NotificaDto() + { + Count = 0, + Notifiche = [] + }; + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new NotificaQueryGetByIdEntePersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdHandlandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdHandlandler.cs new file mode 100644 index 0000000..ed6a678 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByIdHandlandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class NotificaQueryGetByIdHandlandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(NotificaQueryGetById request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new NotificaQueryGetByIdPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByListEntiHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByListEntiHandler.cs new file mode 100644 index 0000000..aa63efd --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByListEntiHandler.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class NotificaQueryGetByListEntiHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(NotificaQueryGetByListaEnti request, CancellationToken ct) + { + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new NotificaQueryGetByListEntiPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByRecapitistaHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByRecapitistaHandler.cs new file mode 100644 index 0000000..2602796 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Notifiche/QueryHandlers/NotificaQueryGetByRecapitistaHandler.cs @@ -0,0 +1,39 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Notifiche.QueryHandlers; + +public class NotificaQueryGetByRecapitistaHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + IMediator handler, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + private readonly IMediator _handler = handler; + public async Task Handle(NotificaQueryGetByRecapitista request, CancellationToken ct) + { + var annoNotifica = request.AnnoValidita!.Value; + var meseNotifica = request.MeseValidita!.Value; + + var calendario = await _handler.Send(new CalendarioContestazioneQueryGet(request.AuthenticationInfo, annoNotifica, meseNotifica)); + + if (!calendario.ValidVisualizzazione) + return new NotificaRECCONDto() + { + Count = 0, + Notifiche = [] + }; + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new NotificaQueryGetByRecapitistaPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DapperBase.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DapperBase.cs new file mode 100644 index 0000000..ef10e37 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DapperBase.cs @@ -0,0 +1,76 @@ +using System.Data; +using Dapper; +using static Dapper.SqlMapper; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public abstract class DapperBase : IDatabase +{ + private async Task Execute(Task task, IDbConnection connection, IDbTransaction? transaction) + { + if (transaction is null) + using (connection) + return (await task); + else + return (await task); + } + + public async Task ExecuteAsync( + IDbConnection connection, + string sqlCommand, + object? parameters, + IDbTransaction? transaction, + CommandType type, + int? commandTimeout = null) + { + var task = connection.ExecuteAsync(sqlCommand, parameters, transaction, commandTimeout, type); + return await Execute(task, connection, transaction); + } + + public async Task ExecuteAsync( + IDbConnection connection, + string sqlCommand, + object? parameters, + IDbTransaction? transaction, + CommandType type, + int? commandTimeout = null) + { + var task = connection.QueryFirstAsync(sqlCommand, parameters, transaction, commandTimeout, type); + return await Execute(task, connection, transaction); + } + + public async Task> SelectAsync( + IDbConnection connection, + string sqlQuery, + object? parameters, + IDbTransaction? transaction, + CommandType type, + int? commandTimeout = null) + { + var task = connection.QueryAsync(sqlQuery, parameters, transaction, commandTimeout, type); + return await Execute(task, connection, transaction); + } + + public async Task QueryMultipleAsync( + IDbConnection connection, + string sqlQuery, + object? parameters, + IDbTransaction? transaction, + CommandType type, + int? commandTimeout = null) + { + return await connection.QueryMultipleAsync(sqlQuery, parameters, transaction, commandTimeout, type); + } + + public async Task SingleAsync( + IDbConnection connection, + string sqlQuery, + object? parameters, + IDbTransaction? transaction, + CommandType type, + int? commandTimeout = null) + { + var task = connection.QuerySingleAsync(sqlQuery, parameters, transaction, commandTimeout, type); + return await Execute(task, connection, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContext.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContext.cs new file mode 100644 index 0000000..13fec2b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContext.cs @@ -0,0 +1,81 @@ +using System.Data; +using PortaleFatture.BE.Core.Exceptions; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public class DbContext : IDbContext +{ + private bool _disposed; + private IDbConnection? _connection; + private IDbTransaction? _transaction; + private string _schema; + public DbContext(IDbConnection connection, + string schema, + bool transactional = false, + IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) + { + if (string.IsNullOrEmpty(schema) || schema!.Length > 4) + throw new ConfigurationException("Database invalid schema!"); + + _schema = schema.EndsWith(".") ? schema : $"{schema}."; + _connection = connection; + if (_connection.State == ConnectionState.Closed) + _connection.Open(); + if (transactional) + _transaction = _connection.BeginTransaction(isolationLevel); + } + + public string GetSchema() => _schema; + + public Task Query(IQuery query, CancellationToken ct = default) + => query.Execute(_connection, _schema, _transaction, ct); + + + public Task Execute(ICommand command, CancellationToken ct = default) + { + if (command.RequiresTransaction && _transaction == null) + throw new Exception($"The command {command.GetType()} requires a transaction"); + + return command.Execute(_connection, _schema, _transaction, ct); + } + + public Task Execute(ICommand command, CancellationToken ct = default) + { + if (command.RequiresTransaction && _transaction == null) + throw new Exception($"The command {command.GetType()} requires a transaction"); + + return command.Execute(_connection, _schema, _transaction, ct); + } + + public void Commit() + => _transaction?.Commit(); + + public void Rollback() + => _transaction?.Rollback(); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~DbContext() + => Dispose(false); + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + _transaction?.Dispose(); + _connection?.Dispose(); + } + + _transaction = null; + _connection = null; + + _disposed = true; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContextFactory.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContextFactory.cs new file mode 100644 index 0000000..48352c7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/DbContextFactory.cs @@ -0,0 +1,25 @@ +using System.Data; +using Microsoft.Data.SqlClient; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public class DbContextFactory : IDbContextFactory, IFattureDbContextFactory, ISelfCareDbContextFactory +{ + private readonly string _schema; + private readonly string _connectionString; + public DbContextFactory(string connectionString, string schema) + { + _connectionString = connectionString; + _schema = schema; + } + public async Task Create( + bool transactional = false, + IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, + CancellationToken ct = default) + { + var conn = new SqlConnection(_connectionString); + await conn.OpenAsync(ct); + return new DbContext(conn, _schema, transactional, isolationLevel); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/ICommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/ICommand.cs new file mode 100644 index 0000000..0196637 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/ICommand.cs @@ -0,0 +1,14 @@ +using System.Data; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public interface ICommand +{ + bool RequiresTransaction { get; } + Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default); +} +public interface ICommand +{ + bool RequiresTransaction { get; } + Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDatabase.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDatabase.cs new file mode 100644 index 0000000..3a048b7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDatabase.cs @@ -0,0 +1,13 @@ +using System.Data; +using static Dapper.SqlMapper; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public interface IDatabase +{ + Task QueryMultipleAsync(IDbConnection connection, string sqlCommand, object? parameters, IDbTransaction? transaction = null, CommandType type = CommandType.Text, int? commandTimeout = null); + Task ExecuteAsync(IDbConnection connection, string sqlCommand, object? parameters, IDbTransaction? transaction = null, CommandType type = CommandType.Text, int? commandTimeout = null); + Task ExecuteAsync(IDbConnection connection, string sqlCommand, object? parameters, IDbTransaction? transaction = null, CommandType type = CommandType.Text, int? commandTimeout = null); + Task> SelectAsync(IDbConnection connection, string sqlCommand, object? parameters, IDbTransaction? transaction = null, CommandType type = CommandType.Text, int? commandTimeout = null); + Task SingleAsync(IDbConnection connection, string sqlCommand, object? parameters, IDbTransaction? transaction = null, CommandType type = CommandType.Text, int? commandTimeout = null); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContext.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContext.cs new file mode 100644 index 0000000..616661c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContext.cs @@ -0,0 +1,13 @@ +using System.Windows.Input; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public interface IDbContext : IDisposable +{ + public string GetSchema(); + Task Query(IQuery query, CancellationToken ct = default); + Task Execute(ICommand command, CancellationToken ct = default); + Task Execute(ICommand command, CancellationToken ct = default); + void Commit(); + void Rollback(); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContextFactory.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContextFactory.cs new file mode 100644 index 0000000..de8fec1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IDbContextFactory.cs @@ -0,0 +1,8 @@ +using System.Data; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public interface IDbContextFactory +{ + Task Create(bool transactional = false, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IQuery.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IQuery.cs new file mode 100644 index 0000000..16f86d3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/IQuery.cs @@ -0,0 +1,6 @@ +using System.Data; +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; +public interface IQuery +{ + Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/IFattureDbContextFactory.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/IFattureDbContextFactory.cs new file mode 100644 index 0000000..28177f9 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/IFattureDbContextFactory.cs @@ -0,0 +1,5 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +public interface IFattureDbContextFactory: IDbContextFactory +{ +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/ISelfCareDbContextFactory.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/ISelfCareDbContextFactory.cs new file mode 100644 index 0000000..92635a5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/Schemas/ISelfCareDbContextFactory.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; + +public interface ISelfCareDbContextFactory : IDbContextFactory +{ + +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/SqlExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/SqlExtensions.cs new file mode 100644 index 0000000..e5afefe --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Persistence/SqlExtensions.cs @@ -0,0 +1,49 @@ +using PortaleFatture.BE.Core.Exceptions; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; + +namespace PortaleFatture.BE.Infrastructure.Common.Persistence; + +public static class SqlExtensions +{ + public static string AddJoin(this string sql, string schema) + { + return sql.Replace("[schema_inner]", schema); + } + + public static string Add(this string sql, string schema) + { + return sql.Replace("[schema]", schema); + } + + public static string AddTop(this string sql, int? top) + { + if (top == null) + return sql; + else + return sql.Replace("/*top*/", $" top {top}"); + } + + public static string GetColumn(this string propertyName) + { + var propertyInfo = typeof(T)!.GetProperty(propertyName)!; + var customAttribute = (ColumnAttribute)Attribute.GetCustomAttribute(propertyInfo, typeof(ColumnAttribute))!; + if (customAttribute != null) + return $"{customAttribute.Name!}"; + throw new ConfigurationException($"Error mapping column {propertyName}"); + } + + public static string GetAsColumn(this string propertyName) + { + var fieldName = GetColumn(propertyName); + return $"{fieldName} as {propertyName}"; + } + + public static string GetTable(this string className) + { + var customAttribute = typeof(T)!.GetCustomAttribute(); + if (customAttribute != null) + return $"{customAttribute.Name!}"; + throw new ConfigurationException($"Error mapping table {className}"); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/IScadenziarioService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/IScadenziarioService.cs new file mode 100644 index 0000000..4b3eb0f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/IScadenziarioService.cs @@ -0,0 +1,9 @@ +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Scadenziari; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari; + +public interface IScadenziarioService +{ + Task<(bool, Scadenziario)> GetScadenziario(IAuthenticationInfo authenticationInfo, TipoScadenziario tipo, int anno, int mese); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGet.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGet.cs new file mode 100644 index 0000000..1d094c1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGet.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Scadenziari; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +public class CalendarioContestazioneQueryGet(IAuthenticationInfo authenticationInfo, int anno, int mese) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public int Anno { get; internal set; } = anno; + public int Mese { get; internal set; } = mese; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGetAll.cs new file mode 100644 index 0000000..0194b77 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/CalendarioContestazioneQueryGetAll.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Scadenziari; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +public class CalendarioContestazioneQueryGetAll(IAuthenticationInfo authenticationInfo) : IRequest> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/Builder/CalendarioContestazioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/Builder/CalendarioContestazioneSQLBuilder.cs new file mode 100644 index 0000000..437eff5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/Builder/CalendarioContestazioneSQLBuilder.cs @@ -0,0 +1,55 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence.Builder; + +internal static class CalendarioContestazioneSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + CalendarioContestazione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.AnnoContestazione).GetAsColumn()); + builder.Select(nameof(@obj.MeseContestazione).GetAsColumn()); + builder.Select(nameof(@obj.DataInizio).GetAsColumn()); + builder.Select(nameof(@obj.DataFine).GetAsColumn()); + builder.Select(nameof(@obj.DataVerifica).GetAsColumn()); + return builder; + } + + private static string WhereByAnnoMese() + { + CalendarioContestazione? obj; + var fieldAnno = nameof(@obj.AnnoContestazione).GetColumn(); + var fieldMese = nameof(@obj.MeseContestazione).GetColumn(); + return $"{fieldAnno} = @{nameof(@obj.AnnoContestazione)} AND {fieldMese} = @{nameof(@obj.MeseContestazione)}"; + } + + + public static string SelectByAnnoMese() + { + var tableName = nameof(CalendarioContestazione); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereByAnnoMese(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectAll() + { + var tableName = nameof(CalendarioContestazione); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } + public static string OrderBy() + { + CalendarioContestazione? @obj = null; + return $" ORDER BY {nameof(@obj.AnnoContestazione).GetColumn()} DESC, {nameof(@obj.MeseContestazione).GetColumn()}"; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetAllPersistence.cs new file mode 100644 index 0000000..a332129 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetAllPersistence.cs @@ -0,0 +1,18 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence; + +public class CalendarioContestazioneQueryGetAllPersistence(CalendarioContestazioneQueryGetAll command) : DapperBase, IQuery?> +{ + private readonly CalendarioContestazioneQueryGetAll _command = command; + private static readonly string _sql = CalendarioContestazioneSQLBuilder.SelectAll(); + private static readonly string _orderBy = CalendarioContestazioneSQLBuilder.OrderBy(); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var sql = _sql + _orderBy; + return await ((IDatabase)this).SelectAsync(connection!, sql.Add(schema), transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetPersistence.cs new file mode 100644 index 0000000..2811fd4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/Persistence/CalendarioContestazioneQueryGetPersistence.cs @@ -0,0 +1,28 @@ +using System.Data; +using DocumentFormat.OpenXml.InkML; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence; + +public class CalendarioContestazioneQueryGetPersistence(CalendarioContestazioneQueryGet command) : DapperBase, IQuery +{ + private readonly CalendarioContestazioneQueryGet _command = command; + private static readonly string _sql = CalendarioContestazioneSQLBuilder.SelectByAnnoMese(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + try + { + return await ((IDatabase)this).SingleAsync(connection!, _sql.Add(schema), new + { + AnnoContestazione = _command.Anno, + MeseContestazione = _command.Mese + }, transaction); + } + catch + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/ScadenziarioQueryGetByTipo.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/ScadenziarioQueryGetByTipo.cs new file mode 100644 index 0000000..a25a821 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/Queries/ScadenziarioQueryGetByTipo.cs @@ -0,0 +1,13 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Scadenziari; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +public class ScadenziarioQueryGetByTipo(IAuthenticationInfo authenticationInfo, TipoScadenziario tipo, int anno, int mese) : IRequest<(bool, Scadenziario)> +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public TipoScadenziario Tipo { get; internal set; } = tipo; + public int Anno { get; internal set; } = anno; + public int Mese { get; internal set; } = mese; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneAllQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneAllQueryHandler.cs new file mode 100644 index 0000000..e956f19 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneAllQueryHandler.cs @@ -0,0 +1,27 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.QueryHandlers; + +public class CalendarioContestazioneAllQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler?> +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task?> Handle(CalendarioContestazioneQueryGetAll request, CancellationToken ct) + { + + using var rs = await _factory.Create(cancellationToken: ct); + return await rs.Query(new CalendarioContestazioneQueryGetAllPersistence(request), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneQueryHandler.cs new file mode 100644 index 0000000..9100ff0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/CalendarioContestazioneQueryHandler.cs @@ -0,0 +1,55 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.QueryHandlers; + +public class CalendarioContestazioneQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + public async Task Handle(CalendarioContestazioneQueryGet request, CancellationToken ct) + { + + using var rs = await _factory.Create(cancellationToken: ct); + var calendario = await rs.Query(new CalendarioContestazioneQueryGetPersistence(request), ct); + var (annoAttuale, meseAttuale, giornoAttuale, adesso) = Time.YearMonthDay(); + if (calendario == null) + return new CalendarioContestazione() + { + Adesso = adesso, + AnnoContestazione = request.Anno, + MeseContestazione = request.Mese, + Valid = false, + ValidVerifica = false + }; + + var tValid = adesso >= calendario!.DataInizio && adesso <= calendario!.DataFine; + var tVerifica= adesso >= calendario!.DataInizio && adesso <= calendario!.DataVerifica; + var tVisualizzazione = adesso >= calendario!.DataInizio; + + CalendarioContestazione calendarioContestazione = new() + { + Valid = tValid, + ValidVerifica = tVerifica, + DataInizio = calendario.DataInizio, + DataFine = calendario.DataFine, + DataVerifica = calendario.DataVerifica, + AnnoContestazione = calendario.AnnoContestazione, + MeseContestazione = calendario.MeseContestazione, + Adesso = adesso, + ValidVisualizzazione = tVisualizzazione + }; + return calendarioContestazione; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/ScadenziarioQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/ScadenziarioQueryHandler.cs new file mode 100644 index 0000000..1ee2b83 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/QueryHandlers/ScadenziarioQueryHandler.cs @@ -0,0 +1,62 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari.QueryHandlers; + +public class ScadenziarioQueryHandler( + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task<(bool, Scadenziario)> Handle(ScadenziarioQueryGetByTipo request, CancellationToken cancellationToken) + { + var authInfo = request.AuthenticationInfo; + var tipo = request.Tipo; + var meseVerifica = request.Mese; + var annoVerifica = request.Anno; + + Scadenziario scadenziario; + if (tipo == TipoScadenziario.DatiModuloCommessa) + scadenziario = await Task.Run(() => new Scadenziario() + { + GiornoFine = 19, + GiornoInizio = 1 + }); + else if (tipo == TipoScadenziario.DatiFatturazione) + scadenziario = await Task.Run(() => new Scadenziario() + { + GiornoFine = 31, + GiornoInizio = 1 + }); + else + throw new ConfigurationException("Time table not configured for the specific data."); + + if (authInfo.Ruolo != Ruolo.ADMIN) + return (false, scadenziario); + + if (tipo == TipoScadenziario.DatiModuloCommessa) + { + var (annoFatturazione, meseFatturazione, giornoAttuale, adesso) = Time.YearMonthDayFatturazione(); + scadenziario.Mese = meseFatturazione; + scadenziario.Anno = annoFatturazione; + scadenziario.Adesso = adesso; + if (meseFatturazione != meseVerifica || annoFatturazione != annoVerifica) // deve essere il mese corrente fatturazione + 1 + return (false, scadenziario); + + if (giornoAttuale >= scadenziario.GiornoInizio && giornoAttuale <= scadenziario.GiornoFine) + return (true, scadenziario); + else + return (false, scadenziario); + } + return (false, scadenziario); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/ScadenziarioService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/ScadenziarioService.cs new file mode 100644 index 0000000..7dc6087 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Scadenziari/ScadenziarioService.cs @@ -0,0 +1,18 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; + +namespace PortaleFatture.BE.Infrastructure.Common.Scadenziari; + +public class ScadenziarioService(IMediator handler, ILogger logger) : IScadenziarioService +{ + private readonly IMediator _handler = handler; + private readonly ILogger _logger = logger; + + public async Task<(bool, Scadenziario)> GetScadenziario(IAuthenticationInfo authenticationInfo, TipoScadenziario tipo, int anno, int mese) + { + return await _handler.Send(new ScadenziarioQueryGetByTipo(authenticationInfo, tipo, anno, mese)); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/ContrattoQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/ContrattoQueryGetById.cs new file mode 100644 index 0000000..338badc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/ContrattoQueryGetById.cs @@ -0,0 +1,14 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.SelfCare; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; + +public class ContrattoQueryGetById : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } + public ContrattoQueryGetById(IAuthenticationInfo? authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/EnteQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/EnteQueryGetById.cs new file mode 100644 index 0000000..50e89a7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/EnteQueryGetById.cs @@ -0,0 +1,14 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.SelfCare; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; + +public class EnteQueryGetById : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } + public EnteQueryGetById(IAuthenticationInfo? authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/ContrattoSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/ContrattoSQLBuilder.cs new file mode 100644 index 0000000..b3bfe9d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/ContrattoSQLBuilder.cs @@ -0,0 +1,38 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence.Builder; + +public class ContrattoSQLBuilder +{ + private static string WhereById() + { + Contratto? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldProdotto = nameof(@obj.Prodotto).GetColumn(); + return $"{fieldIdEnte} = @{nameof(@obj.IdEnte)} AND {fieldProdotto} = @{nameof(@obj.Prodotto)}"; + } + + private static SqlBuilder CreateSelect() + { + Contratto? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Prodotto).GetAsColumn()); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.IdTipoContratto).GetAsColumn()); + return builder; + } + + public static string SelectBy() + { + var tableName = nameof(Contratto); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/EnteSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/EnteSQLBuilder.cs new file mode 100644 index 0000000..c3170a3 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/Builder/EnteSQLBuilder.cs @@ -0,0 +1,44 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence.Builder; + +public class EnteSQLBuilder +{ + private static string WhereById() + { + Ente? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + return $"{fieldIdEnte} = @{nameof(@obj.IdEnte)}"; + } + + private static SqlBuilder CreateSelect() + { + Ente? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.Profilo).GetAsColumn()); + builder.Select(nameof(@obj.Descrizione).GetAsColumn()); + builder.Select(nameof(@obj.Email).GetAsColumn()); + builder.Select(nameof(@obj.Address).GetAsColumn()); + builder.Select(nameof(@obj.Cap).GetAsColumn()); + builder.Select(nameof(@obj.CodiceIstat).GetAsColumn()); + builder.Select(nameof(@obj.Citta).GetAsColumn()); + builder.Select(nameof(@obj.Provincia).GetAsColumn()); + builder.Select(nameof(@obj.Nazione).GetAsColumn()); + builder.Select(nameof(@obj.PartitaIva).GetAsColumn()); + return builder; + } + + public static string SelectBy() + { + var tableName = nameof(Ente); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/ContrattoQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/ContrattoQueryGetByIdPersistence.cs new file mode 100644 index 0000000..ec01cdc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/ContrattoQueryGetByIdPersistence.cs @@ -0,0 +1,22 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence; + +public class ContrattoQueryGetByIdPersistence(string idEnte, string? prodotto) : DapperBase, IQuery +{ + private readonly string? _idEnte = idEnte; + private readonly string? _prodotto = prodotto; + private static readonly string _sqlSelect = ContrattoSQLBuilder.SelectBy(); + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var results = await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), + new { IdEnte = _idEnte, + Prodotto = _prodotto}, transaction); + return results?.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/EnteQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/EnteQueryGetByIdPersistence.cs new file mode 100644 index 0000000..d47d8dc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/Queries/Persistence/EnteQueryGetByIdPersistence.cs @@ -0,0 +1,22 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence; + +public class EnteQueryGetByIdPersistence : DapperBase, IQuery +{ + private readonly string? _idEnte; + private static readonly string _sqlSelect = EnteSQLBuilder.SelectBy(); + + public EnteQueryGetByIdPersistence(string idEnte) + { + this._idEnte = idEnte; + } + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var results = await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), new { IdEnte = _idEnte }, transaction); + return results?.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/ContrattoQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/ContrattoQueryHandler.cs new file mode 100644 index 0000000..2fc2931 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/ContrattoQueryHandler.cs @@ -0,0 +1,28 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.QueryHandlers; + +public class ContrattoQueryHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task Handle(ContrattoQueryGetById request, CancellationToken ct) + { + var idEnte = request.AuthenticationInfo!.IdEnte; + var prodotto = request.AuthenticationInfo.Prodotto; + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new ContrattoQueryGetByIdPersistence(idEnte!, prodotto!), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/EnteQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/EnteQueryHandler.cs new file mode 100644 index 0000000..f3794b0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SelfCare/QueryHandlers/EnteQueryHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.SelfCare.QueryHandlers; + +public class EnteQueryHandler : IRequestHandler +{ + private readonly ISelfCareDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public EnteQueryHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + public async Task Handle(EnteQueryGetById request, CancellationToken ct) + { + var idEnte = request.AuthenticationInfo!.IdEnte; + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new EnteQueryGetByIdPersistence(idEnte!), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/Persistence/StoricoCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/Persistence/StoricoCreateCommandPersistence.cs new file mode 100644 index 0000000..5fc6ed6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/Persistence/StoricoCreateCommandPersistence.cs @@ -0,0 +1,39 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence; + +public class StoricoCreateCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly StoricoCreateCommand _command; + public StoricoCreateCommandPersistence(StoricoCreateCommand command) + => _command = command; + + private static readonly string _sqlInsert = @" +INSERT INTO [schema][Log] + ([FkIdEnte] + ,[IdUtente] + ,[DataEvento] + ,[DescrizioneEvento] + ,[JsonTransazione]) + VALUES + (@IdEnte, + @IdUtente, + @DataEvento, + @DescrizioneEvento, + @JsonTransazione) +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert.Add(schema), new + { + idEnte = _command.AuthenticationInfo.IdEnte, + idUtente = _command.AuthenticationInfo.Id, + dataEvento = _command.DataEvento, + descrizioneEvento = _command.DescrizioneEvento, + jsonTransazione = _command.JsonTransazione + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/StoricoCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/StoricoCreateCommand.cs new file mode 100644 index 0000000..1706b6f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Storici/Commands/StoricoCreateCommand.cs @@ -0,0 +1,15 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Storici.Commands; + +public class StoricoCreateCommand(IAuthenticationInfo authenticationInfo, + DateTime DataEvento, + string? DescrizioneEvento, + string? JsonTransazione) : IRequest +{ + public IAuthenticationInfo AuthenticationInfo { get; internal set; } = authenticationInfo; + public DateTime DataEvento { get; internal set; } = DataEvento; + public string? DescrizioneEvento { get; internal set; } = DescrizioneEvento; + public string? JsonTransazione { get; internal set; } = JsonTransazione; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByDescrizione.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByDescrizione.cs new file mode 100644 index 0000000..e9b4cd4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByDescrizione.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.SelfCare; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public sealed class EnteQueryGetByDescrizione(AuthenticationInfo? authenticationInfo, string? descrizione) : IRequest> +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? Descrizione { get; internal set; } = descrizione; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRagioneSociale.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRagioneSociale.cs new file mode 100644 index 0000000..a0ee4e7 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRagioneSociale.cs @@ -0,0 +1,12 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public sealed class EnteQueryGetByRagioneSociale(AuthenticationInfo? authenticationInfo, string? descrizione, string? prodotto, string? profilo) : IRequest> +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? Descrizione { get; internal set; } = descrizione; + public string? Prodotto { get; internal set; } = prodotto; + public string? Profilo { get; internal set; } = profilo; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRecapitistiConsolidatori.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRecapitistiConsolidatori.cs new file mode 100644 index 0000000..c5253a4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/EnteQueryGetByRecapitistiConsolidatori.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.SelfCare; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public sealed class EnteQueryGetByRecapitistiConsolidatori(IAuthenticationInfo? authenticationInfo, string? tipo) : IRequest> +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public string? Tipo { get; internal set; } = tipo; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/FlagContestazioneQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/FlagContestazioneQueryGetAll.cs new file mode 100644 index 0000000..4006d15 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/FlagContestazioneQueryGetAll.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public class FlagContestazioneQueryGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/CategoriaSpedizioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/CategoriaSpedizioneSQLBuilder.cs new file mode 100644 index 0000000..86d70de --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/CategoriaSpedizioneSQLBuilder.cs @@ -0,0 +1,26 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public class CategoriaSpedizioneSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + CategoriaSpedizione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Descrizione)); + builder.Select(nameof(@obj.Tipo)); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(CategoriaSpedizione); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/EnteSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/EnteSQLBuilder.cs new file mode 100644 index 0000000..039a13c --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/EnteSQLBuilder.cs @@ -0,0 +1,122 @@ +using System.Text; +using Dapper; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class EnteSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + Ente? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Descrizione).GetAsColumn()); + return builder; + } + + private static SqlBuilder CreateSelectWithId() + { + Ente? @obj = null; + var builder = new SqlBuilder(); + builder.Select($"e.{nameof(@obj.IdEnte).GetAsColumn()}"); + builder.Select(nameof(@obj.Descrizione).GetAsColumn()); + return builder; + } + + private static string WhereBySearch() + { + Ente? obj; + var fieldDescription = nameof(@obj.Descrizione).GetColumn(); + return $"{fieldDescription} LIKE '%' + @{nameof(@obj.Descrizione)} + '%'"; + } + + private static string WhereByTipo() + { + Ente? obj; + var fieldDescription = nameof(@obj.Profilo).GetColumn(); + return $"{fieldDescription} = @{nameof(@obj.Profilo)}"; + } + + public static string AddSearch(string? prodotto, string? profilo) + { + var stringBuilder = new StringBuilder(); + Ente? obj; + if (!string.IsNullOrWhiteSpace(profilo)) + { + stringBuilder.Append(" AND "); + var fieldProfilo = nameof(@obj.Profilo).GetColumn(); + stringBuilder.Append($"{fieldProfilo} = @{nameof(@obj.Profilo)}"); + } + + if (!string.IsNullOrWhiteSpace(prodotto)) + { + stringBuilder.Append(" AND "); + var fieldProdotto= nameof(Contratto.Prodotto).GetColumn(); + stringBuilder.Append($"{fieldProdotto} = @{nameof(Contratto.Prodotto)}"); + } + return stringBuilder.ToString(); + } + + private static int _top = 100; + public static string SelectAllBySearch() + { + var tableName = $"[schema]{nameof(Ente).GetTable()} e"; + var builder = CreateSelect(); + + var rightEnteTable = $"[schema]{nameof(Ente).GetTable()}"; + var innerContrattoTable = $"[schema]{nameof(Contratto).GetTable()}"; + var internalIdEnte = nameof(Ente.IdEnte).GetColumn(); + builder.InnerJoin($"{innerContrattoTable} c on e.{internalIdEnte} = c.{internalIdEnte}"); + + builder.Where(WhereBySearch()); + + var builderTemplate = builder.AddTemplate($"Select TOP {_top} /**select**/ from {tableName} /**innerjoin**/ /**where**/ "); + return builderTemplate.RawSql; + } + public static string SelectAllByDescrizione() + { + var tableName = $"[schema]{nameof(Ente).GetTable()} e"; + var builder = CreateSelectWithId(); + + var rightEnteTable = $"[schema]{nameof(Ente).GetTable()}"; + var innerContrattoTable = $"[schema]{nameof(Contratto).GetTable()}"; + var internalIdEnte = nameof(Ente.IdEnte).GetColumn(); + builder.InnerJoin($"{innerContrattoTable} c on e.{internalIdEnte} = c.{internalIdEnte}"); + + builder.Where(WhereBySearch()); + + var builderTemplate = builder.AddTemplate($"Select TOP {_top} /**select**/ from {tableName} /**innerjoin**/ /**where**/ "); + return builderTemplate.RawSql; + } + + public static string SelectAllByTipo() + { + var tableName = $"[schema]{nameof(Ente).GetTable()} e"; + var builder = CreateSelectWithId(); + + var rightEnteTable = $"[schema]{nameof(Ente).GetTable()}"; + var innerContrattoTable = $"[schema]{nameof(Contratto).GetTable()}"; + var internalIdEnte = nameof(Ente.IdEnte).GetColumn(); + builder.InnerJoin($"{innerContrattoTable} c on e.{internalIdEnte} = c.{internalIdEnte}"); + + builder.Where(WhereByTipo()); + + var builderTemplate = builder.AddTemplate($"Select TOP {_top} /**select**/ from {tableName} /**innerjoin**/ /**where**/ "); + return builderTemplate.RawSql; + } + + private static string _sqlAll = @$"Select e.internalistitutionid as IdEnte , +description as RagioneSociale, +c.onboardingtokenid as IdContratto, +t.Descrizione as TipoContratto + from pfd.Enti e + INNER JOIN pfd.Contratti c + on e.internalistitutionid = c.internalistitutionid + INNER JOIN pfw.TipoContratto t + on t.IdTipoContratto = c.FkIdTipoContratto"; + public static string SelectAll() + { + return _sqlAll; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/FlagContestazioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/FlagContestazioneSQLBuilder.cs new file mode 100644 index 0000000..74796a5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/FlagContestazioneSQLBuilder.cs @@ -0,0 +1,26 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class FlagContestazioneSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + FlagContestazione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Flag).GetAsColumn()); + builder.Select(nameof(@obj.Descrizione).GetAsColumn()); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(FlagContestazione); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProdottoSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProdottoSQLBuilder.cs new file mode 100644 index 0000000..b7e1641 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProdottoSQLBuilder.cs @@ -0,0 +1,25 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class ProdottoSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + Prodotto? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Nome).GetAsColumn()); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(Prodotto); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProfiloSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProfiloSQLBuilder.cs new file mode 100644 index 0000000..9b038f6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/ProfiloSQLBuilder.cs @@ -0,0 +1,25 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class ProfiloSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + Ente? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Profilo).GetAsColumn()); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(Ente); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select DISTINCT /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/StatoCommessaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/StatoCommessaSQLBuilder.cs new file mode 100644 index 0000000..e0e87e0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/StatoCommessaSQLBuilder.cs @@ -0,0 +1,35 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public class StatoCommessaSQLBuilder +{ + private static string WhereById() + { + StatoCommessa? obj; + var fieldIdEnte = nameof(@obj.Default); + return $"[{fieldIdEnte}] = 1"; + } + + private static SqlBuilder CreateSelect() + { + StatoCommessa? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Stato)); + return builder; + } + + public static string SelectBy() + { + var tableName = nameof(StatoCommessa); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoCommessaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoCommessaSQLBuilder.cs new file mode 100644 index 0000000..eb179dc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoCommessaSQLBuilder.cs @@ -0,0 +1,25 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class TipoCommessaSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + TipoCommessa? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Descrizione)); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(TipoCommessa); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContestazioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContestazioneSQLBuilder.cs new file mode 100644 index 0000000..39c5eeb --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContestazioneSQLBuilder.cs @@ -0,0 +1,25 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class TipoContestazioneSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + TipoContestazione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Tipo).GetAsColumn()); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(TipoContestazione); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContrattoSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContrattoSQLBuilder.cs new file mode 100644 index 0000000..23e7945 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoContrattoSQLBuilder.cs @@ -0,0 +1,27 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class TipoContrattoSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + TipoContratto? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Descrizione)); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(TipoContratto); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoFatturaSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoFatturaSQLBuilder.cs new file mode 100644 index 0000000..1cd6bda --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoFatturaSQLBuilder.cs @@ -0,0 +1,21 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +public static class TipoFatturaSQLBuilder +{ + private static string _sql = @" +SELECT distinct + [FkTipologiaFattura] + FROM [pfd].[FattureTestata] +WHERE [AnnoRiferimento]=@anno AND [MeseRiferimento]=@mese +ORDER BY [FkTipologiaFattura] +"; + public static string SelectAll() + { + return _sql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoSpedizioneSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoSpedizioneSQLBuilder.cs new file mode 100644 index 0000000..b1a79de --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/Builder/TipoSpedizioneSQLBuilder.cs @@ -0,0 +1,26 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; +public class TipoSpedizioneSQLBuilder +{ + private static SqlBuilder CreateSelect() + { + TipoSpedizione? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.Id).GetAsColumn()); + builder.Select(nameof(@obj.Descrizione)); + builder.Select(nameof(@obj.IdCategoriaSpedizione).GetAsColumn()); + builder.Select(nameof(@obj.Tipo)); + return builder; + } + + public static string SelectAll() + { + var tableName = nameof(TipoSpedizione); + var builder = CreateSelect(); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName}"); + return builderTemplate.RawSql; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByDescrizionePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByDescrizionePersistence.cs new file mode 100644 index 0000000..9c6cc3f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByDescrizionePersistence.cs @@ -0,0 +1,22 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class EnteQueryGetByDescrizionePersistence(string descrizione) : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = EnteSQLBuilder.SelectAllByDescrizione(); + private readonly string _descrizione = descrizione; + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var sql = _sqlSelect.Add(schema); + + return await ((IDatabase)this).SelectAsync(connection!, sql, new + { + descrizione = _descrizione + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRagioneSocialePersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRagioneSocialePersistence.cs new file mode 100644 index 0000000..29ac23a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRagioneSocialePersistence.cs @@ -0,0 +1,25 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class EnteQueryGetByRagioneSocialePersistence(string descrizione, string? prodotto, string? profilo) : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = EnteSQLBuilder.SelectAllBySearch(); + private readonly string _descrizione = descrizione; + private readonly string? _prodotto = prodotto; + private readonly string? _profilo = profilo; + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var sql = _sqlSelect.Add(schema); + sql += EnteSQLBuilder.AddSearch(_prodotto, _profilo); + return await ((IDatabase)this).SelectAsync(connection!, sql, new + { + descrizione = _descrizione, + profilo = _profilo, + prodotto = _prodotto + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRecapitistiConsolidatoriPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRecapitistiConsolidatoriPersistence.cs new file mode 100644 index 0000000..a73dfab --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/EnteQueryGetByRecapitistiConsolidatoriPersistence.cs @@ -0,0 +1,22 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class EnteQueryGetByRecapitistiConsolidatoriPersistence(string? tipo) : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = EnteSQLBuilder.SelectAllByTipo(); + private readonly string? _tipo = tipo!; + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var sql = _sqlSelect.Add(schema); + + return await ((IDatabase)this).SelectAsync(connection!, sql, new + { + profilo = _tipo + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/FlagContestazioneQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/FlagContestazioneQueryGetAllPersistence.cs new file mode 100644 index 0000000..5c3dd4e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/FlagContestazioneQueryGetAllPersistence.cs @@ -0,0 +1,16 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class FlagContestazioneQueryGetAllPersistence : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = FlagContestazioneSQLBuilder.SelectAll(); + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProdottoQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProdottoQueryGetAllPersistence.cs new file mode 100644 index 0000000..3556b0a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProdottoQueryGetAllPersistence.cs @@ -0,0 +1,18 @@ +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries.Persistence.Builder; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; +using System.Data; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class ProdottoQueryGetAllPersistence : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = ProdottoSQLBuilder.SelectAll(); + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProfiloQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProfiloQueryGetAllPersistence.cs new file mode 100644 index 0000000..c051756 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/ProfiloQueryGetAllPersistence.cs @@ -0,0 +1,15 @@ +using System.Data; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class ProfiloQueryGetAllPersistence : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = ProfiloSQLBuilder.SelectAll(); + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/SpedizioneQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/SpedizioneQueryGetAllPersistence.cs new file mode 100644 index 0000000..ef93554 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/SpedizioneQueryGetAllPersistence.cs @@ -0,0 +1,23 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class SpedizioneQueryGetAllPersistence : DapperBase, IQuery?> +{ + private static readonly string _sqlSelect = string.Join(";", CategoriaSpedizioneSQLBuilder.SelectAll(), TipoSpedizioneSQLBuilder.SelectAll()); + public async Task?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken ct = default) + { + var categorie = await ((IDatabase)this).QueryMultipleAsync(connection!, _sqlSelect.Add(schema), null, transaction); + if (categorie == null) + return null; + var masterCategorie = await categorie.ReadAsync(); + var tipi = await categorie.ReadAsync(); + foreach (var cat in masterCategorie) + cat.TipoSpedizione = tipi.Where(x => x.IdCategoriaSpedizione == cat.Id).ToList(); + + return masterCategorie; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/StatoCommessaQueryGetByDefaultPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/StatoCommessaQueryGetByDefaultPersistence.cs new file mode 100644 index 0000000..982fb32 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/StatoCommessaQueryGetByDefaultPersistence.cs @@ -0,0 +1,17 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class StatoCommessaQueryGetByDefaultPersistence : DapperBase, IQuery +{ + private static readonly string _sqlSelect = StatoCommessaSQLBuilder.SelectBy(); + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var results = await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + return results.IsNullNotAny() ? null : results.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoCommessaQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoCommessaQueryGetAllPersistence.cs new file mode 100644 index 0000000..903d34f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoCommessaQueryGetAllPersistence.cs @@ -0,0 +1,16 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class TipoCommessaQueryGetAllPersistence : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = TipoCommessaSQLBuilder.SelectAll(); + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContestazioneQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContestazioneQueryGetAllPersistence.cs new file mode 100644 index 0000000..7737406 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContestazioneQueryGetAllPersistence.cs @@ -0,0 +1,16 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class TipoContestazioneQueryGetAllPersistence : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = TipoContestazioneSQLBuilder.SelectAll(); + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContrattoQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContrattoQueryGetAllPersistence.cs new file mode 100644 index 0000000..b2d6266 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoContrattoQueryGetAllPersistence.cs @@ -0,0 +1,16 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class TipoContrattoQueryGetAllPersistence : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = TipoContrattoSQLBuilder.SelectAll(); + + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), null, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoFatturaQueryGetAllPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoFatturaQueryGetAllPersistence.cs new file mode 100644 index 0000000..2c07f9d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/Persistence/TipoFatturaQueryGetAllPersistence.cs @@ -0,0 +1,20 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +public class TipoFatturaQueryGetAllPersistence(int anno, int mese) : DapperBase, IQuery> +{ + private static readonly string _sqlSelect = TipoFatturaSQLBuilder.SelectAll(); + private readonly int _anno = anno; + private readonly int _mese = mese; + public async Task> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + return await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), new { + anno = _anno, + mese = _mese + }, transaction); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProdottoQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProdottoQueryGetAll.cs new file mode 100644 index 0000000..1a24648 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProdottoQueryGetAll.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Tipologie; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public sealed class ProdottoQueryGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProfiloQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProfiloQueryGetAll.cs new file mode 100644 index 0000000..58a163a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/ProfiloQueryGetAll.cs @@ -0,0 +1,9 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public sealed class ProfiloQueryGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/SpedizioneQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/SpedizioneQueryGetAll.cs new file mode 100644 index 0000000..c658837 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/SpedizioneQueryGetAll.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Tipologie; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public class SpedizioneQueryGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/StatoCommessaQueryGetByDefault.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/StatoCommessaQueryGetByDefault.cs new file mode 100644 index 0000000..559f7f2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/StatoCommessaQueryGetByDefault.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Tipologie; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public class StatoCommessaQueryGetByDefault : IRequest +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoCommessaQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoCommessaQueryGetAll.cs new file mode 100644 index 0000000..6d7740b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoCommessaQueryGetAll.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Tipologie; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public class TipoCommessaQueryGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContestazioneGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContestazioneGetAll.cs new file mode 100644 index 0000000..fe7c215 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContestazioneGetAll.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Tipologie; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public sealed class TipoContestazioneGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContrattoQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContrattoQueryGetAll.cs new file mode 100644 index 0000000..1ec0bed --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoContrattoQueryGetAll.cs @@ -0,0 +1,10 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Tipologie; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public class TipoContrattoQueryGetAll : IRequest> +{ + IAuthenticationInfo? AuthenticationInfo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoFatturaQueryGetAll.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoFatturaQueryGetAll.cs new file mode 100644 index 0000000..cec412a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/Queries/TipoFatturaQueryGetAll.cs @@ -0,0 +1,11 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +public class TipoFatturaQueryGetAll(AuthenticationInfo? authenticationInfo, int anno, int mese) : IRequest> +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo; + public int Anno { get; internal set; } = anno; + public int Mese { get; internal set; } = mese; +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EnteQueryGetByRecapitistiConsolidatoriHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EnteQueryGetByRecapitistiConsolidatoriHandler.cs new file mode 100644 index 0000000..74cfeae --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EnteQueryGetByRecapitistiConsolidatoriHandler.cs @@ -0,0 +1,35 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class EnteQueryGetByRecapitistiConsolidatoriHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task> Handle(EnteQueryGetByRecapitistiConsolidatori request, CancellationToken ct) + { + if (request.AuthenticationInfo!.Auth! != AuthType.PAGOPA) + throw new SecurityException(); + + if (request == null || request!.Tipo == null || (request!.Tipo != Profilo.Recapitista && request!.Tipo != Profilo.Consolidatore)) + throw new ValidationException(_localizer["RicercaEnteEmpty"]); + + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new EnteQueryGetByRecapitistiConsolidatoriPersistence(request.Tipo), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByDescrizioneHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByDescrizioneHandler.cs new file mode 100644 index 0000000..e868a0a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByDescrizioneHandler.cs @@ -0,0 +1,35 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class EntiQueryGetByDescrizioneHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task> Handle(EnteQueryGetByDescrizione request, CancellationToken ct) + { + //if (request.AuthenticationInfo!.Auth! != AuthType.PAGOPA || request.AuthenticationInfo!.Auth! != AuthType.con) + // throw new SecurityException(); + + if (request == null || request!.Descrizione == null || request!.Descrizione.Length < 3) + throw new ValidationException(_localizer["RicercaEnteEmpty"]); + + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new EnteQueryGetByDescrizionePersistence(request.Descrizione!), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByRagioneSocialeHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByRagioneSocialeHandler.cs new file mode 100644 index 0000000..db4fb9d --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/EntiQueryGetByRagioneSocialeHandler.cs @@ -0,0 +1,34 @@ +using System.Security; +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class EntiQueryGetByRagioneSocialeHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler> +{ + private readonly ISelfCareDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task> Handle(EnteQueryGetByRagioneSociale request, CancellationToken ct) + { + if (request.AuthenticationInfo!.Auth! != AuthType.PAGOPA) + throw new SecurityException(); + + if (request == null || request!.Descrizione == null) + throw new ValidationException(_localizer["RicercaEnteEmpty"]); + + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new EnteQueryGetByRagioneSocialePersistence(request.Descrizione!, request.Prodotto, request.Profilo), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/FlagContestazioneQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/FlagContestazioneQueryHandler.cs new file mode 100644 index 0000000..09672d2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/FlagContestazioneQueryHandler.cs @@ -0,0 +1,26 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class FlagContestazioneQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler> +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task> Handle(FlagContestazioneQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new FlagContestazioneQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProdottoQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProdottoQueryHandler.cs new file mode 100644 index 0000000..5f7b838 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProdottoQueryHandler.cs @@ -0,0 +1,26 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class ProdottoQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler> +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task> Handle(ProdottoQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new ProdottoQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProfiloQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProfiloQueryHandler.cs new file mode 100644 index 0000000..85c95a8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/ProfiloQueryHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class ProfiloQueryHandler : IRequestHandler> +{ + private readonly ISelfCareDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public ProfiloQueryHandler( + ISelfCareDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task> Handle(ProfiloQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new ProfiloQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/SpedizioneQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/SpedizioneQueryHandler.cs new file mode 100644 index 0000000..68f15a2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/SpedizioneQueryHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class SpedizioneQueryHandler : IRequestHandler?> +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public SpedizioneQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task?> Handle(SpedizioneQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new SpedizioneQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/StatoCommessaQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/StatoCommessaQueryHandler.cs new file mode 100644 index 0000000..c043b70 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/StatoCommessaQueryHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +internal class StatoCommessaQueryHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public StatoCommessaQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task Handle(StatoCommessaQueryGetByDefault request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new StatoCommessaQueryGetByDefaultPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoCommessaQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoCommessaQueryHandler.cs new file mode 100644 index 0000000..97462f2 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoCommessaQueryHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class TipoCommessaQueryHandler : IRequestHandler> +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public TipoCommessaQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task> Handle(TipoCommessaQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new TipoCommessaQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContestazioneQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContestazioneQueryHandler.cs new file mode 100644 index 0000000..8e3cd53 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContestazioneQueryHandler.cs @@ -0,0 +1,27 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class TipoContestazioneQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) : IRequestHandler> +{ + private readonly IFattureDbContextFactory _factory = factory; + private readonly ILogger _logger = logger; + private readonly IStringLocalizer _localizer = localizer; + + public async Task> Handle(TipoContestazioneGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new TipoContestazioneQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContrattoQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContrattoQueryHandler.cs new file mode 100644 index 0000000..4023052 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoContrattoQueryHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class TipoContrattoQueryHandler : IRequestHandler> +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public TipoContrattoQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task> Handle(TipoContrattoQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new TipoContrattoQueryGetAllPersistence(), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoFatturaQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoFatturaQueryHandler.cs new file mode 100644 index 0000000..df7feab --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Tipologie/QueryHandlers/TipoFatturaQueryHandler.cs @@ -0,0 +1,32 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Tipologie.QueryHandlers; + +public class TipoFatturaQueryHandler : IRequestHandler> +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + public TipoFatturaQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + + public async Task> Handle(TipoFatturaQueryGetAll request, CancellationToken ct) + { + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new TipoFatturaQueryGetAllPersistence(request.Anno, request.Mese), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/CommandHandlers/UtenteCreateCommandHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/CommandHandlers/UtenteCreateCommandHandler.cs new file mode 100644 index 0000000..278692a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/CommandHandlers/UtenteCreateCommandHandler.cs @@ -0,0 +1,36 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Utenti; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Utenti.Commands; +using PortaleFatture.BE.Infrastructure.Common.Utenti.Commands.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.CommandHandlers; + +public class UtenteCreateCommandHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public UtenteCreateCommandHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + public async Task Handle(UtenteCreateCommand command, CancellationToken ct) + { + var (_, _, _, adesso) = Time.YearMonthDay(); + command.DataUltimo = command.DataUltimo == null ? adesso : command.DataUltimo.Value; + command.DataPrimo = command.DataPrimo == null ? adesso : command.DataPrimo.Value; + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Execute(new UtenteCreateCommandPersistence(command), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/Persistence/UtenteCreateCommandPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/Persistence/UtenteCreateCommandPersistence.cs new file mode 100644 index 0000000..cb4618a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/Persistence/UtenteCreateCommandPersistence.cs @@ -0,0 +1,59 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Entities.Utenti; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.Commands.Persistence; + +public class UtenteCreateCommandPersistence : DapperBase, ICommand +{ + public bool RequiresTransaction => false; + private readonly UtenteCreateCommand _command; + public UtenteCreateCommandPersistence(UtenteCreateCommand command) + => _command = command; + + private static readonly string _sqlInsertUpdate = @" +MERGE +INTO [schema]utenti as dm +using (VALUES + ( + @idEnte, + @idUtente, + @dataPrimo, + @dataUltimo + ) + ) AS source (idEnte, idUtente, dataPrimo, dataUltimo) +ON dm.fkidente = source.idente +AND dm.idUtente = source.idUtente +WHEN matched THEN +UPDATE +SET dataUltimo = source.dataUltimo +WHEN NOT matched THEN +INSERT + ( + fkidente, + idUtente, + dataPrimo, + dataUltimo + ) + VALUES + ( + source.idEnte, + source.idUtente, + source.dataPrimo, + source.dataUltimo + ); +SELECT * FROM [schema]utenti WHERE fkidente=@idEnte AND @idUtente = idUtente; +"; + + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var utente = await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsertUpdate.Add(schema), + new { idEnte = _command.AuthenticationInfo!.IdEnte, + idUtente = _command.AuthenticationInfo.Id, + dataPrimo = _command.DataPrimo, + dataUltimo = _command.DataUltimo }, transaction); + + return utente; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/UtenteCreateCommand.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/UtenteCreateCommand.cs new file mode 100644 index 0000000..60e6433 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Commands/UtenteCreateCommand.cs @@ -0,0 +1,16 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Utenti; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.Commands; + +public class UtenteCreateCommand : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } + public UtenteCreateCommand(IAuthenticationInfo? authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } + public DateTime? DataPrimo { get; set; } + public DateTime? DataUltimo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/Builder/UtenteSQLBuilder.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/Builder/UtenteSQLBuilder.cs new file mode 100644 index 0000000..f040b3b --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/Builder/UtenteSQLBuilder.cs @@ -0,0 +1,39 @@ +using Dapper; +using PortaleFatture.BE.Core.Entities.SelfCare; +using PortaleFatture.BE.Core.Entities.Utenti; +using PortaleFatture.BE.Infrastructure.Common.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.Queries.Persistence.Builder; + +public class UtenteSQLBuilder +{ + private static string WhereById() + { + Utente? obj; + var fieldIdEnte = nameof(@obj.IdEnte).GetColumn(); + var fieldIdUtente = nameof(@obj.IdUtente); + return $"{fieldIdEnte} = @{nameof(@obj.IdEnte)} AND {fieldIdUtente} = @{nameof(@obj.IdUtente)} "; + } + + private static SqlBuilder CreateSelect() + { + Utente? @obj = null; + var builder = new SqlBuilder(); + builder.Select(nameof(@obj.IdUtente)); + builder.Select(nameof(@obj.IdEnte).GetAsColumn()); + builder.Select(nameof(@obj.DataUltimo)); + builder.Select(nameof(@obj.DataPrimo)); + return builder; + } + + public static string SelectBy() + { + var tableName = nameof(Utente); + tableName = tableName.GetTable(); + var builder = CreateSelect(); + var where = WhereById(); + builder.Where(where); + var builderTemplate = builder.AddTemplate($"Select /**select**/ from [schema]{tableName} /**where**/ "); + return builderTemplate.RawSql; + } +} diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/UtenteQueryGetByIdPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/UtenteQueryGetByIdPersistence.cs new file mode 100644 index 0000000..1ee5468 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/Persistence/UtenteQueryGetByIdPersistence.cs @@ -0,0 +1,24 @@ +using System.Data; +using PortaleFatture.BE.Core.Entities.Utenti; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Utenti.Queries.Persistence.Builder; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.Queries.Persistence; + +public class UtenteQueryGetByIdPersistence : DapperBase, IQuery +{ + private readonly string? _idEnte; + private readonly string? _idUtente; + private static readonly string _sqlSelect = UtenteSQLBuilder.SelectBy(); + + public UtenteQueryGetByIdPersistence(string idEnte, string idUtente) + { + this._idEnte = idEnte; + this._idUtente = idUtente; + } + public async Task Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default) + { + var results = await ((IDatabase)this).SelectAsync(connection!, _sqlSelect.Add(schema), new { IdEnte = _idEnte, IdUtente = _idUtente }, transaction); + return results?.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/UtenteQueryGetById.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/UtenteQueryGetById.cs new file mode 100644 index 0000000..a474401 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/Queries/UtenteQueryGetById.cs @@ -0,0 +1,16 @@ +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Utenti; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.Queries; + +public class UtenteQueryGetById : IRequest +{ + public IAuthenticationInfo? AuthenticationInfo { get; internal set; } + public UtenteQueryGetById(IAuthenticationInfo? authenticationInfo) + { + this.AuthenticationInfo = authenticationInfo; + } + public DateTime DataPrimo { get; set; } + public DateTime DataUltimo { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/QueryHandlers/UtenteQueryHandler.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/QueryHandlers/UtenteQueryHandler.cs new file mode 100644 index 0000000..f9ac415 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Utenti/QueryHandlers/UtenteQueryHandler.cs @@ -0,0 +1,36 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.Utenti; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Utenti.Queries; +using PortaleFatture.BE.Infrastructure.Common.Utenti.Queries.Persistence; + +namespace PortaleFatture.BE.Infrastructure.Common.Utenti.QueryHandlers; + +public class UtenteQueryHandler : IRequestHandler +{ + private readonly IFattureDbContextFactory _factory; + private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + + public UtenteQueryHandler( + IFattureDbContextFactory factory, + IStringLocalizer localizer, + ILogger logger) + { + _factory = factory; + _localizer = localizer; + _logger = logger; + } + public async Task Handle(UtenteQueryGetById request, CancellationToken ct) + { + var idEnte = request.AuthenticationInfo!.IdEnte; + var idUtente = request.AuthenticationInfo!.Id; + using var uow = await _factory.Create(cancellationToken: ct); + return await uow.Query(new UtenteQueryGetByIdPersistence(idEnte!, idUtente!), ct); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/ConfigurationExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/ConfigurationExtensions.cs new file mode 100644 index 0000000..ad0dd2f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/ConfigurationExtensions.cs @@ -0,0 +1,65 @@ +using System.Text; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; + +namespace PortaleFatture.BE.Infrastructure; + +public static class ConfigurationExtensions +{ + public static JwtBearerOptions JwtAuthenticationAzureAdConfiguration(this JwtBearerOptions options, AzureAd jwtAuth) + { + if (jwtAuth == null) + { + throw new ConfigurationException("Jwt configuration error"); + } + + options.SaveToken = true; + options.Audience = jwtAuth.ClientId; + options.Authority = $"{jwtAuth.Instance}{jwtAuth.TenantId}"; + return options; + } + + public static JwtBearerOptions JwtAuthenticationConfiguration(this JwtBearerOptions options, JwtConfiguration jwtAuth) + { + if (jwtAuth == null) + { + throw new ConfigurationException("Jwt configuration error"); + } + + if (jwtAuth.ValidIssuer == null || jwtAuth.ValidAudience == null || jwtAuth.Secret == null) + { + throw new ConfigurationException("Jwt configuration error"); + } + + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidIssuer = jwtAuth.ValidIssuer, + ValidateAudience = true, + ValidAudience = jwtAuth.ValidAudience, + ValidateLifetime = true, + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtAuth.Secret)), + RequireExpirationTime = true, + ClockSkew = TimeSpan.Zero + }; + options.Events = new JwtBearerEvents + { + OnAuthenticationFailed = context => + { + if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) + { + context.Response.Headers.Add("IS-TOKEN-EXPIRED", "true"); + } + + return Task.CompletedTask; + } + }; + + return options; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/AesEncryption.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/AesEncryption.cs new file mode 100644 index 0000000..1126a9f --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/AesEncryption.cs @@ -0,0 +1,59 @@ +using System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.WebUtilities; + +namespace PortaleFatture.BE.Infrastructure.Gateway; +public class AesEncryption(string key) : IAesEncryption +{ + private readonly string _key = key; + + public string EncryptString(string plainText) + { + var iv = new byte[16]; + byte[] array; + + using (var aes = Aes.Create()) + { + aes.Key = Encoding.UTF8.GetBytes(_key); + aes.IV = iv; + + var encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + using var memoryStream = new MemoryStream(); + using var cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write); + using (var streamWriter = new StreamWriter((Stream)cryptoStream)) + { + streamWriter.Write(plainText); + } + + array = memoryStream.ToArray(); + } + + return ToString(array); + } + + public string DecryptString(string cipherText) + { + var iv = new byte[16]; + var buffer = FromString(cipherText); + + using var aes = Aes.Create(); + aes.Key = Encoding.UTF8.GetBytes(_key); + aes.IV = iv; + var decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + + using var memoryStream = new MemoryStream(buffer); + using var cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read); + using var streamReader = new StreamReader((Stream)cryptoStream); + return streamReader.ReadToEnd(); + } + private string ToString(byte[] input) + { + return WebEncoders.Base64UrlEncode(input); + } + + public byte[] FromString(string input) + { + return WebEncoders.Base64UrlDecode(input); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateContainer.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateContainer.cs new file mode 100644 index 0000000..0e5e6dd --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateContainer.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public sealed class CertificateContainer +{ + [JsonPropertyName("keys")] + public List? Keys { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateKey.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateKey.cs new file mode 100644 index 0000000..7e23f3a --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/CertificateKey.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public sealed class CertificateKey +{ + [JsonPropertyName("alg")] + public string? Alg { get; set; } + + [JsonPropertyName("kty")] + public string? Kty { get; set; } + + [JsonPropertyName("use")] + public string? Use { get; set; } + + [JsonPropertyName("x5c")] + public List? X5c { get; set; } + + [JsonPropertyName("n")] + public string? N { get; set; } + + [JsonPropertyName("e")] + public string? E { get; set; } + + [JsonPropertyName("kid")] + public string? Kid { get; set; } + + [JsonPropertyName("x5t")] + public string? X5t { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/EmailSender.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/EmailSender.cs new file mode 100644 index 0000000..b0f4c5e --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/EmailSender.cs @@ -0,0 +1,42 @@ +using MailKit.Security; +using MimeKit.Text; +using MimeKit; +using MailKit.Net.Smtp; + +namespace PortaleFatture.BE.Infrastructure.Gateway.Email; + +public class EmailSender(string smtpSource, int smtpPort, string smtpUser, string smtpPassword, string from) : IEmailSender +{ + private readonly string _smtpSource = smtpSource; + private readonly int _smtpPort = smtpPort; + private readonly string _smtpUser = smtpUser; + private readonly string _smtpPassword = smtpPassword; + private readonly string _from = from; + + public (string, bool) SendEmail( + string to, + string subject, + string message) + { + try + { + var email = new MimeMessage(); + email.From.Add(MailboxAddress.Parse(_from)); + email.To.Add(MailboxAddress.Parse(to)); + email.Subject = subject; + email.Body = new TextPart(TextFormat.Html) { Text = message }; + + using var smtp = new SmtpClient(); + smtp.Timeout = 10000; + smtp.Connect(_smtpSource, _smtpPort, SecureSocketOptions.SslOnConnect); + smtp.Authenticate(_smtpUser, _smtpPassword); + var result = smtp.Send(email); + smtp.Disconnect(true); + return (result, true); + } + catch (Exception ex) + { + return (ex.Message, false); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/IEmailSender.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/IEmailSender.cs new file mode 100644 index 0000000..59b4807 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Email/IEmailSender.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Infrastructure.Gateway.Email +{ + public interface IEmailSender + { + (string, bool) SendEmail(string to, string subject, string message); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IAesEncryption.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IAesEncryption.cs new file mode 100644 index 0000000..3e5a1d4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IAesEncryption.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Infrastructure.Gateway +{ + public interface IAesEncryption + { + string DecryptString(string cipherText); + string EncryptString(string plainText); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IMicrosoftGraphHttpClient.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IMicrosoftGraphHttpClient.cs new file mode 100644 index 0000000..8cdf6b8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IMicrosoftGraphHttpClient.cs @@ -0,0 +1,8 @@ + +namespace PortaleFatture.BE.Infrastructure.Gateway +{ + public interface IMicrosoftGraphHttpClient + { + Task> GetGroupsAsync(string azureADAccessToken, CancellationToken ct = default); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPAHttpClient.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPAHttpClient.cs new file mode 100644 index 0000000..73547c9 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPAHttpClient.cs @@ -0,0 +1,11 @@ +using System.IdentityModel.Tokens.Jwt; + +namespace PortaleFatture.BE.Infrastructure.Gateway +{ + public interface IPagoPAHttpClient + { + Task GetCertificateByKidAsync(string? kid, CancellationToken ct = default); + Task?> GetCertificatesAsync(CancellationToken ct = default); + JwtSecurityToken? GetSelfCareTokenAsync(string? selfcareToken, CancellationToken ct = default); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPATokenService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPATokenService.cs new file mode 100644 index 0000000..6d1d8dc --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/IPagoPATokenService.cs @@ -0,0 +1,11 @@ +using System.Security.Claims; +using PortaleFatture.BE.Core.Auth.PagoPA; + +namespace PortaleFatture.BE.Infrastructure.Gateway +{ + public interface IPagoPATokenService + { + Task<(ClaimsPrincipal?, bool)> Validate(string selfcareToken, bool requireExpirationTime = false, CancellationToken ct = default); + Task ValidateContent(string selfcareToken, string azureADAccessToken, bool requireExpirationTime = false, CancellationToken ct = default); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareHttpClient.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareHttpClient.cs new file mode 100644 index 0000000..281d7d4 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareHttpClient.cs @@ -0,0 +1,11 @@ +using System.IdentityModel.Tokens.Jwt; + +namespace PortaleFatture.BE.Infrastructure.Gateway +{ + public interface ISelfCareHttpClient + { + Task GetCertificateByKidAsync(string? kid, CancellationToken ct = default); + Task?> GetCertificatesAsync(CancellationToken ct = default); + JwtSecurityToken? GetSelfCareTokenAsync(string? selfcareToken, CancellationToken ct = default); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareTokenService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareTokenService.cs new file mode 100644 index 0000000..d0a20e5 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/ISelfCareTokenService.cs @@ -0,0 +1,12 @@ +using System.Security.Claims; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Auth.SelfCare; + +namespace PortaleFatture.BE.Infrastructure.Gateway +{ + public interface ISelfCareTokenService + { + Task<(ClaimsPrincipal?, bool)> Validate(string selfcareToken, bool requireExpirationTime = false, CancellationToken ct = default); + Task ValidateContent(string selfcareToken, bool requireExpirationTime = false, CancellationToken ct = default); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphGroups.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphGroups.cs new file mode 100644 index 0000000..023f700 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphGroups.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public sealed class MicrosoftGraphGroups +{ + [JsonPropertyName("@odata.context")] + public string? OdataContext { get; set; } + [JsonPropertyName("value")] + public List? Groups { get; set; } +} + +public sealed class Group +{ + [JsonPropertyName("@odata.type")] + public string? ODataType { get; set; } + + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("displayName")] + public string? DisplayName { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphHttpClient.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphHttpClient.cs new file mode 100644 index 0000000..83c38b1 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/MicrosoftGraphHttpClient.cs @@ -0,0 +1,42 @@ +using System.Security; +using Azure.Core; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public class MicrosoftGraphHttpClient( + IHttpClientFactory httpClientFactory, + ILogger logger) : IMicrosoftGraphHttpClient +{ + private readonly ILogger _logger = logger; + private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; + private readonly string _endpoint = "https://graph.microsoft.com/"; + + private HttpClient GetClient() + { + var client = _httpClientFactory.CreateClient(nameof(MicrosoftGraphHttpClient)); + client.BaseAddress = new Uri(_endpoint!); + return client; + } + public async Task> GetGroupsAsync(string azureADAccessToken, CancellationToken ct = default) + { + try + { + using var client = GetClient(); + client.DefaultRequestHeaders.Add("Authorization", "Bearer " + azureADAccessToken); + var result = await client.GetAsync($"v1.0/me/memberOf", ct); + result.EnsureSuccessStatusCode(); + var jsonResponse = await result.Content.ReadAsStringAsync(ct); + var graph = jsonResponse.Deserialize(); + return graph.Groups!.Select(t => new { t.Id, t.DisplayName }) + .ToDictionary(t => t.Id, t => t.DisplayName); + } + catch + { + var msg = "Fatal error reaching pagoPA certificates!"; + _logger.LogError(msg); + throw new SecurityException(msg); + } + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPAHttpClient.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPAHttpClient.cs new file mode 100644 index 0000000..e3f88d8 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPAHttpClient.cs @@ -0,0 +1,70 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Extensions; +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public class PagoPAHttpClient( + IPortaleFattureOptions options, + IHttpClientFactory httpClientFactory, + ILogger logger) : IPagoPAHttpClient +{ + private readonly ILogger _logger = logger; + private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; + private readonly IPortaleFattureOptions _options = options; + private HttpClient GetClient(string? baseAddress) + { + var client = _httpClientFactory.CreateClient(nameof(PagoPAHttpClient)); + client.BaseAddress = new Uri(baseAddress!); + return client; + } + + public async Task?> GetCertificatesAsync(CancellationToken ct = default) + { + try + { + using var client = GetClient(_options.AzureAd!.Instance); + var result = await client.GetAsync($"{_options.AzureAd!.TenantId}/discovery/keys?appid={_options.AzureAd!.ClientId}", ct); + result.EnsureSuccessStatusCode(); + var jsonResponse = await result.Content.ReadAsStringAsync(ct); + var container = jsonResponse.Deserialize(); + return container.Keys!; + } + catch + { + var msg = "Fatal error reaching pagoPA certificates!"; + _logger.LogError(msg); + throw new SecurityException(msg); + } + } + + public async Task GetCertificateByKidAsync(string? kid, CancellationToken ct = default) + { + var msg = "Fatal error reaching pagoPA certificates!"; + if (string.IsNullOrEmpty(kid)) + { + _logger.LogError(msg); + throw new SecurityException(msg); + } + var certificates = await GetCertificatesAsync(ct); + if (certificates == null) + { + _logger.LogError(msg); + throw new SecurityException(msg); + } + var certificate = certificates.Where(x => x.Kid == kid).FirstOrDefault(); + if (certificate == null) + { + _logger.LogError(msg); + throw new SecurityException(msg); + } + return certificate; + } + + public JwtSecurityToken? GetSelfCareTokenAsync(string? selfcareToken, CancellationToken ct = default) + { + var handler = new JwtSecurityTokenHandler(); + return handler.ReadToken(selfcareToken) as JwtSecurityToken; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPATokenService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPATokenService.cs new file mode 100644 index 0000000..b637a87 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/PagoPATokenService.cs @@ -0,0 +1,110 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security; +using System.Security.Claims; +using System.Security.Cryptography; +using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Auth.PagoPA; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; + +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public class PagoPATokenService( + IPagoPAHttpClient httpClient, + IMicrosoftGraphHttpClient httpMicrosoftGraphClient, + IPortaleFattureOptions options, + ILogger logger) : IPagoPATokenService +{ + private readonly IPagoPAHttpClient _httpClient = httpClient; + private readonly ILogger _logger = logger; + private readonly IPortaleFattureOptions _options = options; + private readonly IMicrosoftGraphHttpClient _httpMicrosoftGraphClient = httpMicrosoftGraphClient; + public async Task<(ClaimsPrincipal?, bool)> Validate(string selfcareToken, bool requireExpirationTime = false, CancellationToken ct = default) + { + var securityToken = _httpClient.GetSelfCareTokenAsync(selfcareToken); + var kid = securityToken!.Header.Kid; + var certificate = await _httpClient.GetCertificateByKidAsync(kid, ct); + return Verify(certificate, selfcareToken, requireExpirationTime); + } + + public async Task ValidateContent(string selfcareToken, string azureADAccessToken, bool requireExpirationTime = false, CancellationToken ct = default) + { + (var tk, var verify) = await Validate(selfcareToken, requireExpirationTime, ct); + if (verify) + { + // call graph 4 groups + var groups = await _httpMicrosoftGraphClient.GetGroupsAsync(azureADAccessToken, ct); + return Mapper(tk, groups); + } + throw new SecurityException(); + } + + private PagoPADto Mapper(ClaimsPrincipal? tk, Dictionary groups) + { + var claims = tk!.Claims; + var roles = claims.Where(x => x.Type == ClaimTypes.Role); + if (roles.IsNullOrEmpty()) + throw new RoleException("There are no roles in the claims."); + + var idGroups = roles.Select(x => x.Value); + + return new PagoPADto() + { + Email = claims.Where(x => x.Type == CustomClaim.PreferredUsername).FirstOrDefault()!.Value, + Uid = claims.Where(x => x.Type == CustomClaim.Oid).FirstOrDefault()!.Value, + Name = claims.Where(x => x.Type == CustomClaim.Name).FirstOrDefault()!.Value, + Roles = roles.Select(x => x.Value), + Groups = groups.Where(x=> idGroups!.Contains(x.Key)).Select(x=>x.Value)!, + }; + } + + private (ClaimsPrincipal?, bool) Verify(CertificateKey? certificate, string selfcareToken, bool requireExpirationTime) + { + var rsa = new RSACryptoServiceProvider(); + rsa.ImportParameters( + new RSAParameters() + { + Modulus = FromBase64Url(certificate!.N!), + Exponent = FromBase64Url(certificate!.E!) + }); + + var validationParameters = new TokenValidationParameters + { + RequireExpirationTime = requireExpirationTime, + RequireSignedTokens = true, + ValidAudience = _options.AzureAd!.ClientId, + ValidateAudience = true, + ValidIssuer = $"https://login.microsoftonline.com/{_options.AzureAd.TenantId}/v2.0", + ValidateIssuer = true, + ValidateLifetime = requireExpirationTime, + IssuerSigningKey = new RsaSecurityKey(rsa) + }; + var handler = new JwtSecurityTokenHandler(); + + ClaimsPrincipal claimPrincipal; + try + { + claimPrincipal = handler.ValidateToken(selfcareToken, validationParameters, out var validatedSecurityToken); + if (validatedSecurityToken == null) + return (null, false); + } + catch + { + var msg = "Token Exchange Expired! JWT: { jwt }"; + _logger.LogError(msg, selfcareToken); + throw new SecurityException(msg); + } + return (claimPrincipal, true); + } + + private static byte[] FromBase64Url(string base64Url) + { + var padded = base64Url.Length % 4 == 0 + ? base64Url : base64Url + "====".Substring(base64Url.Length % 4); + var base64 = padded.Replace("_", "/") + .Replace("-", "+"); + return Convert.FromBase64String(base64); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareHttpClient.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareHttpClient.cs new file mode 100644 index 0000000..9f74d61 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareHttpClient.cs @@ -0,0 +1,78 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public class SelfCareHttpClient( + IPortaleFattureOptions options, + IHttpClientFactory httpClientFactory, + ILogger logger) : ISelfCareHttpClient +{ + private readonly ILogger _logger = logger; + private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; + private readonly IPortaleFattureOptions _options = options; + private HttpClient GetClient(string? baseAddress = null) + { + if (string.IsNullOrWhiteSpace(baseAddress)) + { + var msg = "SelfCare uri certificate missing!"; + _logger.LogError(msg); + throw new ConfigurationException(msg); + } + + var client = _httpClientFactory.CreateClient(nameof(SelfCareHttpClient)); + client.BaseAddress = new Uri(baseAddress); + return client; + } + + public async Task?> GetCertificatesAsync(CancellationToken ct = default) + { + try + { + using var client = GetClient(_options.SelfCareUri); + var result = await client.GetAsync(_options.SelfCareCertEndpoint, ct); + result.EnsureSuccessStatusCode(); + var jsonResponse = await result.Content.ReadAsStringAsync(ct); + var container = jsonResponse.Deserialize(); + return container.Keys!; + } + catch + { + var msg = "Fatal error reaching self care certificates!"; + _logger.LogError(msg); + throw new SecurityException(msg); + } + } + + public async Task GetCertificateByKidAsync(string? kid, CancellationToken ct = default) + { + var msg = "Fatal error reaching self care certificates!"; + if (string.IsNullOrEmpty(kid)) + { + _logger.LogError(msg); + throw new SecurityException(msg); + } + var certificates = await GetCertificatesAsync(ct); + if (certificates == null) + { + _logger.LogError(msg); + throw new SecurityException(msg); + } + var certificate = certificates.Where(x => x.Kid == kid).FirstOrDefault(); + if (certificate == null) + { + _logger.LogError(msg); + throw new SecurityException(msg); + } + return certificate; + } + + public JwtSecurityToken? GetSelfCareTokenAsync(string? selfcareToken, CancellationToken ct = default) + { + var handler = new JwtSecurityTokenHandler(); + return handler.ReadToken(selfcareToken) as JwtSecurityToken; + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareTokenService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareTokenService.cs new file mode 100644 index 0000000..dc90a67 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/SelfCareTokenService.cs @@ -0,0 +1,103 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security; +using System.Security.Claims; +using System.Security.Cryptography; +using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Auth.SelfCare; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Infrastructure.Gateway; + +public class SelfCareTokenService : ISelfCareTokenService +{ + private readonly ISelfCareHttpClient _httpClient; + private readonly ILogger _logger; + private readonly IPortaleFattureOptions _options; + public SelfCareTokenService( + ISelfCareHttpClient httpClient, + IPortaleFattureOptions options, + ILogger logger) + { + this._httpClient = httpClient; + this._logger = logger; + this._options = options; + } + + public async Task<(ClaimsPrincipal?, bool)> Validate(string selfcareToken, bool requireExpirationTime = false, CancellationToken ct = default) + { + var securityToken = _httpClient.GetSelfCareTokenAsync(selfcareToken); + var kid = securityToken!.Header.Kid; + var certificate = await _httpClient.GetCertificateByKidAsync(kid, ct); + return Verify(certificate, selfcareToken, requireExpirationTime); + } + + public async Task ValidateContent(string selfcareToken, bool requireExpirationTime = false, CancellationToken ct = default) + { + (var tk, var verify) = await Validate(selfcareToken, requireExpirationTime, ct); + if (verify) + return Mapper(tk); + return null; + } + + private SelfCareDto Mapper(ClaimsPrincipal? tk) + { + var claims = tk!.Claims; + return new SelfCareDto() + { + Email = claims.Where(x => x.Type == ClaimTypes.Email).FirstOrDefault() == null ? null : claims.Where(x => x.Type == ClaimTypes.Email).FirstOrDefault()!.Value, + Uid = claims.Where(x => x.Type == CustomClaim.Uid).FirstOrDefault()!.Value, + Organization = claims.Where(x => x.Type == CustomClaim.Organization).FirstOrDefault()!.Value.Deserialize(), + }; + } + + private (ClaimsPrincipal?, bool) Verify(CertificateKey? certificate, string selfcareToken, bool requireExpirationTime) + { + var rsa = new RSACryptoServiceProvider(); + rsa.ImportParameters( + new RSAParameters() + { + Modulus = FromBase64Url(certificate!.N!), + Exponent = FromBase64Url(certificate!.E!) + }); + + var validationParameters = new TokenValidationParameters + { + RequireExpirationTime = requireExpirationTime, + RequireSignedTokens = true, + ValidAudience = _options.SelfCareAudience, + ValidateAudience = true, + ValidIssuer = _options.SelfCareUri, + ValidateIssuer = true, + ValidateLifetime = requireExpirationTime, + IssuerSigningKey = new RsaSecurityKey(rsa) + }; + var handler = new JwtSecurityTokenHandler(); + + ClaimsPrincipal claimPrincipal; + try + { + claimPrincipal = handler.ValidateToken(selfcareToken, validationParameters, out var validatedSecurityToken); + if (validatedSecurityToken == null) + return (null, false); + } + catch + { + var msg = "Token Exchange Expired! ExJwt: { jwt }"; + _logger.LogError(msg, selfcareToken); + throw new SecurityException(msg); + } + return (claimPrincipal, true); + } + + private static byte[] FromBase64Url(string base64Url) + { + var padded = base64Url.Length % 4 == 0 + ? base64Url : base64Url + "====".Substring(base64Url.Length % 4); + var base64 = padded.Replace("_", "/") + .Replace("-", "+"); + return Convert.FromBase64String(base64); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/IRelStorageService.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/IRelStorageService.cs new file mode 100644 index 0000000..b704319 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/IRelStorageService.cs @@ -0,0 +1,13 @@ +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Gateway.Storage; + +public interface IRelStorageService +{ + Task AddDocument(RelTestataKey idTestata, MemoryStream memoryStream, string extension = ".pdf"); + Task AddStringEncodeBase64(RelTestataKey idTestata, string encodeBase64Content, string extension = ".pdf"); + Task ReadBytes(RelTestataKey idTestata, string extension = ".pdf"); + Task ReadStringEncodeBase64(RelTestataKey idTestata, string extension = ".pdf"); + Task<(byte[], Dictionary)> ReadZip(RelTestataDto testate, string extension = ".pdf"); +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/RelStorage.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/RelStorage.cs new file mode 100644 index 0000000..c3395d0 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/RelStorage.cs @@ -0,0 +1,154 @@ +using System.IO.Compression; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; + +namespace PortaleFatture.BE.Infrastructure.Gateway.Storage; + +public class RelStorageService(IPortaleFattureOptions options, + IStringLocalizer localizer, + ILogger logger) : IRelStorageService +{ + private readonly IStringLocalizer _localizer = localizer; + private readonly ILogger _logger = logger; + private readonly IPortaleFattureOptions _options = options; + public async Task AddStringEncodeBase64( + RelTestataKey idTestata, + string encodeBase64Content, + string extension = ".pdf") + { + var fileName = RelTestataKey.FileName(idTestata, extension); + var blobClient = new BlobClient(_options.Storage!.ConnectionString, + RelTestataKey.Folder(idTestata, _options.Storage.RelFolder!), + fileName); + + try + { + using var memoryStream = new MemoryStream(); + var streamWriter = new StreamWriter(memoryStream); + streamWriter.Write(encodeBase64Content); + streamWriter.Flush(); + memoryStream.Position = 0; + await blobClient.UploadAsync(memoryStream, true); + } + catch + { + var msg = $"Errore nel caricare il file {fileName}!"; + _logger.LogError(msg); + throw new DomainException(msg); + } + } + + public async Task ReadStringEncodeBase64(RelTestataKey idTestata, + string extension = ".pdf") + { + var fileName = RelTestataKey.FileName(idTestata, extension); + var blobClient = new BlobClient(_options.Storage!.ConnectionString, + RelTestataKey.Folder(idTestata, _options.Storage.RelFolder!), + fileName); + try + { + BlobDownloadResult downloadResult = await blobClient.DownloadContentAsync(); + return downloadResult.Content.ToString(); + } + catch + { + var msg = $"Errore nel legger il file {fileName}!"; + _logger.LogError(msg); + throw new DomainException(msg); + } + } + + public async Task AddDocument(RelTestataKey idTestata, + MemoryStream memoryStream, + string extension = ".pdf") + { + var fileName = RelTestataKey.FileName(idTestata, extension); + var headers = new BlobHttpHeaders + { + ContentType = "application/pdf", + ContentLanguage = "it-IT" + }; + var blobClient = new BlobClient(_options.Storage!.ConnectionString, + RelTestataKey.Folder(idTestata, _options.Storage.RelFolder!), + fileName); + try + { + memoryStream.Position = 0; + await blobClient.UploadAsync(memoryStream, true); + blobClient.SetHttpHeaders(headers); + } + catch + { + var msg = $"Errore nel caricare il file {fileName}!"; + _logger.LogError(msg); + throw new DomainException(msg); + throw; + } + } + + public async Task ReadBytes(RelTestataKey idTestata, + string extension = ".pdf") + { + byte[] bytes; + var fileName = RelTestataKey.FileName(idTestata, extension); + var blobClient = new BlobClient(_options.Storage!.ConnectionString, + RelTestataKey.Folder(idTestata, _options.Storage.RelFolder!), + fileName); + try + { + using var memoryStream = new MemoryStream(); + var downloadResult = await blobClient.DownloadToAsync(memoryStream); + bytes = memoryStream.ToArray(); + return bytes; + } + catch + { + var msg = $"Errore nel legger il file {fileName}!"; + _logger.LogError(msg); + throw new DomainException(msg); + } + } + + public async Task<(byte[], Dictionary)> ReadZip( + RelTestataDto testate, + string extension = ".pdf") + { + Dictionary fileValues = []; + byte[] zipBytes; + using var memoryStreamZip = new MemoryStream(); + { + using var zipArchive = new ZipArchive(memoryStreamZip, ZipArchiveMode.Create, false); + { + memoryStreamZip.Position = 0; + foreach (var testata in testate.RelTestate!) + { + var key = RelTestataKey.Deserialize(testata.IdTestata!); + try + { + var bytes = await ReadBytes(key); + zipArchive.AddFile(testata.NomeTestata + extension, bytes); + fileValues.Add(key.ToString(), bytes.GetHashSHA512()); + } + catch + { + var msg = $"Errore nel legger il file {key}!"; + _logger.LogError(msg); + } + } + zipArchive.Dispose(); + } + zipBytes = memoryStreamZip.ToArray(); + memoryStreamZip.Flush(); + } + + return (zipBytes, fileValues); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/StorageExtensions.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/StorageExtensions.cs new file mode 100644 index 0000000..f5b92f6 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Gateway/Storage/StorageExtensions.cs @@ -0,0 +1,16 @@ +using System.IO.Compression; + +namespace PortaleFatture.BE.Infrastructure.Gateway.Storage; +public static class StorageExtensions +{ + private static ZipArchiveEntry CreateEntry(ZipArchive zip, string entryName, CompressionLevel compressionLevel = CompressionLevel.Fastest) + { + return zip.CreateEntry(entryName, compressionLevel); + } + public static void AddFile(this ZipArchive zip, string fileName, byte[] bytes) + { + var entry = CreateEntry(zip, fileName); + using var entryStream = entry.Open(); + entryStream.Write(bytes, 0, bytes.Length); + } +} \ No newline at end of file diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/PortaleFatture.BE.Infrastructure.csproj b/src/Infrastructure/PortaleFatture.BE.Infrastructure/PortaleFatture.BE.Infrastructure.csproj new file mode 100644 index 0000000..e5c3287 --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/PortaleFatture.BE.Infrastructure.csproj @@ -0,0 +1,41 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/RootInfrastructure.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/RootInfrastructure.cs new file mode 100644 index 0000000..b5fa5ed --- /dev/null +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/RootInfrastructure.cs @@ -0,0 +1,5 @@ +namespace PortaleFatture.BE.Infrastructure; + +public class RootInfrastructure +{ +} diff --git a/src/Presentation/PortaleFatture.BE.Api/Dockerfile b/src/Presentation/PortaleFatture.BE.Api/Dockerfile new file mode 100644 index 0000000..42dcef3 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Dockerfile @@ -0,0 +1,28 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build + +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["src/Presentation/PortaleFatture.BE.Api/PortaleFatture.BE.Api.csproj", "src/Presentation/PortaleFatture.BE.Api/"] +COPY ["src/Infrastructure/PortaleFatture.BE.Infrastructure/PortaleFatture.BE.Infrastructure.csproj", "src/Infrastructure/PortaleFatture.BE.Infrastructure/"] +COPY ["src/Core/PortaleFatture.BE.Core/PortaleFatture.BE.Core.csproj", "src/Core/PortaleFatture.BE.Core/"] +RUN dotnet restore "./src/Presentation/PortaleFatture.BE.Api/./PortaleFatture.BE.Api.csproj" +COPY . . +WORKDIR "/src/src/Presentation/PortaleFatture.BE.Api" +RUN dotnet build "./PortaleFatture.BE.Api.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./PortaleFatture.BE.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "PortaleFatture.BE.Api.dll"] \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs new file mode 100644 index 0000000..18a6a7c --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs @@ -0,0 +1,381 @@ +using System.Diagnostics; +using System.Reflection; +using System.Security; +using System.Security.Claims; +using System.Text.Json; +using Dapper; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Http.Json; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Logging; +using Microsoft.OpenApi.Models; +using Polly; +using Polly.Extensions.Http; +using PortaleFatture.BE.Api.Infrastructure.Culture; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure; +using PortaleFatture.BE.Infrastructure.Common; +using PortaleFatture.BE.Infrastructure.Common.Documenti; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari; +using PortaleFatture.BE.Infrastructure.Gateway; +using PortaleFatture.BE.Infrastructure.Gateway.Storage; + +namespace PortaleFatture.BE.Api.Infrastructure; +public static class ConfigurationExtensions +{ + private static readonly ModuleManager _moduleManager = new(); + public static IServiceCollection AddModules(this WebApplicationBuilder builder) + { + var services = builder.Services; + var configuration = builder.Configuration; + var isProd = builder.Environment.IsProduction(); + + PortaleFattureOptions options = new(); + configuration.GetSection(nameof(PortaleFattureOptions)).Bind(options); + + if (isProd) + { + AsyncHelper.RunSync(options.VaultClientSettings); + + builder.Logging.AddApplicationInsights( + configureTelemetryConfiguration: (config) => + config.ConnectionString = options.ApplicationInsights, + configureApplicationInsightsLoggerOptions: (options) => { } + ); + } + + SqlMapper.AddTypeHandler(typeof(FattureListaDto), new JsonTypeHandler()); + + services.AddSingleton(options); + + services.AddAssemblyToModuleRegistration(typeof(ConfigurationExtensions).Assembly); + + services.AddLogging(o => o.AddConfiguration(configuration.GetSection(Module.LoggingLabel))); + + services + .AddJwtOrApiKeyAuthentication(options!) + .AddIdentities(options!); + + services + .AddEndpointsApiExplorer() + .AddSwaggerGen(o => + { + o.SwaggerDoc("v1", new OpenApiInfo { Title = "Portale Fatture", Version = "v1" }); + o.AddSecurityDefinition("nonce", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.ApiKey, + In = ParameterLocation.Query, + Name = "nonce", + Description = "Nonce query string expected session key" + }); + o.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "nonce" + } + }, + Array.Empty() + } + }); + o.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Name = "Authorization", + Type = SecuritySchemeType.ApiKey, + Scheme = "Bearer", + BearerFormat = "JWT", + In = ParameterLocation.Header, + Description = "JSON Web Token based security" + }); + o.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + Array.Empty() + } + }); + }) + .AddCors(opt => + { + opt.AddPolicy(Module.CORSLabel, o => + o + .WithOrigins(options.CORSOrigins!.Split(";")) + .AllowAnyHeader() + .AllowAnyMethod()); + }) + .AddGateways() + .AddInfrastructure() + .AddLocalization(); + + return services; + } + + public static IServiceCollection AddGateways(this IServiceCollection services) + { + static IAsyncPolicy ExponentialRetryPolicy() + { + return HttpPolicyExtensions + .HandleTransientHttpError() + .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) + .WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(1)); + } + + services.AddHttpClient(Module.GatewayLabel, (_, client) => + { + client.DefaultRequestHeaders.Add("ConsistencyLevel", "eventual"); + }) + .SetHandlerLifetime(TimeSpan.FromMinutes(5)) + .AddPolicyHandler(ExponentialRetryPolicy()); + services.AddSingleton(); + return services; + } + + public static IServiceCollection AddAssemblyToModuleRegistration(this IServiceCollection services, Assembly assembly) + { + _moduleManager.AddModulesFromAssembly(assembly); + _moduleManager.RegisterModules(services); + + return services; + } + + private static IApplicationBuilder MapEndpoints(this WebApplication application) + { + return _moduleManager.MapEndpoints(application); + } + + [DebuggerStepThrough] + public static WebApplication UseModules(this WebApplication application) + { + if (!application.Environment.IsDevelopment()) + application.UseHttpsRedirection(); + + application + .UseCulture() + .UseSwagger() + .UseSwaggerUI() + .UseCors(Module.CORSLabel) + .UseHttpsRedirection() + .UseExceptionHandler(exceptionHandlerApp => + exceptionHandlerApp.Run(context => + { + var exceptionHandlerPathFeature = context.Features.Get(); + var exception = exceptionHandlerPathFeature?.Error; + var problem = exception switch + { + SessionException => Results.Problem(statusCode: StatusCodes.Status419AuthenticationTimeout, detail: exception.Message), + ConfigurationException => Results.Problem(statusCode: StatusCodes.Status400BadRequest, detail: exception.Message), + SecurityException => Results.Problem(statusCode: StatusCodes.Status401Unauthorized), + RoleException => Results.Problem(statusCode: StatusCodes.Status403Forbidden), + DomainException => Results.Problem(statusCode: StatusCodes.Status500InternalServerError, detail: exception.Message), + ValidationException => Results.Problem(statusCode: StatusCodes.Status400BadRequest, detail: exception.Message), + NotFoundException => Results.Problem(statusCode: StatusCodes.Status404NotFound, detail: exception.Message), + not null => Results.Problem(statusCode: StatusCodes.Status500InternalServerError, detail: exception.Message), + _ => Results.Problem(statusCode: StatusCodes.Status500InternalServerError, detail: "Generic error, contact system administrator") + }; + return problem.ExecuteAsync(context); + })); + + application.UseForwardedHeaders(new ForwardedHeadersOptions + { + ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto + }); + + application + .MapHealthChecks(Module.HealthcheckLabel) + .WithMetadata(new AllowAnonymousAttribute()); + + application + .UseAuthentication() + .UseAuthorization(); + + application + .MapEndpoints(); + + application.UseMiddleware(); + + return application; + } + + private static IServiceCollection AddInfrastructure( + this IServiceCollection services) + { + services + .AddPersistence(); + + + services + .AddPortaleFattureHealthChecks(); + + services.AddMediatR(x => x.RegisterServicesFromAssembly(typeof(RootInfrastructure).Assembly)); + + services.Configure(options => + { + options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + options.SerializerOptions.WriteIndented = true; + options.SerializerOptions.IncludeFields = true; + }); + + services.AddHttpClient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + var hostingEnvironment = services + .BuildServiceProvider() + .GetRequiredService(); + var rootPath = hostingEnvironment.ContentRootPath; + services.AddSingleton(new DocumentBuilder(rootPath)); + return services; + } + + private static IServiceCollection AddIdentities(this IServiceCollection services, IPortaleFattureOptions options) + { + JwtConfiguration jwtAuth = options.JWT!; + services + .AddScoped(_ => new JwtTokenService(jwtAuth)) + .AddScoped() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(new AesEncryption(jwtAuth.Secret!)); + + services + .AddAuthorization(); + + return services; + } + + private static IServiceCollection AddJwtOrApiKeyAuthentication(this IServiceCollection services, IPortaleFattureOptions foptions) + { + IdentityModelEventSource.ShowPII = true; + services + .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => options.JwtAuthenticationConfiguration(foptions.JWT!)); + + services.AddAuthorizationBuilder() + .AddPolicy(Module.SelfCarePolicy, policy => + policy + .RequireClaim(Module.SelfCarePolicyClaim, AuthType.SELFCARE) + .RequireClaim(Module.SelfCarePolicyProfiloClaim, + Profilo.PubblicaAmministrazione, + Profilo.GestorePubblicoServizio, + Profilo.SocietaControlloPubblico, + Profilo.PrestatoreServiziPagamento, + Profilo.AssicurazioniIVASS, + Profilo.StazioneAppaltanteANAC, + Profilo.PartnerTecnologico) + ) + .AddPolicy(Module.PagoPAPolicy, policy => + policy + .RequireClaim(Module.SelfCarePolicyClaim, AuthType.PAGOPA)) + .AddPolicy(Module.SelfCareRecapitistaPolicy, policy => + policy + .RequireClaim(Module.SelfCarePolicyClaim, AuthType.SELFCARE) + .RequireClaim(Module.SelfCarePolicyProfiloClaim, + Profilo.Recapitista) + ) + .AddPolicy(Module.SelfCareConsolidatorePolicy, policy => + policy + .RequireClaim(Module.SelfCarePolicyClaim, AuthType.SELFCARE) + .RequireClaim(Module.SelfCarePolicyProfiloClaim, + Profilo.Consolidatore) + ); + services.AddSingleton(); + return services; + } + + public static IServiceCollection AddPersistence(this IServiceCollection services) + { + var options = services + .BuildServiceProvider() + .GetRequiredService(); + + var dbConnectionString = options.ConnectionString ?? + throw new ConfigurationException("Db connection string not configured"); + + var fattureSchema = options.FattureSchema ?? + throw new ConfigurationException($"Db schema fatture not existent"); + + var selfCareSchema = options.SelfCareSchema ?? + throw new ConfigurationException($"Db schema fatture not existent"); + + services.AddSingleton(new DbContextFactory(dbConnectionString, selfCareSchema)); + services.AddSingleton(new DbContextFactory(dbConnectionString, fattureSchema)); + services.AddSingleton(); + + return services; + } + + private static IServiceCollection AddPortaleFattureHealthChecks( + this IServiceCollection services) + { + services + .AddHealthChecks(); + return services; + } + + + [DebuggerStepThrough] + private static RouteHandlerBuilder SetOpenApi(this RouteHandlerBuilder builder, string[] tags, string? name = null, + string? displayName = null, string? description = null, string? summary = null, string? securityPolicy = null, + params object[] metadata) + { + var result = builder + .WithOpenApi() + .RequireCors(Module.CORSLabel) + .WithTags(tags); + + if (securityPolicy is not null) + builder.RequireAuthorization(securityPolicy); + else + builder.RequireAuthorization(); + + if (name is not null) + result = result.WithSummary(name); + + if (displayName is not null) + result = result.WithName(displayName); + + if (description is not null) + result = result.WithDescription(description); + + if (summary is not null) + result = result.WithSummary(summary); + + if (metadata.Any()) + result = result.WithMetadata(metadata); + + return result; + } + + [DebuggerStepThrough] + public static RouteHandlerBuilder SetOpenApi(this RouteHandlerBuilder builder, string groupName, + string? name = null, + string? displayName = null, string? description = null, string? summary = null, string? securityPolicy = null, + params object[] metadata) + { + return builder + .SetOpenApi(new[] { groupName }, name, displayName, description, summary, + securityPolicy, metadata); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Culture/CultureConfiguration.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Culture/CultureConfiguration.cs new file mode 100644 index 0000000..99bb382 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Culture/CultureConfiguration.cs @@ -0,0 +1,23 @@ +using System.Globalization; + +namespace PortaleFatture.BE.Api.Infrastructure.Culture; + +public static class CultureConfiguration +{ + private static void SetCulture(string cultureName) + { + SetCulture(new CultureInfo(cultureName)); + } + + private static void SetCulture(CultureInfo culture) + { + CultureInfo.DefaultThreadCurrentCulture = culture; + CultureInfo.DefaultThreadCurrentUICulture = culture; + } + + public static WebApplication UseCulture(this WebApplication application, string defaultCulture = "it-IT") + { + SetCulture(defaultCulture); + return application; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DisposableFileStreamResult.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DisposableFileStreamResult.cs new file mode 100644 index 0000000..99f7255 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DisposableFileStreamResult.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Net.Http.Headers; + +namespace PortaleFatture.BE.Api.Infrastructure.Documenti; + +public sealed class DisposableStreamResult(Stream stream, string contentType) : FileStreamResult(stream, contentType) +{ + public override Task ExecuteResultAsync(ActionContext context) + { + return base.ExecuteResultAsync(context).ContinueWith(task => + { + if (stream == null) + return; + stream.Dispose(); + }); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DocsExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DocsExtensions.cs new file mode 100644 index 0000000..db18f37 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/DocsExtensions.cs @@ -0,0 +1,135 @@ +using System.Globalization; +using System.IO; +using CsvHelper; +using CsvHelper.Configuration; +using Microsoft.AspNetCore.Mvc; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; + +namespace PortaleFatture.BE.Api.Infrastructure.Documenti; + +public static class DocsExtensions +{ + private static readonly string _mimeCsv = "text/csv"; + private static readonly string _mimeExcel = "application/vnd.ms-excel"; + private static readonly CsvConfiguration _csvConfiguration = new(new CultureInfo("it-IT")) + { + Delimiter = ";", + HasHeaderRecord = true + }; + + public static async Task ToArray(this IEnumerable lista) where M : ClassMap + { + byte[]? data; + using (var stream = new MemoryStream()) + { + using (TextWriter textWriter = new StreamWriter(stream)) + { + using var csv = new CsvWriter(textWriter, _csvConfiguration); + csv.Context.RegisterClassMap(); + stream.Position = 0; + await csv.WriteRecordsAsync(lista!); + await textWriter.FlushAsync(); + await stream.FlushAsync(); + data = stream.ToArray(); + await csv.FlushAsync(); + } + } + return data; + } + public static async Task ToStream(this IEnumerable lista) where M : ClassMap + { + var stream = new MemoryStream(); + TextWriter textWriter = new StreamWriter(stream); + var csv = new CsvWriter(textWriter, _csvConfiguration); + csv.Context.RegisterClassMap(); + await csv.FlushAsync(); + await csv.WriteRecordsAsync(lista!); + await textWriter.FlushAsync(); + await stream.FlushAsync(); + stream.Seek(0, SeekOrigin.Begin); + return stream; + } + + private static async Task ToFile(this IEnumerable lista) where M : ClassMap + { + var filename = $"{Guid.NewGuid()}.csv"; + byte[] data; + using (var stream = new MemoryStream()) + { + using (TextWriter textWriter = new StreamWriter(stream)) + { + using var csv = new CsvWriter(textWriter, _csvConfiguration); + csv.Context.RegisterClassMap(); + stream.Position = 0; + await csv.WriteRecordsAsync(lista!); + await textWriter.FlushAsync(); + data = stream.ToArray(); + await csv.FlushAsync(); + } + await stream.FlushAsync(); + } + return Results.File(data!, _mimeCsv, filename, enableRangeProcessing: true); + } + public static void ForceGarbageCollection() + { + // Force a full collection of all generations + GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true, compacting: true); + + // Wait for pending finalizers to complete + GC.WaitForPendingFinalizers(); + + // Optionally, force another collection to reclaim objects that became unreachable due to finalizers + GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true, compacting: true); + } + public static async Task ToCsv(this IEnumerable lista) where M : ClassMap + { + return await ToFile(lista); + } + + public static async Task ToCsvv2(this IEnumerable lista) where M : ClassMap + { + var filename = $"{Guid.NewGuid()}.csv"; + var stream = new MemoryStream(); + + using (var textWriter = new StreamWriter(stream, leaveOpen: true)) + using (var csv = new CsvWriter(textWriter, _csvConfiguration)) + { + csv.Context.RegisterClassMap(); + await csv.WriteRecordsAsync(lista); + await textWriter.FlushAsync(); + } + + stream.Seek(0, SeekOrigin.Begin); + + return new FileStreamResult(stream, _mimeCsv) + { + FileDownloadName = filename + }; + } + + public static async Task ToExcel(this IEnumerable lista) + { + var filename = $"{Guid.NewGuid()}.xlsx"; + var dataSet = lista.FillOneSheet(); + byte[] data; + using (var stream = dataSet.ToExcel()) + { + data = stream.ToArray(); + await stream.FlushAsync(); + } + return Results.File(data!, _mimeExcel, filename); + } + + public static async Task ToExcelv2(this IEnumerable lista) + { + var filename = $"{Guid.NewGuid()}.xlsx"; + var dataSet = lista.FillOneSheetv2(); + byte[] data; + using (var stream = dataSet.ToExcel()) + { + data = stream.ToArray(); + await stream.FlushAsync(); + } + return Results.File(data!, _mimeExcel, filename); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/PRIMO_SALDO_rel.html b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/PRIMO_SALDO_rel.html new file mode 100644 index 0000000..98e3763 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/PRIMO_SALDO_rel.html @@ -0,0 +1,133 @@ + + + + + + + + + +

+ + +

+


+

+ + REGOLARE ESECUZIONE + +

+

+ Accordo di adesione alla Piattaforma per la notificazione degli atti della pubblica +

+

+ amministrazione di cui all'art. 26 del D.L. 76/2020 s.m.i. +

+


+

+ Amministrazione: [RagioneSociale]; +

+

+ Fornitore: PagoPA S.p.A.; +

+

+ Identificativo + Contratto: [IdContratto] +

+


+

+ VISTO  + + il report delle + prestazioni svolte con riguardo all'accordo di adesione alla piattaforma per la notificazione degli atti della + pubblica amministrazione di cui all'art. 26 del D.L. 76/2020 s.m.i. (di seguito, "Accordo") nel mese di [Mese] [Anno]   presente sul Portale Fatturazione, il quale riporta il numero di notifiche digitali e analogiche espletate, ivi incluse quelle che non hanno superato le verifiche di + conformità e/o annullate dopo la presa in carico; + +

+


+

+ ATTESA + + la veridicità, correttezza e completezza delle prestazioni svolte, come verificate e non + contestate dal Referente amministrativo sul Portale Fatturazione secondo le previsioni dell'Accordo e per l'effetto + accettate dall'Aderente, nei termini di cui al report scaricabile dall'apposita sezione presente sul + Portale; + +

+

+ RITENUTO di dover procedere al rilascio del presente documento, +

+


+

CERTIFICA

+


+

+ che il Fornitore ha regolarmente eseguito le prestazioni di cui all'Accordo in oggetto, così come dettagliate nel report, non + contestate dal Referente amministrativo sul Portale Fatturazione, e per l'effetto accettate dall'Aderente, e + che, pertanto, nulla osta alla fatturazione delle prestazioni ivi indicate per un totale fatturabile pari + ad [Totale] oltre IVA, così + determinato: +

+

+ - € [TotaleDigitale] per n. [TotaleNotificheDigitali] + notifiche digitali e € [TotaleAnalogico] per n. [TotaleNotificheAnalogiche] notifiche analogiche espletate. +

+

+ + Si richiede di riportare in fattura quanto già indicato in fase di inserimento dei dati sul + Portale Fatturazione (a titolo esemplificativo e non esaustivo: CUP, impegno di spesa, ecc.). + +

+

+ Si precisa che l'importo di cui sopra sarà compensato di eventuale importo già anticipato in + sede di fattura di anticipo e/o acconto, ove prevista. +

+


+


+ +

L'ADERENTE

+

+ + nella persona del referente amministrativo legittimato a firmare il presente + documento + +

+

_______________________________________

+


+

+


+

+ + + + + + + + + +
+

+ PagoPA S.p.A. +

+

+ società per azioni con socio unico +

+

+ capitale sociale di euro 1,000,000 interamente versato +

+

+ sede legale in Roma, Piazza Colonna 370, CAP 00187 +

+

+ n. di iscrizione a Registro Imprese di Roma, CF e P.IVA +

+

+ 15376371009 +

+
+ +
+ + \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/SECONDO_SALDO_rel.html b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/SECONDO_SALDO_rel.html new file mode 100644 index 0000000..7ba42d7 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/SECONDO_SALDO_rel.html @@ -0,0 +1,205 @@ + + + + + + + + + + +

+ + + +

+


+

+ + REGOLARE ESECUZIONE + +

+

+ Accordo di adesione alla Piattaforma per la notificazione degli atti della pubblica +

+

+ amministrazione di cui all'art. 26 del D.L. 76/2020 s.m.i. +

+


+

+ Amministrazione: [RagioneSociale]; +

+

+ Fornitore: PagoPA + S.p.A.; +

+

+ Identificativo + Contratto: [IdContratto] +

+


+

+ VISTO  + + il report delle + prestazioni svolte con riguardo all'accordo di adesione alla piattaforma per la notificazione degli atti + della + pubblica amministrazione di cui all'art. 26 del D.L. 76/2020 s.m.i. (di seguito, "Accordo") nel mese di + [Mese] + [Anno]   presente sul Portale Fatturazione, il quale + riporta il numero di notifiche digitali e analogiche espletate, ivi incluse quelle che non hanno superato le + verifiche di + conformità e/o annullate dopo la presa in carico; + +

+


+

+ CONSIDERATO + + che in data ____________ l'Aderente ha certificato, con apposita attestazione di + regolare esecuzione, la veridicità, correttezza e completezza di quota parte delle prestazioni + svolte, come verificate e non contestate dal Referente amministrativo sul Portale + Fatturazione secondo le previsioni dell'Accordo e per l'effetto accettate dall'Aderente; + +

+

+ VISTE + + le osservazioni riportate nel medesimo report delle prestazioni svolte presente sul + Portale Fatturazione, rispetto alle notifiche contestate dal Referente amministrativo; + +

+

+ ATTESA + + la veridicità, correttezza e completezza delle prestazioni svolte precedentemente + contestate, come verificate dal Referente amministrativo sul Portale Fatturazione secondo + le ulteriori previsioni dell'Accordo, nei termini di cui al citato report scaricabile dall'apposita + sezione presente sul Portale; + +

+

+ RITENUTO di + dover procedere al rilascio del presente documento, +

+


+

+ CERTIFICA +

+


+

+ che il Fornitore ha regolarmente eseguito le prestazioni di cui all'Accordo in oggetto, così come dettagliate + nel report, non + contestate dal Referente amministrativo sul Portale Fatturazione, e per l'effetto accettate dall'Aderente, e + che, pertanto, nulla osta alla fatturazione delle prestazioni ivi indicate per un totale fatturabile + pari + ad [Totale] oltre IVA, così + determinato: +

+

+ - € [TotaleDigitale] per n. [TotaleNotificheDigitali] + notifiche digitali e € [TotaleAnalogico] per n. [TotaleNotificheAnalogiche] notifiche analogiche espletate. +

+

+ + Si richiede di riportare in fattura quanto già indicato in fase di inserimento dei dati sul + Portale Fatturazione (a titolo esemplificativo e non esaustivo: CUP, impegno di spesa, ecc.). + +

+


+ +

+ L'ADERENTE

+

+ + nella persona del referente amministrativo legittimato a firmare il presente + documento + +

+

+ _______________________________________ +

+


+

+


+

+ + + + + + + + + +
+

+ PagoPA S.p.A. +

+

+ società per azioni con socio unico +

+

+ capitale sociale di euro 1,000,000 interamente versato +

+

+ sede legale in Roma, Piazza Colonna 370, CAP 00187 +

+

+ n. di iscrizione a Registro Imprese di Roma, CF e P.IVA +

+

+ 15376371009 +

+
+ + +
+ + + \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/daticommessa.html b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/daticommessa.html new file mode 100644 index 0000000..2551564 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Documenti/daticommessa.html @@ -0,0 +1,273 @@ + + + + + + Dati Commessa + + + + +
+ + + + + + + + + + + + + + [DatiModuloCommessa] + + + + + + + + [DatiModuloCommessaCosti] +
+ + + + +
+ PagoPA +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Soggetto Aderente (Ragione Sociale) + + [Descrizione] +
+ Sede Legale Completa + + [IndirizzoCompleto] +
+ Partita Iva/ Codice Fiscale + + [PartitaIva] +
+ Cup + + [Cup] +
+ Soggetto Split Payment + + [SplitPayment] +
+ Prodotto + + [Prodotto] +
+ PEC + + [Pec] +
+ Email Riferimento Contatti + + [Contatti] +
+ Data Di Compilazione + + [DataModifica] +
+ + + + +
+ Ai sensi dell'articolo 2 comma 5, l'Aderente predispone un ordinativo (Commessa) nei confronti della Società avente un arco temporale pari a un singolo mese solare: +
+ + + + + +
+ Mese di riferimento dell'ordinativo + + [MeseAttivita] +
+
Territorio nazionaleTerritorio diverso da nazionaleTotale notifiche da processare
+
+ + \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/IModule.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/IModule.cs new file mode 100644 index 0000000..f516329 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/IModule.cs @@ -0,0 +1,5 @@ +namespace PortaleFatture.BE.Api.Infrastructure; + +public interface IModule +{ +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/IRegistrableModule.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/IRegistrableModule.cs new file mode 100644 index 0000000..ad71f45 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/IRegistrableModule.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Infrastructure; + +public interface IRegistrableModule : IModule +{ + void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder); +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/MapAttribute.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/MapAttribute.cs new file mode 100644 index 0000000..593a3b6 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/MapAttribute.cs @@ -0,0 +1,24 @@ +namespace PortaleFatture.BE.Api.Infrastructure; + +[AttributeUsage(AttributeTargets.Method)] +public class MapAttribute : Attribute +{ + public MapAttribute(MapMethod method, string? route = null) + { + Method = method; + Route = route; + } + + public MapMethod Method { get; } + + public string? Route { get; } +} + +public enum MapMethod +{ + Get, + Post, + Put, + Delete, + Patch +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Module.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Module.cs new file mode 100644 index 0000000..f2d3514 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/Module.cs @@ -0,0 +1,33 @@ +namespace PortaleFatture.BE.Api.Infrastructure; + +public abstract class Module : IModule +{ + public static string DatiFatturazioneLabelPagoPA = "Dati Fatturazione PagoPA"; + public static string DatiFatturazioneLabel = "Dati Fatturazione"; + public static string DatiModuloCommessaLabelPagoPA = "Dati Modulo Commessa PagoPA"; + public static string DatiModuloCommessaLabel = "Dati Modulo Commessa"; + public static string DatiConfigurazioneModuloCommessaLabel = "Dati Configurazione Modulo Commessa"; + public static string DatiTipologiaLabel = "Dati Tipologie"; + public static string DatiNotificaLabel = "Dati Notifiche"; + public static string DatiFattureLabel = "Dati Fatture"; + public static string DatiRelLabel = "Dati Rel"; + public static string DatiRelLabelPagoPA = "Dati Rel PagoPA"; + public static string DatiNotificaLabelPagoPA = "Dati Notifiche PagoPA"; + public static string DatiNotificaLabelRecapitisti = "Dati Notifiche Recapitisti"; + public static string DatiNotificaLabelConsolidatori = "Dati Notifiche Consolidatori"; + public static string DatiAuthLabel = "Autenticazione"; + public static string DatiAsseverazioneLabelPagoPA = "Dati Asseverazione PagoPA"; + + public const string CORSLabel = "portalefatture"; + public const string GatewayLabel = "gateway"; + public const string HealthcheckLabel = "health"; + public const string LoggingLabel = "Logging"; + // + public const string SelfCareRecapitistaPolicy = "SelfCareRecapitistaPolicy"; + public const string SelfCareConsolidatorePolicy = "SelfCareConsolidatorePolicy"; + public const string SelfCarePolicy = "SelfCarePolicy"; + public const string PagoPAPolicy = "PagoPAPolicy"; + // + public const string SelfCarePolicyClaim = "auth"; + public const string SelfCarePolicyProfiloClaim = "profilo"; +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleExtensions.cs new file mode 100644 index 0000000..9dc7665 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleExtensions.cs @@ -0,0 +1,158 @@ +using System.Diagnostics; +using System.Reflection; +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; + +namespace PortaleFatture.BE.Api.Infrastructure; + +public static class ModuleExtensions +{ + public static async Task VaultClientSettings(this PortaleFattureOptions model) + { + model.JWT ??= new(); + model.AzureAd ??= new(); + model.Storage ??= new(); + + var selfCareUri = Environment.GetEnvironmentVariable("SELF_CARE_URI") ?? + throw new ConfigurationException("Please specify a SELF_CARE_URI!"); + + var selfCareCertEndpoint = Environment.GetEnvironmentVariable("SELFCARE_CERT_ENDPOINT") ?? + throw new ConfigurationException("Please specify a SELFCARE_CERT_ENDPOINT!"); + + var validAudience = Environment.GetEnvironmentVariable("JWT_VALID_AUDIENCE") ?? + throw new ConfigurationException("Please specify a JWT_VALID_AUDIENCE!"); + + var validIssuer = Environment.GetEnvironmentVariable("JWT_VALID_ISSUER") ?? + throw new ConfigurationException("Please specify a JWT_VALID_ISSUER!"); + + var connectionString = Environment.GetEnvironmentVariable("CONNECTION_STRING") ?? + throw new ConfigurationException("Please specify a CONNECTION_STRING!"); + + var secret = Environment.GetEnvironmentVariable("JWT_SECRET") ?? + throw new ConfigurationException("Please specify a JWT_VALID_ISSUER!"); + + var corsOrigins = Environment.GetEnvironmentVariable("CORS_ORIGINS") ?? + throw new ConfigurationException("Please specify a CORS_ORIGINS!"); + + var selfCareTimeOut = Environment.GetEnvironmentVariable("SELF_CARE_TIMEOUT") ?? + throw new ConfigurationException("Please specify a SELF_CARE_TIMEOUT!"); + + var selfCareAudience = Environment.GetEnvironmentVariable("SELF_CARE_AUDIENCE") ?? + throw new ConfigurationException("Please specify a SELF_CARE_AUDIENCE!"); + + var adminKey = Environment.GetEnvironmentVariable("ADMIN_KEY") ?? + throw new ConfigurationException("Please specify a ADMIN_KEY!"); + + var relFolder = Environment.GetEnvironmentVariable("STORAGE_REL_FOLDER") ?? + throw new ConfigurationException("Please specify a STORAGE_REL_FOLDER!"); + + var storageConnectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTIONSTRING") ?? + throw new ConfigurationException("Please specify a STORAGE_CONNECTIONSTRING!"); + + var applicationInsights = Environment.GetEnvironmentVariable("APPLICATION_INSIGHTS") ?? + throw new ConfigurationException("Please specify an APPLICATION_INSIGHTS!"); + var azureADInstance = Environment.GetEnvironmentVariable("AZUREAD_INSTANCE") ?? + throw new ConfigurationException("Please specify an AZUREAD_INSTANCE!"); + + var azureADTenantId = Environment.GetEnvironmentVariable("AZUREAD_TENANTID") ?? + throw new ConfigurationException("Please specify an AZUREAD_TENANTID!"); + + var azureADClientId = Environment.GetEnvironmentVariable("AZUREAD_CLIENTID") ?? + throw new ConfigurationException("Please specify an AZUREAD_CLIENTID!"); + + var azureADGroup = Environment.GetEnvironmentVariable("AZUREAD_ADGROUP") ?? + throw new ConfigurationException("Please specify an AZUREAD_ADGROUP!"); + + model.ConnectionString = connectionString; //await model.ConnectionString.Mapper(); + model.SelfCareUri = selfCareUri; + model.SelfCareCertEndpoint = selfCareCertEndpoint; + model.JWT.ValidAudience = validAudience; + model.JWT.Secret = secret; //await model.JWT.Secret.Mapper(); + model.JWT.ValidIssuer = validIssuer; + model.CORSOrigins = corsOrigins; + model.SelfCareTimeOut = selfCareTimeOut; + model.SelfCareAudience = selfCareAudience; + model.AdminKey = adminKey; + model.AzureAd.ClientId = azureADClientId; + model.AzureAd.TenantId = azureADTenantId; + model.AzureAd.Instance = azureADInstance; + model.AzureAd.AdGroup = azureADGroup; + model.Storage.RelFolder = relFolder; + model.Storage.ConnectionString = storageConnectionString; + + model.ApplicationInsights = applicationInsights; + return model; + } + + private static string _kvUri = "https://{0}.vault.azure.net"; + private static async Task Mapper(this string? secretName) + { + var keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME") ?? + throw new ConfigurationException("Please specify an KEY_VAULT_NAME!"); + + var kvUri = String.Format(_kvUri, keyVaultName); + var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential()) ?? + throw new ConfigurationException("Could not find any vault holy connected to KEY_VAULT_NAME!"); + + var secret = await client.GetSecretAsync(secretName); + return secret.Value.Value; + } + + public static IEndpointRouteBuilder Map(this IEndpointRouteBuilder app, Type moduleType) + { + if (app == null || moduleType == null) + throw new ConfigurationException("Please specify an IEndpointRouteBuilder OR Module Type!"); + + foreach (var method in moduleType.GetMethods(BindingFlags.Instance | BindingFlags.Public)) + { + app.Map(method, moduleType); + } + + return app; + } + + public static IEndpointConventionBuilder? Map(this IEndpointRouteBuilder app, MethodInfo method, Type moduleType, + string? routePrefix = null) + { + if (app == null || moduleType == null || method == null) + throw new ConfigurationException("Please specify an IEndpointRouteBuilder OR MethodInfo OR Module Type!"); + + var mapAttr = method.GetCustomAttribute(); + if (mapAttr is null) + { + return null; + } + + var route = mapAttr.Route ?? method.Name.ToLowerInvariant(); + if (!string.IsNullOrEmpty(routePrefix)) + { + route = $"{routePrefix}/{route}"; + } + + var options = new RequestDelegateFactoryOptions { ThrowOnBadRequest = true }; + var metaData = RequestDelegateFactory.InferMetadata(method, options); + var delegateResult = RequestDelegateFactory.Create(method, + ctx => ctx.RequestServices.GetRequiredService(moduleType), options, metaData); + return app.Map(mapAttr.Method, route, delegateResult.RequestDelegate); + } + + [DebuggerStepThrough] + public static IEndpointConventionBuilder Map(this IEndpointRouteBuilder app, MapMethod method, string route, + RequestDelegate mapDelegate) + { + if (app == null || mapDelegate == null) + throw new ConfigurationException("Please specify an IEndpointRouteBuilder OR Map RequestDelegate!"); + + return method switch + { + MapMethod.Get => app.MapGet(route, mapDelegate), + MapMethod.Post => app.MapPost(route, mapDelegate), + MapMethod.Put => app.MapPut(route, mapDelegate), + MapMethod.Delete => app.MapDelete(route, mapDelegate), + MapMethod.Patch => app.MapPatch(route, mapDelegate), + _ => throw new NotSupportedException($"Not supported MapMethod {method}") + }; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleManager.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleManager.cs new file mode 100644 index 0000000..a3f9871 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ModuleManager.cs @@ -0,0 +1,62 @@ +using System.Reflection; + +namespace PortaleFatture.BE.Api.Infrastructure; + +public class ModuleManager +{ + public HashSet Modules { get; } = new(); + + public void AddModule(Type type) + { + if(type is null) + throw new InvalidDataException($"{nameof(type)} is null"); + if (!type.IsSubclassOf(typeof(Module))) + throw new InvalidDataException($"{type.FullName} is not a module"); + + if (Modules.Contains(type)) + return; + + Modules.Add(type); + } + + public void AddModulesFromAssembly(Assembly assembly) + { + if (assembly is null) + throw new InvalidDataException($"{nameof(assembly)} is null"); + var moduleTypes = assembly + .GetTypes() + .Where(x => x.IsSubclassOf(typeof(Module))); + + foreach (var moduleType in moduleTypes) + AddModule(moduleType); + } + + public void RegisterModules(IServiceCollection serviceCollection) + { + if (serviceCollection is null) + throw new InvalidDataException($"{nameof(serviceCollection)} is null"); + + foreach (var module in Modules) + serviceCollection.AddScoped(module); + } + + public WebApplication MapEndpoints(WebApplication app) + { + if (app is null) + throw new InvalidDataException($"{nameof(app)} is null"); + using var scope = app.Services.CreateScope(); + + foreach (var moduleType in Modules) + { + if (moduleType.IsAssignableTo(typeof(IRegistrableModule))) + { + var module = (IRegistrableModule)scope.ServiceProvider.GetRequiredService(moduleType); + module.RegisterEndpoints(app); + continue; + } + app.Map(moduleType); + } + + return app; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/NonceMultiTabsMiddleware.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/NonceMultiTabsMiddleware.cs new file mode 100644 index 0000000..550d3b4 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/NonceMultiTabsMiddleware.cs @@ -0,0 +1,38 @@ +using PortaleFatture.BE.Api.Modules.Auth.Extensions; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Gateway; + +namespace PortaleFatture.BE.Api.Infrastructure; + +public class NonceMultiTabsMiddleware(RequestDelegate next, IAesEncryption encryption) +{ + private readonly RequestDelegate _next = next; + private readonly IAesEncryption? _encryption = encryption; + private static readonly Dictionary _whitelist = new() + { + { "/favicon.ico", "/favicon.ico" }, + { "/", "/" }, + { "/health", "/health" }, + { "/api/auth/pagopa/login", "/api/auth/pagopa/login" }, + { "/api/auth/profilo", "/api/auth/profilo" }, + { "/api/auth/selfcare/login", "/api/auth/selfcare/login" } + }; + public async Task InvokeAsync(HttpContext context) + { + var url = context.Request.Path; + var isInWhitelist = _whitelist.TryGetValue(url, out var value); + if (!isInWhitelist) + { + var authInfo = context.GetAuthInfo(); + var nonce = context.Request.Query["nonce"]; + if (string.IsNullOrWhiteSpace(nonce)) + throw new SessionException("Session expired!"); + var decryptedNonce = _encryption!.DecryptString(nonce!); + var verify = authInfo.Verify(decryptedNonce!); + if (!verify) + throw new SessionException("Session expired!"); + } + await _next(context); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneEndpoints.cs new file mode 100644 index 0000000..844730c --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneEndpoints.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.Asseverazione; + +public partial class AsseverazioneModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + endpointRouteBuilder + .MapPost("api/asseverazione", PostAsseverazioneAsync) + .WithName("Permette di visualizzare il log asseverazione") + .SetOpenApi(Module.DatiAsseverazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/asseverazione/documento", PostAsseverazioneDocumentoAsync) + .WithName("Permette di visualizzare il documento log asseverazione") + .SetOpenApi(Module.DatiAsseverazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/asseverazione/export", PostAsseverazioneExportDocumentoAsync) + .WithName("Permette di visualizzare il documento export asseverazione") + .SetOpenApi(Module.DatiAsseverazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + + endpointRouteBuilder + .MapPost("api/asseverazione/upload/", PostUploadAsync) + .WithName("Permette caricare il file import excel") + .SetOpenApi(Module.DatiAsseverazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneModule.cs new file mode 100644 index 0000000..69da275 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/AsseverazioneModule.cs @@ -0,0 +1,177 @@ +using System.Data; +using System.Globalization; +using CsvHelper; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Modules.Asseverazione.Extensions; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using static Microsoft.AspNetCore.Http.TypedResults; + + +namespace PortaleFatture.BE.Api.Modules.Asseverazione; + +public partial class AsseverazioneModule +{ + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> PostUploadAsync( + HttpContext context, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer) + { + var form = await context.Request.ReadFormAsync(); + var file = form.Files.Where(s => s.Name != "file" || s.Name != "xlsx").FirstOrDefault() ?? + throw new Core.Exceptions.ValidationException("Estensione sbagliata. Passare un xlsx valido."); + var authInfo = context.GetAuthInfo(); + var size = file!.Length; + if (size > 0) + { + var fileName = file.FileName; + var extension = Path.GetExtension(fileName); + if (extension != ".xlsx") + throw new Core.Exceptions.ValidationException("Estensione sbagliata. Passare un xlsx valido."); + + using var memoryStream = new MemoryStream(); + { + await file.CopyToAsync(memoryStream); + var dt = memoryStream.ReadAsseverazioneExcel(); + return Ok(await handler.Send(dt.Mapper(authInfo))); + } + } + return Ok(false); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PostAsseverazioneAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var asseverazione = await handler.Send(new AsseverazioneQueryGet(authInfo)); + if (asseverazione!.IsNullNotAny()) + return NotFound(); + return Ok(asseverazione); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PostAsseverazioneExportDocumentoAsync( + HttpContext context, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var asseverazione = await handler.Send(new AsseverazioneQueryGet(authInfo)); + if (asseverazione!.IsNullNotAny()) + return NotFound(); + + var export = asseverazione!.Select(x => x.Mapper()); + + if (binary == null) + { + var dataSet = export!.FillOneSheetv2(); + var content = dataSet.ToExcelData(); + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + } + else if (binary == true) + { + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + var dataSet = export!.FillOneSheetv2(); + var content = dataSet.ToExcelData(); + return Results.File(content!, mime, filename); + } + else + { + var mime = "text/csv"; + var filename = $"{Guid.NewGuid()}.csv"; + byte[] data; + using (var stream = new MemoryStream()) + using (TextWriter textWriter = new StreamWriter(stream)) + using (var csv = new CsvWriter(textWriter, new CultureInfo("it-IT"))) + { + csv.WriteRecords(export!); + textWriter.Flush(); + data = stream.ToArray(); + } + return Results.File(data!, mime, filename); + } + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PostAsseverazioneDocumentoAsync( + HttpContext context, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var asseverazione = await handler.Send(new AsseverazioneQueryGet(authInfo)); + if (asseverazione!.IsNullNotAny()) + return NotFound(); + + if (binary == null) + { + var dataSet = asseverazione!.FillOneSheetv2(); + var content = dataSet.ToExcel(); + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + } + else if (binary == true) + { + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + var dataSet = asseverazione!.FillOneSheetv2(); + var content = dataSet.ToExcel(); + return Results.File(content!, mime, filename); + } + else + { + var mime = "text/csv"; + var filename = $"{Guid.NewGuid()}.csv"; + byte[] data; + using (var stream = new MemoryStream()) + using (TextWriter textWriter = new StreamWriter(stream)) + using (var csv = new CsvWriter(textWriter, new CultureInfo("it-IT"))) + { + csv.WriteRecords(asseverazione!); + textWriter.Flush(); + data = stream.ToArray(); + } + return Results.File(data!, mime, filename); + } + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Extensions/AsseverazioneExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Extensions/AsseverazioneExtensions.cs new file mode 100644 index 0000000..2f139e4 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Extensions/AsseverazioneExtensions.cs @@ -0,0 +1,22 @@ +using PortaleFatture.BE.Api.Modules.Asseverazione.Payload.Response; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Asseverazione.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; + +namespace PortaleFatture.BE.Api.Modules.Asseverazione.Extensions; +public static class AsseverazioneExtensions +{ + public static AsseverazionExportResponse Mapper(this EnteAsserverazioneDto model) + { + + return new AsseverazionExportResponse + { + DataAsseverazione = model.DataAsseverazione, + Asseverazione = model.Asseverazione, + IdEnte = model.IdEnte, + RagioneSociale = model.RagioneSociale, + Descrizione = model.Descrizione + }; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Payload/Response/AsseverazionExportResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Payload/Response/AsseverazionExportResponse.cs new file mode 100644 index 0000000..23fec55 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Asseverazione/Payload/Response/AsseverazionExportResponse.cs @@ -0,0 +1,45 @@ +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Api.Modules.Asseverazione.Payload.Response; + +public class AsseverazionExportResponse +{ + [Column("internalistitutionid")] + [HeaderAttributev2(caption: "Id Ente", Order = 1)] + public string? IdEnte { get; set; } + + [Column("description")] + [HeaderAttributev2(caption: "Ragione Sociale", Order = 2)] + public string? RagioneSociale { get; set; } + + [Column("Asseverazione")] + public bool? Asseverazione { get; set; } + + [Column("data_asseverazione")] + [HeaderAttributev2(caption: "Data Adesione al Bando", Order = 12)] + public DateTime? DataAsseverazione { get; set; } + + [HeaderAttributev2(caption: "Adessione al Bando", Order = 13)] + public string? TipoAsseverazione + { + get + { + if (Asseverazione.HasValue) + { + if (Asseverazione.Value) + { + return "SI"; + } + else + { + return "NO"; + } + } + else + return string.Empty; + } + } + [HeaderAttributev2(caption: "Descrizione", Order = 14)] + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthEndpoints.cs new file mode 100644 index 0000000..751e9e9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthEndpoints.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.Auth; + +public partial class AuthModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + endpointRouteBuilder + .MapGet("api/auth/selfcare/login", LoginSelfCareAsync) + .WithName("Permette di autenticare un utente selfcare.") + .SetOpenApi(Module.DatiAuthLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/auth/profilo", ProfiloAsync) + .WithName("Permette di verificare un utente selfcare.") + .SetOpenApi(Module.DatiAuthLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/auth/pagopa/login", LoginPagoPAAsync) + .WithName("Permette di verificare il autenticare un utente pagoPA.") + .SetOpenApi(Module.DatiAuthLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthModule.cs new file mode 100644 index 0000000..7e061c9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/AuthModule.cs @@ -0,0 +1,91 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Modules.Auth.Extensions; +using PortaleFatture.BE.Api.Modules.Auth.Payload; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Utenti.Commands; +using PortaleFatture.BE.Infrastructure.Gateway; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.Auth; + +public partial class AuthModule : Module, IRegistrableModule +{ + [AllowAnonymous] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> LoginSelfCareAsync( + HttpContext context, + [FromQuery] string? selfcareToken, + [FromServices] IIdentityUsersService usersService, + [FromServices] IProfileService profileService, + [FromServices] ITokenService tokensService, + [FromServices] IAesEncryption encryption, + [FromServices] IStringLocalizer localizer) + { + var authInfos = await profileService.GetSelfCareInfo(selfcareToken); + return Ok(authInfos!.MapperSelfCare(usersService, tokensService, encryption)); + + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> ProfiloAsync( + HttpContext context, + [FromServices] IIdentityUsersService usersService, + [FromServices] ITokenService tokensService, + [FromServices] IAesEncryption encryption, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + UtenteCreateCommand? command; + if (authInfo.Auth == AuthType.PAGOPA) + command = new UtenteCreateCommand(new AuthenticationInfo() + { + Id = authInfo!.Id, + IdEnte = string.Empty + }); + else + command = new UtenteCreateCommand(authInfo); + var modulo = await handler.Send(command!) ?? throw new DomainException(localizer["UtenteProfiloError"]); + return Ok(authInfo.MapperSelfCare(modulo.DataPrimo, modulo.DataUltimo, encryption)); + } + + [AllowAnonymous] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> LoginPagoPAAsync( + HttpContext context, + [FromBody] PagoPaLoginRequest request, + [FromServices] IProfileService profileService, + [FromServices] IAesEncryption encryption, + [FromServices] IMediator handler, + [FromServices] ITokenService tokensService, + [FromServices] IIdentityUsersService usersService, + [FromServices] IStringLocalizer localizer) + { + var authInfo = await profileService.GetPagoPAInfo(request.IdToken, request.AccessToken)!; + return Ok(authInfo!.MapperPagoPA(usersService, tokensService, encryption)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/AuthExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/AuthExtensions.cs new file mode 100644 index 0000000..9523144 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/AuthExtensions.cs @@ -0,0 +1,133 @@ +using System.Web; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Gateway; + +namespace PortaleFatture.BE.Api.Modules.Auth.Extensions; + +public static class AuthExtensions +{ + public static UtenteInfo MapperSelfCare( + this AuthenticationInfo info, + DateTime dataPrimo, + DateTime dataUltimo, + IAesEncryption encryption) + { + return new UtenteInfo() + { + DescrizioneRuolo = info.DescrizioneRuolo, + Email = info.Email, + Id = info.Id, + IdEnte = info.IdEnte, + IdTipoContratto = info.IdTipoContratto, + NomeEnte = info.NomeEnte, + Prodotto = info.Prodotto, + Profilo = info.Profilo, + Ruolo = info.Ruolo, + DataPrimo = dataPrimo, + DataUltimo = dataUltimo, + Nonce = encryption.EncryptString(info.CreateNonce()), + GruppoRuolo = info.GruppoRuolo, + Auth = info.Auth + }; + } + + public static ProfileInfo MapperPagoPA( + this AuthenticationInfo authInfo, + IIdentityUsersService usersService, + ITokenService tokensService, + IAesEncryption encryption) + { + + var listAuthClaims = usersService.GetUserClaimsFromPagoPAUserAsync(authInfo); + var tokenProfileInfo = tokensService.GenerateJwtToken(listAuthClaims); + return new ProfileInfo() + { + DescrizioneRuolo = authInfo.DescrizioneRuolo, + Email = authInfo.Email, + Id = authInfo.Id, + IdEnte = authInfo.IdEnte, + IdTipoContratto = authInfo.IdTipoContratto, + NomeEnte = authInfo.NomeEnte, + Prodotto = authInfo.Prodotto, + Profilo = authInfo.Profilo, + Ruolo = authInfo.Ruolo, + Nonce = encryption.EncryptString(authInfo.CreateNonce()), + JWT = tokenProfileInfo.JWT, + Valido = tokenProfileInfo.Valido, + GruppoRuolo = authInfo.GruppoRuolo, + Auth = authInfo.Auth + }; + } + + public static List MapperSelfCare( + this List infos, + IIdentityUsersService usersService, + ITokenService tokensService, + IAesEncryption encryption) + { + List profiles = []; + + foreach (var authInfo in infos) + { + var listAuthClaims = usersService.GetUserClaimsFromSelfCareUserAsync(authInfo); + var tokenProfileInfo = tokensService.GenerateJwtToken(listAuthClaims); + var profile = new ProfileInfo() + { + DescrizioneRuolo = authInfo.DescrizioneRuolo, + Email = authInfo.Email, + Id = authInfo.Id, + IdEnte = authInfo.IdEnte, + IdTipoContratto = authInfo.IdTipoContratto, + NomeEnte = authInfo.NomeEnte, + Prodotto = authInfo.Prodotto, + Profilo = authInfo.Profilo, + Ruolo = authInfo.Ruolo, + Nonce = encryption.EncryptString(authInfo.CreateNonce()), + JWT = tokenProfileInfo.JWT, + Valido = tokenProfileInfo.Valido, + GruppoRuolo = authInfo.GruppoRuolo, + Auth = authInfo.Auth + }; + profiles.Add(profile); + } + return profiles; + } + + private const string _separator = "|"; + private static string CreateNonce(this AuthenticationInfo authInfo) + { + return (new NonceDto() + { + Id = authInfo.Id, + IdEnte = authInfo.IdEnte ?? string.Empty, + Prodotto = authInfo.Prodotto ?? string.Empty, + }).Serialize(); + } + + private static AuthenticationInfo ReadNonce(this string nonce) + { + var value = nonce.Deserialize(); + return new AuthenticationInfo() + { + Id = value.Id, + IdEnte = value.IdEnte, + Prodotto = value.Prodotto + }; + } + + public static bool Verify(this AuthenticationInfo authInfo, string decryptedNonce) + { + var checkInfo = decryptedNonce.ReadNonce(); + return authInfo.Id == checkInfo.Id && AreEqual(authInfo.IdEnte, checkInfo.IdEnte) && AreEqual(authInfo.Prodotto, checkInfo.Prodotto); + } + + private static bool AreEqual(string? a, string? b) + { + if (string.IsNullOrEmpty(a)) + return string.IsNullOrEmpty(b); + else + return string.Equals(a, b); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/NonceDto.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/NonceDto.cs new file mode 100644 index 0000000..dfa3abe --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Extensions/NonceDto.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Api.Modules.Auth.Extensions; + +public sealed class NonceDto +{ + public string? Id { get; set; } + public string? IdEnte { get; set; } + public string? Prodotto { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Payload/PagoPaLoginRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Payload/PagoPaLoginRequest.cs new file mode 100644 index 0000000..3f50293 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Auth/Payload/PagoPaLoginRequest.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; + +namespace PortaleFatture.BE.Api.Modules.Auth.Payload; + +public class PagoPaLoginRequest +{ + [JsonPropertyName("token_type")] + public string? TokenType { get; set; } + + [JsonPropertyName("scope")] + public string? Scope { get; set; } + + [JsonPropertyName("expires_in")] + public int ExpiresIn { get; set; } + + [JsonPropertyName("ext_expires_in")] + public int ExtExpiresIn { get; set; } + + [JsonPropertyName("access_token")] + public string? AccessToken { get; set; } + + [JsonPropertyName("refresh_token")] + public string? RefreshToken { get; set; } + + [JsonPropertyName("id_token")] + public string? IdToken { get; set; } + + [JsonPropertyName("client_info")] + public string? ClientInfo { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaEndpoints.cs new file mode 100644 index 0000000..5d42c7a --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaEndpoints.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse; + +public partial class DatiConfigurazioneModuloCommessaModule : Module, IRegistrableModule +{ + + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + + + endpointRouteBuilder + .MapGet("api/configurazionemodulocommessa", GetDatiConfigurazioneModuloCommessaAsync) + .WithName("Permette di ottenere i dati relativi alla configurazione modulo commessa.") + .SetOpenApi(Module.DatiConfigurazioneModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/configurazionemodulocommessa", CreateDatiConfigurazioneModuloCommessaAsync) + .WithName("Permette di ottenere creare/aggiornare i dati relativi alla configurazione modulo commessa.") + .SetOpenApi(Module.DatiConfigurazioneModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaModule.cs new file mode 100644 index 0000000..7d5186d --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/DatiConfigurazioneModuloCommessaModule.cs @@ -0,0 +1,64 @@ +using System.Security; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Extensions; +using PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Request; +using PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Response; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse; + +public partial class DatiConfigurazioneModuloCommessaModule +{ + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetDatiConfigurazioneModuloCommessaAsync( + HttpContext context, + [FromQuery] int idTipoContratto, + [FromQuery] string prodotto, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var configurazione = await handler.Send(new DatiConfigurazioneModuloCommessaQueryGet() { Prodotto = prodotto, IdTipoContratto = idTipoContratto }); + if (configurazione == null) + throw new NotFoundException(localizer["DatiConfigurazioneModuloCommessaMissing"]); + return Ok(configurazione.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> CreateDatiConfigurazioneModuloCommessaAsync( + HttpContext context, + [FromBody] DatiConfigurazioneModuloCommessaCreateRequest req, + [FromQuery] string? adminKey, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler, + [FromServices] IPortaleFattureOptions options) + { + if (options.AdminKey != adminKey) + throw new SecurityException(); + var command = req.Mapper() ?? throw new ValidationException(localizer["DatiConfigurazioneModuloCommessaInvalid"]); + var configurazione = await handler.Send(command); + return configurazione == null + ? throw new DomainException(localizer["DatiConfigurazioneModuloCommessaError"]) + : (Results, NotFound>)Ok(configurazione.Mapper()); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Extensions/DatiConfigurazioneModuloCommessaExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Extensions/DatiConfigurazioneModuloCommessaExtensions.cs new file mode 100644 index 0000000..c080b86 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Extensions/DatiConfigurazioneModuloCommessaExtensions.cs @@ -0,0 +1,71 @@ +using PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Request; +using PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Response; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +namespace PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Extensions; + +public static class DatiConfigurazioneModuloCommessaExtensions +{ + public static DatiConfigurazioneModuloCommessaCreateCommand? Mapper(this DatiConfigurazioneModuloCommessaCreateRequest model) + { + try + { + var idTipoContratto = model.IdTipoContratto; + var prodotto = model.Prodotto; + var tipi = model.Tipi; + var categorie = model.Categorie; + + return new() + { + Tipi = tipi!.Select(x => new DatiConfigurazioneModuloCommessaCreateTipoCommand() + { + IdTipoContratto = idTipoContratto, + Prodotto = prodotto, + MediaNotificaInternazionale = x.PrezzoMedioNotificaInternazionale, + MediaNotificaNazionale = x.PrezzoMedioNotificaNazionale, + IdTipoSpedizione = x.IdTipoSpedizione + }).ToList(), + Categorie = categorie!.Select(x => new DatiConfigurazioneModuloCommessaCreateCategoriaCommand() + { + IdTipoContratto = idTipoContratto, + Prodotto = prodotto, + Percentuale = x.Percentuale, + IdCategoriaSpedizione = x.IdCategoriaSpedizione + }).ToList(), + }; + } + catch + { + return null; + } + } + + public static DatiConfigurazioneModuloCommessaResponse Mapper(this DatiConfigurazioneModuloCommessa model) + { + return new() + { + Tipi = model.Tipi!.Select(x => x.Mapper()), + Categorie = model.Categorie!.Select(x => x.Mapper()), + }; + } + + public static DatiConfigurazioneModuloCategoriaCommessaResponse Mapper(this DatiConfigurazioneModuloCategoriaCommessa model) => + new() + { + Descrizione = model.Descrizione!.Replace("[percent]", model.Percentuale.ToString()), + IdCategoriaSpedizione = model.IdCategoriaSpedizione, + Percentuale = model.Percentuale + }; + + public static DatiConfigurazioneModuloTipoCommessaResponse Mapper(this DatiConfigurazioneModuloTipoCommessa model) => + new() + { + Descrizione = model.Descrizione, + MediaNotificaInternazionale = model.MediaNotificaInternazionale, + MediaNotificaNazionale = model.MediaNotificaNazionale, + IdTipoSpedizione = model.IdTipoSpedizione + }; +} + + diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Request/DatiConfigurazioneModuloCommessaCreateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Request/DatiConfigurazioneModuloCommessaCreateRequest.cs new file mode 100644 index 0000000..d6e5852 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Request/DatiConfigurazioneModuloCommessaCreateRequest.cs @@ -0,0 +1,36 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Request; + +public record DatiConfigurazioneModuloCommessaCreateRequest +{ + [Required] + public int IdTipoContratto { get; set; } + + [Required] + public string? Prodotto { get; set; } + + public List? Categorie { get; set; } + public List? Tipi { get; set; } +} + +public record DatiConfigurazioneModuloCommessaCreateCategoriaRequest +{ + [Required] + public int IdCategoriaSpedizione { get; set; } + + [Required] + public int Percentuale { get; set; } +} + +public record DatiConfigurazioneModuloCommessaCreateTipoSpedizioneRequest +{ + [Required] + public int IdTipoSpedizione { get; set; } + + [Required] + public decimal PrezzoMedioNotificaNazionale { get; set; } + + [Required] + public decimal PrezzoMedioNotificaInternazionale { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Response/DatiConfigurazioneModuloCommessaResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Response/DatiConfigurazioneModuloCommessaResponse.cs new file mode 100644 index 0000000..f30d2d9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiConfigurazioneModuloCommesse/Response/DatiConfigurazioneModuloCommessaResponse.cs @@ -0,0 +1,22 @@ +namespace PortaleFatture.BE.Api.Modules.DatiConfigurazioneModuloCommesse.Response; + +public record DatiConfigurazioneModuloCommessaResponse +{ + public IEnumerable? Categorie { get; set; } + public IEnumerable? Tipi { get; set; } +} + +public record DatiConfigurazioneModuloCategoriaCommessaResponse +{ + public int IdCategoriaSpedizione { get; set; } + public int Percentuale { get; set; } + public string? Descrizione { get; set; } +} + +public record DatiConfigurazioneModuloTipoCommessaResponse +{ + public int IdTipoSpedizione { get; set; } + public decimal MediaNotificaNazionale { get; set; } + public decimal MediaNotificaInternazionale { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneEndpoints.cs new file mode 100644 index 0000000..a1ee3e8 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneEndpoints.cs @@ -0,0 +1,61 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni; + +partial class DatiFatturazioneModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + #region PagoPA + endpointRouteBuilder + .MapPost("api/datifatturazione/pagopa/documento/ricerca", PagoPADatiFatturazioneByDescrizioneDocumentAsync) + .WithName("Permette di ottenere il file excel per la fatturazione enti per ricerca descrizione via utente PagoPA") + .SetOpenApi(Module.DatiFatturazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/datifatturazione/pagopa/ricerca", PagoPADatiFatturazioneByDescrizioneAsync) + .WithName("Permette di ottenere i dati fatturazione enti per ricerca descrizione via utente PagoPA") + .SetOpenApi(Module.DatiFatturazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/datifatturazione/pagopa", CreatePagoPaDatiFatturazioneAsync) + .WithName("Permette di salvare i dati fatturazione via utente PagoPA.") + .SetOpenApi(Module.DatiFatturazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/datifatturazione/pagopa/ente", GetPagoPADatiFatturazioneByIdEnteAsync) + .WithName("Permette di recuperare i dati fatturazione per id ente via utente PagoPA.") + .SetOpenApi(Module.DatiFatturazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPut("api/datifatturazione/pagopa", UpdatePagoPADatiFatturazioneAsync) + .WithName("Permette di modificare i dati di fatturazione via utente PagoPA.") + .SetOpenApi(Module.DatiFatturazioneLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + #endregion + + endpointRouteBuilder + .MapPost("api/datifatturazione", CreateDatiFatturazioneAsync) + .WithName("Permette di salvare i dati di fatturazione.") + .SetOpenApi(Module.DatiFatturazioneLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPut("api/datifatturazione", UpdateDatiFatturazioneAsync) + .WithName("Permette di modificare i dati di fatturazione.") + .SetOpenApi(Module.DatiFatturazioneLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/datifatturazione/ente", GetDatiFatturazioneByIdEnteAsync) + .WithName("Permette di recuperare il dato relativo ai dati fatturazione per id ente.") + .SetOpenApi(Module.DatiFatturazioneLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneModule.cs new file mode 100644 index 0000000..8e0bfe2 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/DatiFatturazioneModule.cs @@ -0,0 +1,193 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Modules.Asseverazione.Extensions; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Extensions; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; +using PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni; + +public partial class DatiFatturazioneModule +{ + #region PAGOPA + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PagoPADatiFatturazioneByDescrizioneDocumentAsync( + HttpContext context, + [FromBody] EnteRicercaByDescrizioneProfiloRequest request, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var fatturazione = await handler.Send(new DatiFatturazioneQueryGetByDescrizione(authInfo, request.IdEnti!, + request.Prodotto, + request.Profilo, + null)); + if (fatturazione == null || !fatturazione.Any()) + return NotFound(); + + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + + var dataSet = fatturazione.FillOneSheet(); + var content = dataSet.ToExcel(); + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + else + return Results.File(content!, mime, filename); + + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PagoPADatiFatturazioneByDescrizioneAsync( + HttpContext context, + [FromBody] EnteRicercaByDescrizioneProfiloRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var fatturazione = await handler.Send(new DatiFatturazioneQueryGetByDescrizione(authInfo, request.IdEnti!, + request.Prodotto, + request.Profilo, + null)); + if (fatturazione == null || !fatturazione.Any()) + return NotFound(); + + return Ok(fatturazione); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, BadRequest>> CreatePagoPaDatiFatturazioneAsync( + HttpContext context, + [FromBody] DatiFatturazionePagoPACreateRequest req, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = req.Mapper(authInfo!); + var createdDatiFatturazione = await handler.Send(command); + return Ok(createdDatiFatturazione.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, BadRequest, NotFound>> GetPagoPADatiFatturazioneByIdEnteAsync( + HttpContext context, + [FromQuery] string? idente, + [FromQuery] string? prodotto, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + authInfo.IdEnte = idente; + authInfo.Prodotto = prodotto; + var datiCommessa = await handler.Send(new DatiFatturazioneQueryGetByIdEnte(authInfo)); + if (datiCommessa == null) + return NotFound(); + return Ok(datiCommessa!.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, BadRequest>> UpdatePagoPADatiFatturazioneAsync( + HttpContext context, + [FromBody] DatiFatturazionePagoPAUpdateRequest req, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = req.Mapper(authInfo); + var updatedDatiFatturazione = await handler.Send(command); + return Ok(updatedDatiFatturazione.Mapper()); + } + + #endregion PAGOPA + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, BadRequest>> CreateDatiFatturazioneAsync( + HttpContext context, + [FromBody] DatiFatturazioneCreateRequest req, + [FromQuery] string? idente, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = req.Mapper(authInfo!); + var createdDatiFatturazione = await handler.Send(command); + return Ok(createdDatiFatturazione.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, BadRequest>> UpdateDatiFatturazioneAsync( + HttpContext context, + [FromBody] DatiFatturazioneUpdateRequest req, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = req.Mapper(authInfo); + var updatedDatiFatturazione = await handler.Send(command); + return Ok(updatedDatiFatturazione.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, BadRequest, NotFound>> GetDatiFatturazioneByIdEnteAsync( + HttpContext context, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var datiCommessa = await handler.Send(new DatiFatturazioneQueryGetByIdEnte(authInfo)); + if (datiCommessa == null) + return NotFound(); + return Ok(datiCommessa!.Mapper()); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Extensions/DatiFatturazioneExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Extensions/DatiFatturazioneExtensions.cs new file mode 100644 index 0000000..fee8fb4 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Extensions/DatiFatturazioneExtensions.cs @@ -0,0 +1,194 @@ +using System.Text; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiFatturazioni; +using PortaleFatture.BE.Core.Entities.Tipologie; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Dto; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Extensions; +public static class DatiFatturazioneExtensions +{ + public static byte[] ToCsv(this IEnumerable dati) + { + var csv = new StringBuilder(); + foreach (var d in dati) + { + var newLine = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}", d.RagioneSociale, d.Prodotto, d.Profilo, d.Cup, d.CodCommessa, d.IdDocumento, d.DataDocumento, d.SplitPayment, d.Pec, d.NotaLegale, d.DataCreazione, d.DataModifica); + csv.AppendLine(newLine); + } + return Encoding.ASCII.GetBytes(csv.ToString()); + } + + public static string GenerateFakeIdEnte() + { + return Guid.NewGuid().ToString(); + } + + public static DatiFatturazioneContattoCreateCommand Mapper(this DatiFatturazioneContattoCreateRequest model) => + new() + { + Email = model.Email + }; + + public static DatiFatturazioneCreateCommand Mapper(this DatiFatturazionePagoPACreateRequest model, AuthenticationInfo authInfo) + { + authInfo.Prodotto = model.Prodotto; + authInfo.IdEnte = model.IdEnte; + return new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = model.NotaLegale, + CodCommessa = model.CodCommessa, + Cup = model.Cup, + DataDocumento = model.DataDocumento, + SplitPayment = model.SplitPayment, + IdDocumento = model.IdDocumento, + Map = model.Map, + Contatti = model.Contatti?.Select(x => x.Mapper()).ToList(), + Pec = model.Pec, + TipoCommessa = model.TipoCommessa + }; + } + + public static DatiFatturazioneCreateCommand Mapper(this DatiFatturazioneCreateRequest model, AuthenticationInfo authInfo) => + new(authInfo) + { + NotaLegale = model.NotaLegale, + CodCommessa = model.CodCommessa, + Cup = model.Cup, + DataDocumento = model.DataDocumento, + SplitPayment = model.SplitPayment, + IdDocumento = model.IdDocumento, + Map = model.Map, + Contatti = model.Contatti?.Select(x => x.Mapper()).ToList(), + Pec = model.Pec, + TipoCommessa = model.TipoCommessa + }; + + public static DatiFatturazioneUpdateCommand Mapper(this DatiFatturazionePagoPAUpdateRequest model, AuthenticationInfo authInfo) + { + authInfo.Prodotto = model.Prodotto; + authInfo.IdEnte = model.IdEnte; + return new(authInfo) + { + Id = model.Id, + NotaLegale = model.NotaLegale, + CodCommessa = model.CodCommessa, + Cup = model.Cup, + DataDocumento = model.DataDocumento, + SplitPayment = model.SplitPayment, + IdDocumento = model.IdDocumento, + Map = model.Map, + Contatti = model.Contatti?.Select(x => x.Mapper()).ToList(), + Pec = model.Pec, + TipoCommessa = model.TipoCommessa, + }; + + } + + public static DatiFatturazioneUpdateCommand Mapper(this DatiFatturazioneUpdateRequest model, AuthenticationInfo authInfo) => + new(authInfo) + { + Id = model.Id, + NotaLegale = model.NotaLegale, + CodCommessa = model.CodCommessa, + Cup = model.Cup, + DataDocumento = model.DataDocumento, + SplitPayment = model.SplitPayment, + IdDocumento = model.IdDocumento, + Map = model.Map, + Contatti = model.Contatti?.Select(x => x.Mapper()).ToList(), + Pec = model.Pec, + TipoCommessa = model.TipoCommessa, + }; + + public static DatiFatturazioneContattoResponse Mapper(this DatiFatturazioneContatto model) => + new() + { + Email = model.Email + }; + + public static DatiFatturazioneResponse Mapper(this DatiFatturazione model) => + new() + { + NotaLegale = model.NotaLegale, + CodCommessa = model.CodCommessa, + Cup = model.Cup, + DataDocumento = model.DataDocumento, + SplitPayment = model.SplitPayment, + IdDocumento = model.IdDocumento, + Map = model.Map, + IdEnte = model.IdEnte, + Id = model.Id, + DataCreazione = model.DataCreazione.DateTime, + DataModifica = model.DataModifica != null ? model.DataModifica!.Value.DateTime : null, + Pec = model.Pec, + TipoCommessa = model.TipoCommessa, + Prodotto = model.Prodotto, + Contatti = model.Contatti?.Select(x => x.Mapper()) + }; + + public static TipoContrattoResponse Mapper(this TipoContratto model) => + new() + { + Id = model.Id, + Descrizione = model.Descrizione + }; + + public static IEnumerable Mapper(this IEnumerable models) + { + return models.Select(x => x.Mapper()); + } + + + public static TipoCommessaResponse Mapper(this TipoCommessa model) => + new() + { + Id = model.Id, + Descrizione = model.Descrizione + }; + + public static IEnumerable Mapper(this IEnumerable models) + { + return models.Select(x => x.Mapper()); + } + + public static ProdottoResponse Mapper(this Prodotto model) => + new() + { + Nome = model.Nome + }; + + public static IEnumerable Mapper(this IEnumerable models) + { + return models.Select(x => x.Mapper()); + } + + public static IEnumerable Mapper(this IEnumerable models) + { + return models.Select(x => x.Mapper()); + } + + public static TipoSpedizioneResponse Mapper(this TipoSpedizione model) => + new() + { + Descrizione = model.Descrizione, + Id = model.Id, + Tipo = model.Tipo + }; + + public static IEnumerable Mapper(this IEnumerable models) + { + return models.Select(x => x.Mapper()); + } + + public static CategoriaSpedizioneResponse Mapper(this CategoriaSpedizione model) => + new() + { + Descrizione = model.Descrizione, + Id = model.Id, + Tipo = model.Tipo, + TipoSpedizione = model.TipoSpedizione!.Mapper().ToList() + }; +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneContattoCreateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneContattoCreateRequest.cs new file mode 100644 index 0000000..7399be6 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneContattoCreateRequest.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; + +public record DatiFatturazioneContattoCreateRequest +{ + [Required] + public string? Email { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneCreateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneCreateRequest.cs new file mode 100644 index 0000000..fc0c12b --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneCreateRequest.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; + +public record DatiFatturazioneCreateRequest +{ + + public string? Cup { get; set; } + [Required] + public bool NotaLegale { get; set; } + + public string? CodCommessa { get; set; } + + public DateTime? DataDocumento { get; set; } + + [Required] + public bool? SplitPayment { get; set; } + + public string? IdDocumento { get; set; } + public string? Map { get; set; } + public string? TipoCommessa { get; set; } + public string? Pec { get; set; } + public List? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPACreateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPACreateRequest.cs new file mode 100644 index 0000000..2727685 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPACreateRequest.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; + +public record DatiFatturazionePagoPACreateRequest +{ + [Required] + public string? IdEnte { get; set; } + + [Required] + public string? Prodotto { get; set; } + + public string? Cup { get; set; } + [Required] + public bool NotaLegale { get; set; } + + public string? CodCommessa { get; set; } + + public DateTime? DataDocumento { get; set; } + + [Required] + public bool? SplitPayment { get; set; } + + public string? IdDocumento { get; set; } + public string? Map { get; set; } + public string? TipoCommessa { get; set; } + public string? Pec { get; set; } + public List? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPAUpdateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPAUpdateRequest.cs new file mode 100644 index 0000000..97eca94 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazionePagoPAUpdateRequest.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; + +public record DatiFatturazionePagoPAUpdateRequest +{ + [Required] + public string? IdEnte { get; set; } + + [Required] + public string? Prodotto { get; set; } + + [Required] + public long Id { get; set; } + + public string? Cup { get; set; } + [Required] + public bool NotaLegale { get; set; } + + public string? CodCommessa { get; set; } + + public DateTime? DataDocumento { get; set; } + [Required] + public bool? SplitPayment { get; set; } + + public string? IdDocumento { get; set; } + public string? Map { get; set; } + [Required] + public string? TipoCommessa { get; set; } + [Required] + public string? Pec { get; set; } + public List? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneUpdateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneUpdateRequest.cs new file mode 100644 index 0000000..b86c61b --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DatiFatturazioneUpdateRequest.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; + +public record DatiFatturazioneUpdateRequest +{ + [Required] + public long Id { get; set; } + + public string? Cup { get; set; } + [Required] + public bool NotaLegale { get; set; } + + public string? CodCommessa { get; set; } + + public DateTime? DataDocumento { get; set; } + [Required] + public bool? SplitPayment { get; set; } + + public string? IdDocumento { get; set; } + public string? Map { get; set; } + [Required] + public string? TipoCommessa { get; set; } + [Required] + public string? Pec { get; set; } + public List? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DocumentDto.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DocumentDto.cs new file mode 100644 index 0000000..02b2e91 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Request/DocumentDto.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; + +public sealed class DocumentDto() +{ + public string? Documento { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/CategoriaSpedizioneResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/CategoriaSpedizioneResponse.cs new file mode 100644 index 0000000..b9f5a19 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/CategoriaSpedizioneResponse.cs @@ -0,0 +1,10 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; + +public class CategoriaSpedizioneResponse +{ + public long? Id { get; set; } + + public string? Descrizione { get; set; } + public string? Tipo { get; set; } + public List? TipoSpedizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaContattoResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaContattoResponse.cs new file mode 100644 index 0000000..c169102 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaContattoResponse.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; + +public record DatiFatturazioneContattoResponse +{ + public string? Email { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaResponse.cs new file mode 100644 index 0000000..712ba16 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/DatiCommessaResponse.cs @@ -0,0 +1,20 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; + +public record DatiFatturazioneResponse +{ + public long Id { get; set; } + public string? Cup { get; set; } + public bool NotaLegale { get; set; } + public string? CodCommessa { get; set; } + public DateTime? DataDocumento { get; set; } + public bool? SplitPayment { get; set; } + public string? IdEnte { get; set; } + public string? IdDocumento { get; set; } + public string? Map { get; set; } + public string? TipoCommessa { get; set; } + public string? Prodotto { get; set; } + public string? Pec { get; set; } + public DateTime DataCreazione { get; set; } + public DateTime? DataModifica { get; set; } + public IEnumerable? Contatti { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/ProdottoResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/ProdottoResponse.cs new file mode 100644 index 0000000..eb02e44 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/ProdottoResponse.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; + +public record ProdottoResponse +{ + public string? Nome { get; set; } +} diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoCommessaResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoCommessaResponse.cs new file mode 100644 index 0000000..8a95e16 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoCommessaResponse.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; + +public record TipoCommessaResponse +{ + public string? Id { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoContrattoResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoContrattoResponse.cs new file mode 100644 index 0000000..36491cd --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoContrattoResponse.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; +public record TipoContrattoResponse +{ + public long Id { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoSpedizioneResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoSpedizioneResponse.cs new file mode 100644 index 0000000..cb5144a --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiFatturazioni/Payload/Response/TipoSpedizioneResponse.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; + +public class TipoSpedizioneResponse +{ + public int Id { get; set; } + public string? Descrizione { get; set; } + public string? Tipo { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaEndpoints.cs new file mode 100644 index 0000000..f6afd11 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaEndpoints.cs @@ -0,0 +1,103 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse; + +public partial class DatiModuloCommessaModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + #region PagoPA + endpointRouteBuilder + .MapGet("api/modulocommessa/pagopa/", GetPagoPADatiModuloCommessaAsync) + .WithName("Permette di ottenere i dati relativi al modulo commessa via utente PagoPA per mese anno.") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/modulocommessa/pagopa/documento/ricerca", PagoPADatiModuloCommessaRicercaDocumentAsync) + .WithName("Permette di ottenere il file excel per il modulo commessa per ricerca descrizione via utente PagoPA") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/modulocommessa/pagopa/ricerca", PagoPADatiModuloCommessaRicercaAsync) + .WithName("Permette di ottenere i dati relativi al modulo commessa via utente PagoPA.") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/modulocommessa/pagopa", CreatePagoPADatiModuloCommessaAsync) + .WithName("Permette di creare/aggiornare i dati relativi al modulo commessa attuale via utente PagoPA.") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/pagopa/dettaglio/{anno}/{mese}", GetPagoPADatiModuloCommessaByAnnoMeseAsync) + .WithName("Permette di ottenere i dati dettaglio relativi a un modulo commessa via utente PagoPA.") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/pagopa/documento/{anno?}/{mese?}", GetPagoPADatiModuloCommessaDocumentoAsync) + .WithName("Permette di visualizzare il documento relativo a un modulo commessa via utente PagoPA.") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/pagopa/download/{anno?}/{mese?}", DownloadPagoPADatiModuloCommessaDocumentoAsync) + .WithName("Permette di scaricare il pdf relativo a un modulo commessa via utente PagoPA.") + .SetOpenApi(Module.DatiModuloCommessaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + + endpointRouteBuilder + .MapPost("api/modulocommessa", CreateDatiModuloCommessaAsync) + .WithName("Permette di creare/aggiornare i dati relativi al modulo commessa attuale.") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa", GetDatiModuloCommessaAsync) + .WithName("Permette di ottenere i dati relativi al modulo commessa attuale.") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/dettaglio/{anno}/{mese}", GetDatiModuloCommessaByAnnoMeseAsync) + .WithName("Permette di ottenere i dati dettaglio relativi a un modulo commessa.") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/lista/{anno?}", GetDatiModuloCommessaByAnnoAsync) + .WithName("Permette di ottenere i dati relativi al modulo commessa per anno.") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/lista/parziali/{anno?}", GetDatiModuloCommessaParzialiByAnnoAsync) + .WithName("Permette di ottenere i dati parziali relativi al modulo commessa per anno.") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/anni", GetDatiModuloCommessaAnniAsync) + .WithName("Permette di ottenere gli anni relativi ai modulo commessa inseriti.") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/documento/{anno?}/{mese?}", GetDatiModuloCommessaDocumentoAsync) + .WithName("Permette di visualizzare il documento relativo a un modulo commessa") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/modulocommessa/download/{anno?}/{mese?}", DownloadDatiModuloCommessaDocumentoAsync) + .WithName("Permette di scaricare il pdf relativo a un modulo commessa") + .SetOpenApi(Module.DatiModuloCommessaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaModule.cs new file mode 100644 index 0000000..577b467 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/DatiModuloCommessaModule.cs @@ -0,0 +1,480 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Extensions; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Extensions; +using PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload; +using PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Request; +using PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Response; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Queries; +using PortaleFatture.BE.Infrastructure.Common.Documenti; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.SelfCare.Queries; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse; + +public partial class DatiModuloCommessaModule +{ + #region PagoPA + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPADatiModuloCommessaAsync( + HttpContext context, + [FromQuery] string? idEnte, + [FromQuery] string? prodotto, + [FromQuery] long? idTipoContratto, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + authInfo.Prodotto = prodotto; + authInfo.IdEnte = idEnte; + authInfo.IdTipoContratto = idTipoContratto; + + await VerificaContratto(handler, localizer, authInfo); + + var modulo = await handler.Send(new DatiModuloCommessaQueryGet(authInfo)); + var response = modulo!.Mapper(authInfo); + response!.Modifica = response.Modifica && !response.ModuliCommessa!.IsNullNotAny(); + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PagoPADatiModuloCommessaRicercaDocumentAsync( + HttpContext context, + [FromBody] EnteRicercaModuloCommessaByDescrizioneRequest req, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var moduli = await handler.Send(new DatiModuloCommessaQueryGetByDescrizione(authInfo) + { + AnnoValidita = req.Anno, + MeseValidita = req.Mese, + Prodotto = req.Prodotto, + IdEnti = req.IdEnti + }); + + if (moduli == null || moduli.Count() == 0) + return NotFound(); + + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + + var dataSet = moduli.FillOneSheet(); + var content = dataSet.ToExcel(); + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + else + return Results.File(content!, mime, filename); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PagoPADatiModuloCommessaRicercaAsync( + HttpContext context, + [FromBody] EnteRicercaModuloCommessaByDescrizioneRequest req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var moduli = await handler.Send(new DatiModuloCommessaQueryGetByDescrizione(authInfo) + { + AnnoValidita = req.Anno, + MeseValidita = req.Mese, + Prodotto = req.Prodotto, + IdEnti = req.IdEnti + }); + + if (moduli == null || moduli.Count() == 0) + return NotFound(); + return Ok(moduli); + } + + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> CreatePagoPADatiModuloCommessaAsync( + HttpContext context, + [FromBody] DatiModuloCommessaPagoPACreateRequest req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + authInfo.IdEnte = req.IdEnte; + authInfo.Prodotto = req.Prodotto; + authInfo.IdTipoContratto = req.IdTipoContratto; + + var fatturabile = req.Fatturabile ?? true; + + await VerificaContratto(handler, localizer, authInfo); + + var modulo = await handler.Send(new DatiModuloCommessaQueryGet(authInfo)); // posso solo modificare, non inserire + if (modulo == null || modulo.DatiModuloCommessa!.IsNullNotAny()) + throw new DomainException(localizer["DatiModuloCommessaDoNotCreate"]); + + var command = req.Mapper(authInfo, authInfo.IdTipoContratto.Value) ?? throw new ValidationException(localizer["DatiModuloCommessaInvalidMapping"]); + foreach (var cmd in command.DatiModuloCommessaListCommand!) + { + cmd.IdEnte = authInfo.IdEnte; + cmd.Fatturabile = fatturabile; + } + + modulo = await handler.Send(command) ?? throw new DomainException(localizer["DatiModuloCommessaInvalidMapping"]); + var response = modulo!.Mapper(authInfo); + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPADatiModuloCommessaByAnnoMeseAsync( + HttpContext context, + [FromRoute] int anno, + [FromRoute] int mese, + [FromQuery] string? idEnte, + [FromQuery] string? prodotto, + [FromQuery] long? idTipoContratto, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + authInfo.IdEnte = idEnte; + authInfo.Prodotto = prodotto; + authInfo.IdTipoContratto = idTipoContratto; + + await VerificaContratto(handler, localizer, authInfo); + + var modulo = await handler.Send(new DatiModuloCommessaQueryGet(authInfo) + { + AnnoValidita = anno, + MeseValidita = mese + }); + + var response = modulo!.Mapper(authInfo); + response!.Modifica = response.Modifica && !response.ModuliCommessa!.IsNullNotAny(); + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPADatiModuloCommessaDocumentoAsync( + HttpContext context, + [FromRoute] int? anno, + [FromRoute] int? mese, + [FromQuery] string? idEnte, + [FromQuery] string? prodotto, + [FromQuery] long? idTipoContratto, + [FromServices] IMediator handler, + [FromServices] IWebHostEnvironment hostingEnvironment, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + authInfo.IdEnte = idEnte; + authInfo.Prodotto = prodotto; + authInfo.IdTipoContratto = idTipoContratto; + + await VerificaContratto(handler, localizer, authInfo); + + var dati = await handler.Send(new DatiModuloCommessaDocumentoQueryGet(authInfo) + { + AnnoValidita = anno, + MeseValidita = mese + }); + if (dati == null) + return NotFound(); + return Ok(dati); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task DownloadPagoPADatiModuloCommessaDocumentoAsync( + HttpContext context, + [FromRoute] int? anno, + [FromRoute] int? mese, + [FromQuery] string? idEnte, + [FromQuery] string? prodotto, + [FromQuery] long? idTipoContratto, + [FromQuery] string? tipo, + [FromServices] IMediator handler, + [FromServices] IDocumentBuilder documentBuilder, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + authInfo.IdEnte = idEnte; + authInfo.Prodotto = prodotto; + authInfo.IdTipoContratto = idTipoContratto; + + await VerificaContratto(handler, localizer, authInfo); + + var dati = await handler.Send(new DatiModuloCommessaDocumentoQueryGet(authInfo) + { + AnnoValidita = anno, + MeseValidita = mese + }); + + if (dati == null) + return NotFound(); + + if (tipo != null && tipo == "pdf") + { + var bytes = documentBuilder.CreateModuloCommessaPdf(dati!); + var filename = $"{Guid.NewGuid()}.pdf"; + var mime = "application/pdf"; + return Results.File(bytes!, mime, filename); + } + else + { + var content = documentBuilder.CreateModuloCommessaHtml(dati!); + var mime = "text/html"; + return Results.Text(content!, mime); + } + } + + private async Task VerificaContratto( + IMediator handler, + IStringLocalizer localizer, + IAuthenticationInfo authInfo) + { + var contratto = await handler.Send(new ContrattoQueryGetById(authInfo)) ?? + throw new DomainException(localizer["DatiModuloCommessaEmptyContratto"]); + + if (authInfo.IdTipoContratto != contratto.IdTipoContratto || authInfo.Prodotto != contratto.Prodotto) + throw new DomainException(localizer["DatiModuloCommessaEmptyContratto"]); + } + + #endregion + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> CreateDatiModuloCommessaAsync( + HttpContext context, + [FromBody] DatiModuloCommessaCreateRequest req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var idente = authInfo.IdEnte; + + var command = req.Mapper(authInfo) ?? throw new ValidationException(localizer["DatiModuloCommessaInvalidMapping"]); + foreach (var cmd in command.DatiModuloCommessaListCommand!) + cmd.IdEnte = idente; + + var modulo = await handler.Send(command) ?? throw new DomainException(localizer["DatiModuloCommessaInvalidMapping"]); + var response = modulo!.Mapper(authInfo); + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetDatiModuloCommessaAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var modulo = await handler.Send(new DatiModuloCommessaQueryGet(authInfo)); + var response = modulo!.Mapper(authInfo); + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetDatiModuloCommessaByAnnoMeseAsync( + HttpContext context, + [FromRoute] int anno, + [FromRoute] int mese, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var modulo = await handler.Send(new DatiModuloCommessaQueryGet(authInfo) + { + AnnoValidita = anno, + MeseValidita = mese + }); + + var response = modulo!.Mapper(authInfo); + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetDatiModuloCommessaByAnnoAsync( + HttpContext context, + [FromRoute] int? anno, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var modulo = await handler.Send(new DatiModuloCommessaQueryGetByAnno(authInfo) + { + AnnoValidita = anno, + }); + if (modulo == null || modulo.Count() == 0) + return NotFound(); + return Ok(modulo.Select(x => x.Mapper())); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetDatiModuloCommessaParzialiByAnnoAsync( + HttpContext context, + [FromRoute] int? anno, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var modulo = await handler.Send(new DatiModuloCommessaParzialiQueryGetByAnno(authInfo) + { + AnnoValidita = anno, + }); + if (modulo == null || modulo.Count() == 0) + return NotFound(); + return Ok(modulo.Select(x => x.Mapper())); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetDatiModuloCommessaAnniAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var anni = await handler.Send(new DatiModuloCommessaGetAnni(authInfo)); + if (anni == null || anni.Count() == 0) + return NotFound(); + return Ok(anni); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetDatiModuloCommessaDocumentoAsync( + HttpContext context, + [FromRoute] int? anno, + [FromRoute] int? mese, + [FromServices] IMediator handler, + [FromServices] IWebHostEnvironment hostingEnvironment, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + var dati = await handler.Send(new DatiModuloCommessaDocumentoQueryGet(authInfo) + { + AnnoValidita = anno, + MeseValidita = mese + }); + if (dati == null) + return NotFound(); + return Ok(dati); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task DownloadDatiModuloCommessaDocumentoAsync( + HttpContext context, + [FromRoute] int? anno, + [FromRoute] int? mese, + [FromQuery] string? tipo, + [FromServices] IMediator handler, + [FromServices] IDocumentBuilder documentBuilder, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + var dati = await handler.Send(new DatiModuloCommessaDocumentoQueryGet(authInfo) + { + AnnoValidita = anno, + MeseValidita = mese + }); + if (dati == null) + return NotFound(); + + if (tipo != null && tipo == "pdf") + { + var bytes = documentBuilder.CreateModuloCommessaPdf(dati!); + var filename = $"{Guid.NewGuid()}.pdf"; + var mime = "application/pdf"; + return Results.File(bytes!, mime, filename); + } + else + { + var content = documentBuilder.CreateModuloCommessaHtml(dati!); + var mime = "text/html"; + return Results.Text(content!, mime); + } + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Extensions/DatiModuloCommessaViewModelExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Extensions/DatiModuloCommessaViewModelExtensions.cs new file mode 100644 index 0000000..3c3a523 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Extensions/DatiModuloCommessaViewModelExtensions.cs @@ -0,0 +1,150 @@ +using Azure; +using PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload; +using PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Response; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Extensions; + +public static class DatiModuloCommessaViewModelExtensions +{ + public static DatiModuloCommessaByAnnoResponse Mapper(this ModuloCommessaByAnnoDto model) + { + Dictionary? totali = []; + foreach (var tot in model.Totali!) + { + totali.Add(tot.Key, new ModuloCommessaMeseTotaleResponse() + { + IdCategoriaSpedizione = tot.Value.IdCategoriaSpedizione, + Tipo = tot.Value.Tipo, + TotaleCategoria = $"{tot.Value.TotaleCategoria} €" + }); + } + return new DatiModuloCommessaByAnnoResponse() + { + TotaleAnalogico = totali.Where(x => x.Key == 1).FirstOrDefault().Value == null ? "0,00 €" : totali.Where(x => x.Key == 1).FirstOrDefault().Value.TotaleCategoria, + TotaleDigitale = totali.Where(x => x.Key == 2).FirstOrDefault().Value == null ? "0,00 €" : totali.Where(x => x.Key == 2).FirstOrDefault().Value.TotaleCategoria, + AnnoValidita = model.AnnoValidita, + IdEnte = model.IdEnte, + IdTipoContratto = model.IdTipoContratto, + MeseValidita = model.MeseValidita, + Modifica = model.Modifica, + Prodotto = model.Prodotto, + Stato = model.Stato, + Totale = $"{model.Totale} €", + DataModifica = model.DataModifica.ToString("d") + }; + } + + public static DatiModuloCommessaParzialiTotaleResponse Mapper(this DatiModuloCommessaParzialiTotale model) + { + return new DatiModuloCommessaParzialiTotaleResponse() + { + Analogico890Nazionali = $"{model.Analogico890Nazionali} €", + AnalogicoARInternazionali = $"{model.AnalogicoARInternazionali} €", + AnalogicoARNazionali = $"{model.AnalogicoARNazionali} €", + Digitale = $"{model.Digitale} €", + AnnoValidita = model.AnnoValidita, + IdEnte = model.IdEnte, + IdTipoContratto = model.IdTipoContratto, + MeseValidita = model.MeseValidita, + Modifica = model.Modifica, + Prodotto = model.Prodotto, + Stato = model.Stato, + Totale = $"{model.Totale} €", + }; + } + + public static DatiModuloCommessaCreateListCommand Mapper(this DatiModuloCommessaPagoPACreateRequest model, AuthenticationInfo authInfo, long idTipoContratto) + { + authInfo.Prodotto = model.Prodotto; + authInfo.IdEnte = model.IdEnte; + authInfo.IdTipoContratto = idTipoContratto; + + var cmd = new DatiModuloCommessaCreateListCommand(authInfo) + { + DatiModuloCommessaListCommand = [] + }; + + foreach (var md in model.ModuliCommessa!) + cmd.DatiModuloCommessaListCommand.Add(md.Mapper()); + return cmd; + } + + public static DatiModuloCommessaCreateListCommand Mapper(this DatiModuloCommessaCreateRequest model, AuthenticationInfo authInfo) + { + var cmd = new DatiModuloCommessaCreateListCommand(authInfo) + { + DatiModuloCommessaListCommand = [] + }; + + foreach (var md in model.ModuliCommessa!) + cmd.DatiModuloCommessaListCommand.Add(md.Mapper()); + return cmd; + } + + public static DatiModuloCommessaCreateCommand Mapper(this DatiModuloCommessaCreateSimpleRequest model) + { + return new DatiModuloCommessaCreateCommand() + { + NumeroNotificheInternazionali = model.NumeroNotificheInternazionali, + NumeroNotificheNazionali = model.NumeroNotificheNazionali, + IdTipoSpedizione = model.IdTipoSpedizione + }; + } + + public static DatiModuloCommessaResponse? Mapper(this ModuloCommessaDto model, AuthenticationInfo info) + { + var cmd = new DatiModuloCommessaResponse + { + ModuliCommessa = [], + Totale = [], + TotaleModuloCommessaNotifica = new(), + Modifica = model.Modifica, + Anno = model.Anno, + Mese = model.Mese, + IdTipoContratto = info.IdTipoContratto!.Value + }; + + if (model is null) + return cmd; + + foreach (var md in model.DatiModuloCommessa!) + { + cmd.ModuliCommessa.Add(new DatiModuloCommessaSimpleResponse() + { + IdTipoSpedizione = md.IdTipoSpedizione, + NumeroNotificheInternazionali = md.NumeroNotificheInternazionali, + NumeroNotificheNazionali = md.NumeroNotificheNazionali, + TotaleNotifiche = md.TotaleNotifiche + }); + cmd.IdTipoContratto = md.IdTipoContratto; + } + + foreach (var mdt in model.DatiModuloCommessaTotale!) + { + cmd.Totale.Add(new TotaleDatiModuloCommessa() + { + TotaleValoreCategoriaSpedizione = mdt.TotaleCategoria, + IdCategoriaSpedizione = mdt.IdCategoriaSpedizione + }); + } + + cmd.TotaleModuloCommessaNotifica = new TotaleDatiModuloCommessaNotifica(); + foreach (var mdc in cmd.ModuliCommessa) + { + cmd.TotaleModuloCommessaNotifica.TotaleNumeroNotificheNazionali += mdc.NumeroNotificheNazionali; + cmd.TotaleModuloCommessaNotifica.TotaleNumeroNotificheInternazionali += mdc.NumeroNotificheInternazionali; + cmd.TotaleModuloCommessaNotifica.TotaleNumeroNotificheDaProcessare += mdc.TotaleNotifiche; + } + cmd.TotaleModuloCommessaNotifica.Totale = cmd.Totale.Select(x => x.TotaleValoreCategoriaSpedizione).Sum(); + + var dataCreazione = model.DatiModuloCommessa!.Select(x => x.DataCreazione).FirstOrDefault(); + var dataModifica = model.DatiModuloCommessa!.Select(x => x.DataModifica).FirstOrDefault(); + cmd.DataModifica = dataModifica == DateTime.MinValue ? dataCreazione : dataModifica; + + return cmd; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/DatiModuloCommessaCreateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/DatiModuloCommessaCreateRequest.cs new file mode 100644 index 0000000..633bd02 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/DatiModuloCommessaCreateRequest.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload; + +public class DatiModuloCommessaCreateRequest +{ + public List? ModuliCommessa { get; set; } + +} +public class DatiModuloCommessaCreateSimpleRequest +{ + public int NumeroNotificheNazionali { get; set; } + public int NumeroNotificheInternazionali { get; set; } + public int IdTipoSpedizione { get; set; } +} + +public class DatiModuloCommessaPagoPACreateRequest +{ + [Required] + public string? IdEnte { get; set; } + + [Required] + public string? Prodotto { get; set; } + + [Required] + public long IdTipoContratto { get; set; } + + [Required] + public List? ModuliCommessa { get; set; } + public bool? Fatturabile { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/EnteRicercaModuloCommessaByDescrizioneRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/EnteRicercaModuloCommessaByDescrizioneRequest.cs new file mode 100644 index 0000000..b069284 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Request/EnteRicercaModuloCommessaByDescrizioneRequest.cs @@ -0,0 +1,16 @@ +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Request; +public sealed class EnteRicercaModuloCommessaByDescrizioneRequest +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? Prodotto { get; set; } + + private string[]? _idEnti; + public string[]? IdEnti + { + get { return _idEnti; } + set { _idEnti = value!.IsNullNotAny() ? null : value; } + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaByAnnoResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaByAnnoResponse.cs new file mode 100644 index 0000000..99e67ab --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaByAnnoResponse.cs @@ -0,0 +1,25 @@ +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Response; + +public class DatiModuloCommessaByAnnoResponse +{ + public bool Modifica { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public string? IdEnte { get; set; } + public long IdTipoContratto { get; set; } + public string? Stato { get; set; } + public string? Prodotto { get; set; } + public string? Totale { get; set; } + public string? DataModifica { get; set; } + public string? TotaleDigitale { get; set; } + public string? TotaleAnalogico { get; set; } +} + +public class ModuloCommessaMeseTotaleResponse +{ + public string? TotaleCategoria { get; set; } + public int IdCategoriaSpedizione { get; set; } + public string? Tipo { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaParzialiTotaleResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaParzialiTotaleResponse.cs new file mode 100644 index 0000000..f079d59 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaParzialiTotaleResponse.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Response; + +public class DatiModuloCommessaParzialiTotaleResponse +{ + [Column("FkIdEnte")] + public string? IdEnte { get; set; } + + [Column("FKIdTipoContratto")] + public long IdTipoContratto { get; set; } + + [Column("FkIdStato")] + public string? Stato { get; set; } + + [Column("FkProdotto")] + public string? Prodotto { get; set; } + public int AnnoValidita { get; set; } + public int MeseValidita { get; set; } + public string? Totale { get; set; } + public string? Digitale { get; set; } + public string? AnalogicoARNazionali { get; set; } + public string? AnalogicoARInternazionali { get; set; } + public string? Analogico890Nazionali { get; set; } + public bool Modifica { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaResponse.cs new file mode 100644 index 0000000..bb8ba9a --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiModuloCommesse/Payload/Response/DatiModuloCommessaResponse.cs @@ -0,0 +1,35 @@ +namespace PortaleFatture.BE.Api.Modules.DatiModuloCommesse.Payload.Response; + +public class DatiModuloCommessaResponse +{ + public long IdTipoContratto { get; set; } + public bool Modifica { get; set; } + public int Anno { get; set; } + public int Mese { get; set; } + public DateTime DataModifica { get; set; } + public List? ModuliCommessa { get; set; } + public TotaleDatiModuloCommessaNotifica? TotaleModuloCommessaNotifica { get; set; } + public List? Totale { get; set; } +} + +public class DatiModuloCommessaSimpleResponse +{ + public int NumeroNotificheNazionali { get; set; } + public int NumeroNotificheInternazionali { get; set; } + public int IdTipoSpedizione { get; set; } + public int TotaleNotifiche { get; set; } +} + +public class TotaleDatiModuloCommessaNotifica +{ + public int TotaleNumeroNotificheNazionali { get; set; } + public int TotaleNumeroNotificheInternazionali { get; set; } + public int TotaleNumeroNotificheDaProcessare { get; set; } + public decimal Totale { get; set; } +} + +public class TotaleDatiModuloCommessa +{ + public int IdCategoriaSpedizione { get; set; } + public decimal TotaleValoreCategoriaSpedizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Extensions/RelExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Extensions/RelExtensions.cs new file mode 100644 index 0000000..3df6966 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Extensions/RelExtensions.cs @@ -0,0 +1,129 @@ +using PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse.Dto; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Queries; + +namespace PortaleFatture.BE.Api.Modules.DatiRel.Extensions; + +public static class RelExtensions +{ + public static RelTipologieFattureByPagoPA Map(this RelTipologiaFatturaPagoPARequest req, AuthenticationInfo authInfo) + { + return new RelTipologieFattureByPagoPA(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + }; + } + + public static RelTipologieFattureByIdEnte Map(this RelTipologiaFatturaRequest req, AuthenticationInfo authInfo) + { + return new RelTipologieFattureByIdEnte(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + }; + } + + public static RelFatturabileByIdEnti Map(this RelFatturabileByIdEntiRequest req, AuthenticationInfo authInfo) + { + return new RelFatturabileByIdEnti(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + EntiIds = req.EntiIds, + Fatturabile = req.Fatturabile == false ? 0 : null + }; + } + + public static RelUploadGetById Map(this RelUploadByIdRequest req, AuthenticationInfo authInfo) + { + return new RelUploadGetById(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdContratto = req.IdContratto, + TipologiaFattura = req.TipologiaFattura + }; + } + + public static RelTestataQueryGetByListaEnti Map(this RelTestataRicercaRequestPagoPA req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new RelTestataQueryGetByListaEnti(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdContratto = req.IdContratto, + TipologiaFattura = req.TipologiaFattura, + Page = page, + Size = pageSize, + EntiIds = req.IdEnti, + Caricata = req.Caricata + }; + } + + public static RelTestataQueryGetByListaEntiQuadratura Map2(this RelTestataRicercaRequestPagoPA req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new RelTestataQueryGetByListaEntiQuadratura(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdContratto = req.IdContratto, + TipologiaFattura = req.TipologiaFattura, + Page = page, + Size = pageSize, + EntiIds = req.IdEnti, + Caricata = req.Caricata + }; + } + + public static RelTestataQueryGetByIdEnte Map(this RelTestataRicercaRequest req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new RelTestataQueryGetByIdEnte(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdContratto = req.IdContratto, + TipologiaFattura = req.TipologiaFattura, + Caricata = req.Caricata, + Page = page, + Size = pageSize + }; + } + + public static RelTestataQueryGetById Map(this RelTestataByIdRequest req, AuthenticationInfo authInfo) + { + return new RelTestataQueryGetById(authInfo) + { + IdTestata = req.IdTestata + }; + } + + public static RelRigheQueryGetById Map(this RelRigheByIdRequest req, AuthenticationInfo authInfo) + { + return new RelRigheQueryGetById(authInfo) + { + IdTestata = req.IdTestata + }; + } + + public static RelDocumentoDto Map(this RelTestataDettaglioDto req) + { + return new RelDocumentoDto() + { + Mese = Convert.ToInt32(req.Mese).GetMonth(), + Anno = req.Anno, + Totale = req.Totale.ToString(), + TotaleAnalogico = req.TotaleAnalogico.ToString(), + TotaleDigitale = req.TotaleDigitale.ToString(), + TotaleNotificheAnalogiche = req.TotaleNotificheAnalogiche, + TotaleNotificheDigitali = req.TotaleNotificheDigitali, + RagioneSociale = req.RagioneSociale, + IdContratto = req.IdContratto, + TipologiaFattura = req.TipologiaFattura, + }; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelFatturabileByIdEntiRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelFatturabileByIdEntiRequest.cs new file mode 100644 index 0000000..7a2e181 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelFatturabileByIdEntiRequest.cs @@ -0,0 +1,9 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelFatturabileByIdEntiRequest +{ + public int Anno { get; set; } + public int Mese { get; set; } + public string[]? EntiIds { get; set; } + public bool Fatturabile { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelRigheByIdRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelRigheByIdRequest.cs new file mode 100644 index 0000000..930707c --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelRigheByIdRequest.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelRigheByIdRequest +{ + public string? IdTestata { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataByIdRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataByIdRequest.cs new file mode 100644 index 0000000..03a0276 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataByIdRequest.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelTestataByIdRequest +{ + public string? IdTestata { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequest.cs new file mode 100644 index 0000000..23fe39d --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequest.cs @@ -0,0 +1,10 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelTestataRicercaRequest +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? TipologiaFattura { get; set; } + public string? IdContratto { get; set; } + public byte? Caricata { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequestPagoPA.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequestPagoPA.cs new file mode 100644 index 0000000..1d7e7d0 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTestataRicercaRequestPagoPA.cs @@ -0,0 +1,19 @@ +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelTestataRicercaRequestPagoPA +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? TipologiaFattura { get; set; } + public string? IdContratto { get; set; } + public byte? Caricata { get; set; } + + private string[]? _idEnti; + public string[]? IdEnti + { + get { return _idEnti; } + set { _idEnti = value!.IsNullNotAny() ? null : value; } + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaPagoPARequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaPagoPARequest.cs new file mode 100644 index 0000000..6a0457a --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaPagoPARequest.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelTipologiaFatturaPagoPARequest +{ + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaRequest.cs new file mode 100644 index 0000000..29d1d99 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelTipologiaFatturaRequest.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelTipologiaFatturaRequest +{ + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelUploadByIdRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelUploadByIdRequest.cs new file mode 100644 index 0000000..bc149f3 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/Payload/Request/RelUploadByIdRequest.cs @@ -0,0 +1,10 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class RelUploadByIdRequest +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? TipologiaFattura { get; set; } + public string? IdContratto { get; set; } + public string? IdEnte { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelEndpoints.cs new file mode 100644 index 0000000..a1b090d --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelEndpoints.cs @@ -0,0 +1,136 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.Notifiche; + +public partial class RelModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + #region selfcare + + endpointRouteBuilder + .MapPost("api/rel/tipologiafattura", PostTipologiaFatturaAsync) + .WithName("Permette di verificare le tipologie fatture") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/firma/upload/{id}", PostUploadFirmaAsync) + .WithName("Permette caricare il file rel pdf firmato") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/firma/log", PostDownloadLogAsync) + .WithName("Permette di scaricare il log pdf firmato") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/firma/download/{id}", GetDownloadFirmaAsync) + .WithName("Permette di scaricare il file rel pdf firmato") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/ente", GetRelTestataByRicercaAsync) + .WithName("Permette di ottenere le Rel dell'ente per ricerca") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/ente/{id}", GetRelTestataByIdAsync) + .WithName("Permette di ottenere le Rel dell'ente per id") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/ente/download/{id}", DownloadRelDocumentoAsync) + .WithName("Permette di scaricare il pdf relativo ad una specifica rel") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/ente/documento/ricerca", GetRelRicercaDocumentAsync) + .WithName("Permette di ottenere il documento Rels dell'ente per ricerca") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/ente/righe/{id}", GetRelRigheDocumentAsync) + .WithName("Permette di ottenere le righe delle Rels dell'ente per ricerca") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + + #region pagoPA + + endpointRouteBuilder + .MapPost("api/rel/pagopa/tipologiafattura", PostTipologiaFatturaPagoPAAsync) + .WithName("Permette di verificare le tipologie fatture pagoPA") + .SetOpenApi(Module.DatiRelLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/pagopa/documento/download/{id}", GetDownloadPagoPAAsync) + .WithName("Permette di scaricare il file rel lato pagoPA pdf firmato") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/fatturabile", PostPagoPAFatturabileAsync) + .WithName("Permette di cambiare lo stato fatturabile via PagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/pagopa/firma/log", PostPagoPADownloadLogAsync) + .WithName("Permette di scaricare il log pdf firmato via PagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/pagopa", GetPagoPARelTestataByRicercaAsync) + .WithName("Permette di ottenere le Rel dell'ente per ricerca pagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/pagopa/documento/ricerca", GetPagoPARelRicercaDocumentAsync) + .WithName("Permette di ottenere il documento Rels dell'ente per ricerca pagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/pagopa/firma/download", PostPagoPADownloadFirmaZipAsync) + .WithName("Permette di ottenere tutti i Rels firmati per ricerca pagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/pagopa/righe/{id}", GetPagoPARelRigheDocumentAsync) + .WithName("Permette di ottenere le righe delle Rels dell'ente per ricerca pagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/pagopa/{id}", GetPagoPARelTestataByIdAsync) + .WithName("Permette di ottenere le Rel dell'ente per id PagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/rel/pagopa/firma/download/{id}", GetPagoPADownloadFirmaAsync) + .WithName("Permette di scaricare il file rel pdf firmato via PagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/rel/pagopa/quadratura/ricerca", GetPagoPAQuadraturaRicercaDocumentAsync) + .WithName("Permette di ottenere il documento quadratura Rels dell'ente per ricerca pagoPA") + .SetOpenApi(Module.DatiRelLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelModule.cs new file mode 100644 index 0000000..6c578b9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/DatiRel/RelModule.cs @@ -0,0 +1,686 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Infrastructure.Documenti; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Api.Modules.DatiRel.Extensions; +using PortaleFatture.BE.Api.Modules.Notifiche.Extensions; +using PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Dto; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Extensions; +using PortaleFatture.BE.Infrastructure.Common.Documenti; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Gateway.Storage; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.Notifiche; + +public partial class RelModule +{ + #region pagoPA + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PostTipologiaFatturaPagoPAAsync( + HttpContext context, + [FromBody] RelTipologiaFatturaPagoPARequest? request, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + + var tipologie = await handler.Send(request!.Map(authInfo)); + if (tipologie == null || tipologie.Count() == 0) + return NotFound(); + return Ok(tipologie); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetDownloadPagoPAAsync( + HttpContext context, + [FromRoute] string? id, + [FromQuery] string? tipo, + [FromServices] IDocumentBuilder documentBuilder, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + var request = new RelTestataByIdRequest() + { + IdTestata = id + }; + var rel = await handler.Send(request.Map(authInfo)); + if (rel == null + || rel.TipologiaFattura!.ToLower().Contains("var") + || rel.TipologiaFattura!.ToLower().Contains("semestrale") + || rel.TipologiaFattura!.ToLower().Contains("annuale")) + return NotFound(); + + if (tipo != null && tipo == "pdf") + { + var bytes = documentBuilder.CreateModuloRelPdf(rel.Map()!); + var filename = $"{Guid.NewGuid()}.pdf"; + var mime = "application/pdf"; + return Results.File(bytes!, mime, filename); + } + else + { + var content = documentBuilder.CreateModuloRelHtml(rel.Map()!); + var mime = "text/html"; + return Results.Text(content!, mime); + } + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> PostPagoPAFatturabileAsync( + HttpContext context, + [FromBody] RelFatturabileByIdEntiRequest? request, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] IRelStorageService storageService) + { + var authInfo = context.GetAuthInfo(); + var fatturabile = await handler.Send(request!.Map(authInfo)); + if (fatturabile == null) + return NotFound(); + return Ok(fatturabile); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PostPagoPADownloadLogAsync( + HttpContext context, + [FromBody] RelUploadByIdRequest? request, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] IRelStorageService storageService) + { + var authInfo = context.GetAuthInfo(); + authInfo.IdEnte = request!.IdEnte; + var upload = await handler.Send(request!.Map(authInfo)); + if (upload == null) + return NotFound(); + return Ok(upload); + } + + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PostPagoPADownloadFirmaZipAsync( + HttpContext context, + [FromBody] RelTestataRicercaRequestPagoPA request, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] IRelStorageService storageService) + { + var authInfo = context.GetAuthInfo(); + if (request.Caricata == null || request.Caricata.Value == 0) + return NotFound(); + + var rels = await handler.Send(request.Map(authInfo, null, null)); + if (rels == null || rels.Count == 0) + return NotFound(); + var (bytes, list) = await storageService.ReadZip(rels); + await handler.Send(rels.RelTestate.Map(list, authInfo)); + + var mime = "application/zip"; + var filename = $"{Guid.NewGuid()}.zip"; + return Results.File(bytes!, mime, filename); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetPagoPADownloadFirmaAsync( + HttpContext context, + [FromRoute] string? id, + [FromQuery] bool? binary, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] IRelStorageService storageService) + { + var authInfo = context.GetAuthInfo(); + var key = RelTestataKey.Deserialize(id!); + + var request = new RelTestataByIdRequest() + { + IdTestata = id + }; + var rel = await handler.Send(request.Map(authInfo)); + if (rel == null) + return NotFound(); + + var bytes = await storageService.ReadBytes(key); + await handler.Send(new RelDownloadCommand(authInfo) + { + Anno = key.Anno, + IdContratto = key.IdContratto, + IdEnte = key.IdEnte, + IdUtente = authInfo.Id, + Mese = key.Mese, + TipologiaFattura = key.TipologiaFattura, + DataEvento = DateTime.UtcNow.ItalianTime(), + Azione = RelAzioneDocumento.Download, + Hash = bytes.GetHashSHA512() + }); + var mime = "application/pdf"; + var filename = $"{Guid.NewGuid()}.pdf"; + + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(bytes) }); + else + return Results.File(bytes!, mime, filename); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPARelTestataByRicercaAsync( + HttpContext context, + [FromBody] RelTestataRicercaRequestPagoPA request, + [FromQuery] int page, + [FromQuery] int pageSize, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var rel = await handler.Send(request.Map(authInfo, page, pageSize)); + if (rel == null || rel.Count == 0) + return NotFound(); + return Ok(rel); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [Authorize()] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetPagoPARelRicercaDocumentAsync( + HttpContext context, + [FromBody] RelTestataRicercaRequestPagoPA request, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var rels = await handler.Send(request.Map(authInfo, null, null)); + if (rels == null || rels.Count == 0) + return NotFound(); + + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + + var dataSet = rels.RelTestate!.FillOneSheetWithTotalsRel(); + var content = dataSet.ToExcel(); + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + else + return Results.File(content!, mime, filename); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [Authorize()] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetPagoPAQuadraturaRicercaDocumentAsync( + HttpContext context, + [FromBody] RelTestataRicercaRequestPagoPA request, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var rels = await handler.Send(request.Map2(authInfo, null, null)); + if (rels == null || rels.Count == 0) + return NotFound(); + + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + + var dataSet = rels.Quadratura!.FillOneSheetWithTotalsRel(); + var content = dataSet.ToExcel(); + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + else + return Results.File(content!, mime, filename); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [Authorize()] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetPagoPARelRigheDocumentAsync( + HttpContext context, + [FromRoute] string? id, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler, + [FromQuery] bool? binary = null) + { + var authInfo = context.GetAuthInfo(); + var idEnte = id!.Split("_")[0]; + authInfo.IdEnte = idEnte; + var request = new RelRigheByIdRequest() + { + IdTestata = id + }; + + var rels = await handler.Send(request.Map(authInfo)); + if (rels == null || rels.Count() == 0) + { + await Results.NotFound("Data not found").ExecuteAsync(context); + return; + } + + var data = await rels.ToArray(); + var filename = $"{Guid.NewGuid()}.csv"; + var mimeCsv = "text/csv"; + await Results.File(data!, mimeCsv, filename, enableRangeProcessing: true).ExecuteAsync(context); + + data = null; + DocsExtensions.ForceGarbageCollection(); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPARelTestataByIdAsync( + HttpContext context, + [FromRoute] string? id, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var idEnte = id!.Split("_")[0]; + authInfo.IdEnte = idEnte; + var request = new RelTestataByIdRequest() + { + IdTestata = id + }; + + var rel = await handler.Send(request.Map(authInfo)); + if (rel == null) + return NotFound(); + return Ok(rel); + } + #endregion + + #region selfcare + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PostTipologiaFatturaAsync( + HttpContext context, + [FromBody] RelTipologiaFatturaRequest? request, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer) + { + var authInfo = context.GetAuthInfo(); + + var tipologie = await handler.Send(request!.Map(authInfo)); + if (tipologie == null || tipologie.Count() == 0) + return NotFound(); + return Ok(tipologie); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PostDownloadLogAsync( + HttpContext context, + [FromBody] RelUploadByIdRequest? request, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] IRelStorageService storageService) + { + var authInfo = context.GetAuthInfo(); + + if (request == null + || request.TipologiaFattura!.ToLower().Contains("var") + || request.TipologiaFattura!.ToLower().Contains("semestrale") + || request.TipologiaFattura!.ToLower().Contains("annuale")) + return NotFound(); + + var upload = await handler.Send(request!.Map(authInfo)); + if (upload == null || upload.Count() == 0) + return NotFound(); + return Ok(upload); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetDownloadFirmaAsync( + HttpContext context, + [FromRoute] string? id, + [FromQuery] bool? binary, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] IRelStorageService storageService) + { + var authInfo = context.GetAuthInfo(); + var key = RelTestataKey.Deserialize(id!); + if (authInfo.IdEnte != key.IdEnte) + throw new DomainException("Wrong Id Ente"); + + var request = new RelTestataByIdRequest() + { + IdTestata = id + }; + var rel = await handler.Send(request.Map(authInfo)); + if (rel == null + || rel.Caricata != 1 + || rel.TipologiaFattura!.ToLower().Contains("var") + || rel.TipologiaFattura!.ToLower().Contains("semestrale") + || rel.TipologiaFattura!.ToLower().Contains("annuale")) + return NotFound(); + + var bytes = await storageService.ReadBytes(key); + await handler.Send(new RelDownloadCommand(authInfo) + { + Anno = key.Anno, + IdContratto = key.IdContratto, + IdEnte = key.IdEnte, + IdUtente = authInfo.Id, + Mese = key.Mese, + TipologiaFattura = key.TipologiaFattura, + DataEvento = DateTime.UtcNow.ItalianTime(), + Azione = RelAzioneDocumento.Download, + Hash = bytes.GetHashSHA512() + }); + var mime = "application/pdf"; + var filename = $"{Guid.NewGuid()}.pdf"; + + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(bytes) }); + else + return Results.File(bytes!, mime, filename); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> PostUploadFirmaAsync( + HttpContext context, + [FromRoute] string? id, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer, + [FromServices] ILogger logger, + [FromServices] IRelStorageService storageService) + { + var form = await context.Request.ReadFormAsync(); + var file = form.Files.Where(s => s.Name != "file" || s.Name != "pdf").FirstOrDefault(); + if (file == null) + throw new ValidationException("Estensione sbagliata. Passare un pdf valido."); + var authInfo = context.GetAuthInfo(); + var size = file!.Length; + if (size > 0) + { + var key = RelTestataKey.Deserialize(id!); + if (authInfo.IdEnte != key.IdEnte) + throw new DomainException("Wrong Id Ente"); + + if (key.TipologiaFattura!.ToLower().Contains("semestrale") + || key.TipologiaFattura!.ToLower().Contains("annuale")) + return NotFound(); + + var fileName = file.FileName; + var extension = Path.GetExtension(fileName); + if (extension != ".pdf") + { + var msg = $"Estensione sbagliata. Passare un pdf valido per la firma. {fileName} per Ente: {authInfo.IdEnte}"; + logger.LogError(msg); + throw new ValidationException("Estensione sbagliata. Passare un pdf valido."); + } + + bool? result = false; + using var memoryStream = new MemoryStream(); + { + await file.CopyToAsync(memoryStream); + await storageService.AddDocument(key, memoryStream); + result = await handler.Send(new RelUploadCreateCommand(authInfo) + { + Anno = key.Anno, + IdContratto = key.IdContratto, + IdEnte = key.IdEnte, + IdUtente = authInfo.Id, + Mese = key.Mese, + TipologiaFattura = key.TipologiaFattura, + DataEvento = DateTime.UtcNow.ItalianTime(), + Azione = RelAzioneDocumento.Upload, + Hash = memoryStream.ToArray().GetHashSHA512() + }); + } + return Ok(result.Value); + } + return Ok(false); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetRelTestataByRicercaAsync( + HttpContext context, + [FromBody] RelTestataRicercaRequest request, + [FromQuery] int page, + [FromQuery] int pageSize, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + + var authInfo = context.GetAuthInfo(); + var rel = await handler.Send(request.Map(authInfo, page, pageSize)); + if (rel == null || rel.Count == 0) + return NotFound(); + return Ok(rel); + + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetRelTestataByIdAsync( + HttpContext context, + [FromRoute] string? id, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var request = new RelTestataByIdRequest() + { + IdTestata = id + }; + + var rel = await handler.Send(request.Map(authInfo)); + if (rel == null) + return NotFound(); + return Ok(rel); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task DownloadRelDocumentoAsync( + HttpContext context, + [FromRoute] string? id, + [FromQuery] string? tipo, + [FromServices] IDocumentBuilder documentBuilder, + [FromServices] IMediator handler, + [FromServices] IStringLocalizer localizer +) + { + var authInfo = context.GetAuthInfo(); + var request = new RelTestataByIdRequest() + { + IdTestata = id + }; + var rel = await handler.Send(request.Map(authInfo)); + if (rel == null + || rel.TipologiaFattura!.ToLower().Contains("var") + || rel.TipologiaFattura!.ToLower().Contains("semestrale") + || rel.TipologiaFattura!.ToLower().Contains("annuale")) + return NotFound(); + + if (tipo != null && tipo == "pdf") + { + var bytes = documentBuilder.CreateModuloRelPdf(rel.Map()!); + var filename = $"{Guid.NewGuid()}.pdf"; + var mime = "application/pdf"; + return Results.File(bytes!, mime, filename); + } + else + { + var content = documentBuilder.CreateModuloRelHtml(rel.Map()!); + var mime = "text/html"; + return Results.Text(content!, mime); + } + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [Authorize()] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetRelRigheDocumentAsync( + HttpContext context, + [FromRoute] string? id, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler, + [FromQuery] bool? binary = null) + { + var authInfo = context.GetAuthInfo(); + var request = new RelRigheByIdRequest() + { + IdTestata = id + }; + + var rels = await handler.Send(request.Map(authInfo)); + if (rels == null || !rels.Any()) + { + await Results.NotFound("Data not found").ExecuteAsync(context); + return; + } + + var data = await rels.ToArray(); + var filename = $"{Guid.NewGuid()}.csv"; + var mimeCsv = "text/csv"; + + await Results.File(data!, mimeCsv, filename, enableRangeProcessing: true).ExecuteAsync(context); + data = null; + DocsExtensions.ForceGarbageCollection(); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [Authorize()] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetRelRicercaDocumentAsync( + HttpContext context, + [FromBody] RelTestataRicercaRequest request, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var rels = await handler.Send(request.Map(authInfo, null, null)); + if (rels == null || rels.Count == 0) + return NotFound(); + + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + + var dataSet = rels.RelTestate!.FillOneSheet(); + var content = dataSet.ToExcel(); + if (binary == null) + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(content.ToArray()) }); + else + return Results.File(content!, mime, filename); + } + #endregion +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Extensions/FattureExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Extensions/FattureExtensions.cs new file mode 100644 index 0000000..5696dc6 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Extensions/FattureExtensions.cs @@ -0,0 +1,191 @@ +using System.Data; +using System.IO.Compression; +using System.Text.RegularExpressions; +using PortaleFatture.BE.Api.Infrastructure.Documenti; +using PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Queries; +using PortaleFatture.BE.Infrastructure.Gateway.Storage; + +namespace PortaleFatture.BE.Api.Modules.Fatture.Extensions; + +public static class FattureExtensions +{ + public static bool IsNotEmpty(this List>? model) + { + if (model == null) + return false; + if (model.Count == 0) + return false; + var count = 0; + foreach (var item in model) + count += item.Count(); + + if (count == 0) + return false; + return true; + } + + public static byte[] ReportFattureModuloCommessa(this List> commesse, string month) + { + DataSet? dataSet = new(); + for (var i = 0; i < commesse.Count; i++) + { + if (i == 0) + dataSet.Tables.Add(commesse[i]!.FillTableWithTotalsRel(0, $"Commesse {month}")); + else if (i == 1) + dataSet.Tables.Add(commesse[i]!.FillTableWithTotalsRel(0, $"Commesse stimate {month}")); + else if (i == 2) + dataSet.Tables.Add(commesse[i]!.FillTableWithTotalsRel(0, $"Commesse stimate fatt. {month}")); + else if (i == 3) + dataSet.Tables.Add(commesse[i]!.FillTableWithTotalsRel(0, $"Commesse fatt. {month}")); + else + dataSet.Tables.Add(commesse[i]!.FillTableWithTotalsRel(0, $"Commesse non fatt. {month}")); + } + + using var memory = dataSet!.ToExcel(); + return memory.ToArray(); + } + + public static byte[] ReportFattureAcconto(this List> commesse, string month) + { + DataSet? dataSet = new(); + for (var i = 0; i < commesse.Count; i++) + dataSet.Tables.Add(commesse[i]!.FillTableWithTotalsRel(0, $"Acconto {month}")); + using var memory = dataSet!.ToExcel(); + return memory.ToArray(); + } + + public static byte[] ReportFattureRel(this List> fatture, string month, string tipologia) + { + DataSet? dataSet = new(); + for (var i = 0; i < fatture.Count; i++) + { + if (i == 0) + dataSet.Tables.Add(fatture[i]!.FillTableWithTotalsRel(9, $"Regolari Esecuzioni {month}")); + else if (i == 1) + dataSet.Tables.Add(fatture[i]!.FillTableWithTotalsRel(9, $"Enti Fatturabili {month}")); + else + dataSet.Tables.Add(fatture[i]!.FillTableWithTotalsRel(9, $"Note di Credito {month}")); + } + + using var memory = dataSet!.ToExcel(); + return memory.ToArray(); + } + + public static FattureQueryRicerca Map(this FatturaRicercaRequest req, AuthenticationInfo authInfo) + { + return new FattureQueryRicerca(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdEnti = req.IdEnti, + TipologiaFattura = req.TipologiaFattura + }; + } + public static FattureRelExcelQuery Mapv2(this FatturaRicercaRequest req, AuthenticationInfo authInfo, string tipologiaFattura) + { + return new FattureRelExcelQuery(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdEnti = req.IdEnti, + TipologiaFattura = tipologiaFattura + }; + } + + public static FattureCommessaExcelQuery Mapv3(this FatturaRicercaRequest req, AuthenticationInfo authInfo) + { + return new FattureCommessaExcelQuery(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdEnti = req.IdEnti + }; + } + + public static FattureAccontoExcelQuery Mapv4(this FatturaRicercaRequest req, AuthenticationInfo authInfo) + { + return new FattureAccontoExcelQuery(authInfo) + { + Anno = req.Anno, + Mese = req.Mese, + IdEnti = req.IdEnti + }; + } + + public static IEnumerable Map(this FattureListaDto model) + { + var result = new List(); + foreach (var item in model) + { + foreach (var pos in item.fattura!.Posizioni!) + { + result.Add(new FattureExcel() + { + Numero = item.fattura!.Numero, + Posizione = pos.CodiceMateriale, + Totale = pos.Imponibile.ToString("0.00"), + }); + } + result.Add(new FattureExcel() + { + Causale = item.fattura!.Causale, + DataFattura = item.fattura!.DataFattura, + Divisa = item.fattura!.Divisa, + IdContratto = item.fattura!.IdContratto, + Numero = item.fattura!.Numero, + IstitutioID = item.fattura.IstitutioID, + MetodoPagamento = item.fattura.MetodoPagamento, + OnboardingTokenID = item.fattura.OnboardingTokenID, + Prodotto = item.fattura.Prodotto, + RagioneSociale = item.fattura.RagioneSociale, + TipologiaFattura = item.fattura.TipologiaFattura, + TipoContratto = item.fattura.TipoContratto, + Totale = item.fattura.Totale.ToString("0.00"), + Identificativo = item.fattura.Identificativo, + Sollecito = item.fattura.Sollecito, + Split = item.fattura.Split, + TipoDocumento = item.fattura.TipoDocumento, + Posizione = "totale:", + }); + + result.Add(new FattureExcel()); + } + return result; + } + + public static byte[] CreateZip(this + Dictionary reports, + ILogger logger, + string extension = ".xlsx") + { + byte[] zipBytes; + using var memoryStreamZip = new MemoryStream(); + { + using var zipArchive = new ZipArchive(memoryStreamZip, ZipArchiveMode.Create, false); + { + memoryStreamZip.Position = 0; + foreach (var report in reports!) + { + try + { + zipArchive.AddFile(report.Key + extension, report.Value); + } + catch + { + var msg = $"Errore nel legger il file {report.Key}!"; + logger.LogError(msg); + } + } + zipArchive.Dispose(); + } + zipBytes = memoryStreamZip.ToArray(); + memoryStreamZip.Flush(); + } + return zipBytes; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureEndpoints.cs new file mode 100644 index 0000000..aeed013 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureEndpoints.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.Fatture; + +public partial class FattureModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + endpointRouteBuilder + .MapPost("api/fatture", PostFattureByRicercaAsync) + .WithName("Permette di ottenere le fatture per ricerca") + .SetOpenApi(Module.DatiFattureLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/fatture/download", PostFattureExcelByRicercaAsync) + .WithName("Permette di ottenere le fatture excel per ricerca") + .SetOpenApi(Module.DatiFattureLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/fatture/report", PostFattureReportByRicercaAsync) + .WithName("Permette di ottenere le fatture excel-report per ricerca") + .SetOpenApi(Module.DatiFattureLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/fatture/tipologia", PostTipologiaFatture) + .WithName("Permette di visualizzare la tipologia fatture") + .SetOpenApi(Module.DatiFattureLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureModule.cs new file mode 100644 index 0000000..289626c --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/FattureModule.cs @@ -0,0 +1,158 @@ +using DocumentFormat.OpenXml.Bibliography; +using System.Text.RegularExpressions; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Infrastructure.Documenti; +using PortaleFatture.BE.Api.Modules.Fatture.Extensions; +using PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.DatiRel; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Fatture.Dto; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.Fatture; + +public partial class FattureModule +{ + + #region pagoPA + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> PostTipologiaFatture( + HttpContext context, + [FromBody] TipologiaFattureRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var tipoFattura = await handler.Send(new TipoFatturaQueryGetAll(authInfo, request.Anno, request.Mese)); + if (tipoFattura.IsNullNotAny()) + return NotFound(); + return Ok(tipoFattura); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> PostFattureByRicercaAsync( + HttpContext context, + [FromBody] FatturaRicercaRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var fatture = await handler.Send(request.Map(authInfo)); + if (fatture == null || !fatture!.Any()) + return NotFound(); + return Ok(fatture); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PostFattureExcelByRicercaAsync( + HttpContext context, + [FromBody] FatturaRicercaRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var fatture = await handler.Send(request.Map(authInfo)); + if (fatture == null || !fatture!.Any()) + return NotFound(); + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + + var dataSet = fatture.Map()!.FillOneSheetv2(); + var content = dataSet.ToExcel(); + var result = new DisposableStreamResult(content, mime) + { + FileDownloadName = filename + }; + return Results.Stream(result.FileStream, result.ContentType, result.FileDownloadName); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task PostFattureReportByRicercaAsync( + HttpContext context, + [FromBody] FatturaRicercaRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] ILogger logger, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + if (request.TipologiaFattura!.IsNullNotAny()) + return NotFound(); + + Dictionary? reports = []; + + foreach (var tipologia in request.TipologiaFattura!) + { + var month = request.Mese.GetMonth(); + var year = request.Anno; + switch (tipologia) + { + case TipologiaFattura.PRIMOSALDO: + var fatture = await handler.Send(request.Mapv2(authInfo, tipologia)); + if (fatture.IsNotEmpty()) + reports.Add($"Lista {tipologia} {year} {month}", fatture!.ReportFattureRel(month, tipologia)); + break; + case TipologiaFattura.SECONDOSALDO: + fatture = await handler.Send(request.Mapv2(authInfo, tipologia)); + if (fatture.IsNotEmpty()) + reports.Add($"Lista {tipologia} {year} {month}", fatture!.ReportFattureRel(request.Mese.GetMonth(), tipologia)); + break; + case TipologiaFattura.ANTICIPO: + var commesse = await handler.Send(request.Mapv3(authInfo)); + if (commesse.IsNotEmpty()) + reports.Add($"Lista ANTICIPO {year} {month}", commesse!.ReportFattureModuloCommessa(request.Mese.GetMonth())); + break; + case TipologiaFattura.ACCONTO: + var acconto = await handler.Send(request.Mapv4(authInfo)); + if (acconto.IsNotEmpty()) + reports.Add($"Lista ACCONTO {year} {month}", acconto!.ReportFattureAcconto(request.Mese.GetMonth())); + break; + default: + break; + } + } + + if (reports.Count > 0) + { + var fileBytes = reports.CreateZip(logger); + var mime = "application/zip"; + var filename = $"{Guid.NewGuid()}.zip"; + return Results.File(fileBytes!, mime, filename); + } + + return NotFound(); + } + #endregion +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/FatturaRicercaRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/FatturaRicercaRequest.cs new file mode 100644 index 0000000..5880d7d --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/FatturaRicercaRequest.cs @@ -0,0 +1,22 @@ +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class FatturaRicercaRequest +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + + private string[]? _idEnti; + public string[]? IdEnti + { + get { return _idEnti; } + set { _idEnti = value!.IsNullNotAny() ? null : value; } + } + private string[]? _tipologiaFattura; + public string[]? TipologiaFattura + { + get { return _tipologiaFattura; } + set { _tipologiaFattura = value!.IsNullNotAny() ? null : value; } + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/TipologiaFattureRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/TipologiaFattureRequest.cs new file mode 100644 index 0000000..3f30805 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Fatture/Payload/Request/TipologiaFattureRequest.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class TipologiaFattureRequest +{ + public int Anno { get; set; } + public int Mese { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs new file mode 100644 index 0000000..6501bfe --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs @@ -0,0 +1,82 @@ +using PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; + +namespace PortaleFatture.BE.Api.Modules.Notifiche.Extensions; + +public static class NotificaExtensions +{ + public static NotificaQueryGetByConsolidatore Map2(this NotificheRicercaRequestPagoPA req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new NotificaQueryGetByConsolidatore(authInfo) + { + AnnoValidita = req.Anno, + Cap = req.Cap, + MeseValidita = req.Mese, + Page = page, + Prodotto = req.Prodotto, + Profilo = req.Profilo, + Size = pageSize, + TipoNotifica = req.TipoNotifica, + StatoContestazione = req.StatoContestazione, + Iun = req.Iun, + RecipientId = req.RecipientId + }; + } + + public static NotificaQueryGetByRecapitista Map2(this NotificheRicercaRequest req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new NotificaQueryGetByRecapitista(authInfo) + { + AnnoValidita = req.Anno, + Cap = req.Cap, + MeseValidita = req.Mese, + Page = page, + Prodotto = req.Prodotto, + Profilo = req.Profilo, + Size = pageSize, + TipoNotifica = req.TipoNotifica, + StatoContestazione = req.StatoContestazione, + Iun = req.Iun, + RecipientId = req.RecipientId + }; + } + + public static NotificaQueryGetByIdEnte Map(this NotificheRicercaRequest req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new NotificaQueryGetByIdEnte(authInfo) + { + AnnoValidita = req.Anno, + Cap = req.Cap, + MeseValidita = req.Mese, + Page = page, + Prodotto = req.Prodotto, + Profilo = req.Profilo, + Size = pageSize, + TipoNotifica = req.TipoNotifica, + StatoContestazione = req.StatoContestazione, + Iun = req.Iun, + RecipientId = req.RecipientId + }; + } + public static NotificaQueryGetByListaEnti Map(this NotificheRicercaRequestPagoPA req, AuthenticationInfo authInfo, int? page, int? pageSize) + { + return new NotificaQueryGetByListaEnti(authInfo) + { + AnnoValidita = req.Anno, + Cap = req.Cap, + MeseValidita = req.Mese, + Page = page, + Prodotto = req.Prodotto, + Profilo = req.Profilo, + Size = pageSize, + TipoNotifica = req.TipoNotifica, + StatoContestazione = req.StatoContestazione, + Iun = req.Iun, + EntiIds = req.IdEnti, + RecipientId = req.RecipientId, + Consolidatori = req.Consolidatori, + Recapitisti = req.Recapitisti + }; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaEndpoints.cs new file mode 100644 index 0000000..2cf43e9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaEndpoints.cs @@ -0,0 +1,119 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.Notifiche; + +public partial class NotificaModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + #region pagoPA + endpointRouteBuilder + .MapPost("api/notifiche/pagopa", GetPagoPANotificheByRicercaAsync) + .WithName("Permette di ottenere le notifiche dell'ente per ricerca PagoPA") + .SetOpenApi(Module.DatiNotificaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/notifiche/pagopa/contestazione/{idNotifica}", GetPagoPAContestazioneAsync) + .WithName("Permette di gestire i dati relativi ad una singola contestazione via PagoPA") + .SetOpenApi(Module.DatiNotificaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPut("api/notifiche/pagopa/contestazione", UpdatePagoPAContestazioneAsync) + .WithName("Permette di modificare i dati relativi alla contestazione via PagoPA.") + .SetOpenApi(Module.DatiNotificaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/notifiche/pagopa/documento/ricerca", GetPagoPANotificheRicercaDocumentAsync) + .WithName("Permette di ottenere il file excel/csv per le notifiche per ricerca via PagoPA.") + .SetOpenApi(Module.DatiNotificaLabelPagoPA) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + #region consolidatore + endpointRouteBuilder + .MapPost("api/notifiche/consolidatore", GetConsolidatoriNotificheByRicercaAsync) + .WithName("Permette di ottenere le notifiche del consolidatore per ricerca") + .SetOpenApi(Module.DatiNotificaLabelConsolidatori) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/notifiche/consolidatore/documento/ricerca", GetConsolidatoriNotificheRicercaDocumentAsync) + .WithName("Permette di ottenere il file excel per le notifiche per ricerca via consolidatore.") + .SetOpenApi(Module.DatiNotificaLabelConsolidatori) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/notifiche/consolidatore/contestazione/{idNotifica}", GetConsolidatoriContestazioneAsync) + .WithName("Permette di gestire i dati relativi ad una singola contestazione via consolidatore.") + .SetOpenApi(Module.DatiNotificaLabelConsolidatori) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPut("api/notifiche/consolidatore/contestazione", UpdateConsolidatoreContestazioneAsync) + .WithName("Permette di modificare i dati relativi alla contestazione via consolidatore.") + .SetOpenApi(Module.DatiNotificaLabelConsolidatori) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + #region recapitista + endpointRouteBuilder + .MapPost("api/notifiche/recapitista", GetRecapitistiNotificheByRicercaAsync) + .WithName("Permette di ottenere le notifiche del recapitista per ricerca") + .SetOpenApi(Module.DatiNotificaLabelRecapitisti) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/notifiche/recapitista/contestazione/{idNotifica}", GetRecapitistiContestazioneAsync) + .WithName("Permette di gestire i dati relativi ad una singola contestazione via recapitista.") + .SetOpenApi(Module.DatiNotificaLabelRecapitisti) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPut("api/notifiche/recapitista/contestazione", UpdateRecapitistaContestazioneAsync) + .WithName("Permette di modificare i dati relativi alla contestazione via recapitista.") + .SetOpenApi(Module.DatiNotificaLabelRecapitisti) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/notifiche/recapitista/documento/ricerca", GetRecapitistaNotificheRicercaDocumentAsync) + .WithName("Permette di ottenere il file excel per le notifiche per ricerca via recapitista.") + .SetOpenApi(Module.DatiNotificaLabelRecapitisti) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + + #region ente + + endpointRouteBuilder + .MapPost("api/notifiche/ente", GetNotificheByRicercaAsync) + .WithName("Permette di ottenere le notiifche dell'ente per ricerca") + .SetOpenApi(Module.DatiNotificaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/notifiche/ente/documento/ricerca", GetNotificheRicercaDocumentAsync) + .WithName("Permette di ottenere il file excel/csv per le notifiche per ricerca") + .SetOpenApi(Module.DatiNotificaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/notifiche/contestazione", CreateContestazioneAsync) + .WithName("Permette di creare i dati relativi alla contestazione.") + .SetOpenApi(Module.DatiNotificaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPut("api/notifiche/contestazione", UpdateContestazioneAsync) + .WithName("Permette di modificare i dati relativi alla contestazione.") + .SetOpenApi(Module.DatiNotificaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/notifiche/contestazione/{idNotifica}", GetContestazioneAsync) + .WithName("Permette di gestire i dati relativi ad una singola contestazione.") + .SetOpenApi(Module.DatiNotificaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + #endregion + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs new file mode 100644 index 0000000..900c446 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs @@ -0,0 +1,578 @@ +using System.Globalization; +using CsvHelper; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Infrastructure.Documenti; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Request; +using PortaleFatture.BE.Api.Modules.Notifiche.Extensions; +using PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Documenti.Common; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Dto; +using PortaleFatture.BE.Infrastructure.Common.Notifiche.Queries; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.Notifiche; + + +public partial class NotificaModule +{ + #region pagoPA + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPANotificheByRicercaAsync( + HttpContext context, + [FromBody] NotificheRicercaRequestPagoPA request, + [FromQuery] int page, + [FromQuery] int pageSize, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map(authInfo, page, pageSize)); + if (notifiche == null || notifiche.Count == 0) + return NotFound(); + return Ok(notifiche); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetPagoPAContestazioneAsync( + HttpContext context, + [FromRoute] string idNotifica, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = new AzioneContestazioneQueryGetByIdNotifica(authInfo, idNotifica); + var azione = await handler.Send(command); + + Contestazione contestazione; + if (azione!.Contestazione == null) + contestazione = new Contestazione() + { + IdNotifica = idNotifica, + StatoContestazione = azione!.Notifica!.StatoContestazione, + Anno = Convert.ToInt16(azione!.Notifica.Anno), + Mese = Convert.ToInt16(azione!.Notifica.Mese), + }; + else + contestazione = azione!.Contestazione; + + var response = new ContestazioneResponse() + { + Contestazione = contestazione, + Modifica = azione!.CreazionePermessa, + Chiusura = azione!.ChiusuraPermessa, + Risposta = azione!.RispostaPermessa + }; + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> UpdatePagoPAContestazioneAsync( + HttpContext context, + [FromBody] ContestazionePagoPAUpdateRequest req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + + var command = new ContestazioneUpdatePagoPACommand(authInfo, req.IdNotifica) + { + NoteSend = req.NoteSend, + Onere = req.Onere, + StatoContestazione = req.StatoContestazione + }; + + var contestazione = await handler.Send(command); + return Ok(contestazione); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetPagoPANotificheRicercaDocumentAsync( + HttpContext context, + [FromBody] NotificheRicercaRequestPagoPA request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler, + [FromQuery] bool? binary = null) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map(authInfo, null, null)); + if (notifiche == null || notifiche.Count == 0) + { + await Results.NotFound("Data not found").ExecuteAsync(context); + return; + } + + var data = await notifiche.Notifiche!.ToArray(); + + var filename = $"{Guid.NewGuid()}.csv"; + var mimeCsv = "text/csv"; + + await Results.File(data!, mimeCsv, filename, enableRangeProcessing: true).ExecuteAsync(context); + data = null; + DocsExtensions.ForceGarbageCollection(); + } + #endregion + + #region consolidatore + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCareConsolidatorePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + + private async Task, NotFound>> UpdateConsolidatoreContestazioneAsync( + HttpContext context, + [FromBody] ContestazioneConsolidatori req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + + var command = new ContestazioneUpdateConsolidatoreCommand(authInfo, req.IdNotifica) + { + NoteConsolidatore = req.Risposta, + StatoContestazione = req.StatoContestazione + }; + + var contestazione = await handler.Send(command); + return Ok(contestazione); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareConsolidatorePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetConsolidatoriContestazioneAsync( + HttpContext context, + [FromRoute] string idNotifica, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = new AzioneContestazioneQueryGetByIdNotifica(authInfo, idNotifica); + var azione = await handler.Send(command); + + Contestazione contestazione; + if (azione!.Contestazione == null) + contestazione = new Contestazione() + { + IdNotifica = idNotifica, + StatoContestazione = azione!.Notifica!.StatoContestazione, + Anno = Convert.ToInt16(azione!.Notifica.Anno), + Mese = Convert.ToInt16(azione!.Notifica.Mese), + }; + else + contestazione = azione!.Contestazione; + + var response = new ContestazioneResponse() + { + Contestazione = contestazione, + Modifica = azione!.CreazionePermessa, + Chiusura = azione!.ChiusuraPermessa, + Risposta = azione!.RispostaPermessa + }; + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareConsolidatorePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetConsolidatoriNotificheRicercaDocumentAsync( + HttpContext context, + [FromBody] NotificheRicercaRequestPagoPA request, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map2(authInfo, null, null)); + if (notifiche == null || notifiche.Count == 0) + return NotFound(); + + + if (binary == null) + { + byte[] data; + using (var stream = new MemoryStream()) + using (TextWriter textWriter = new StreamWriter(stream)) + using (var csv = new CsvWriter(textWriter, new CultureInfo("it-IT"))) + { + csv.WriteRecords(notifiche.Notifiche!); + textWriter.Flush(); + data = stream.ToArray(); + } + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(data) }); + } + else if (binary == true) + { + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + var dataSet = notifiche.Notifiche!.FillOneSheetRECCON(); + var content = dataSet.ToExcel(); + return Results.File(content!, mime, filename); + } + else + { + var mime = "text/csv"; + var filename = $"{Guid.NewGuid()}.csv"; + byte[] data; + using (var stream = new MemoryStream()) + using (TextWriter textWriter = new StreamWriter(stream)) + using (var csv = new CsvWriter(textWriter, new CultureInfo("it-IT"))) + { + csv.WriteRecords(notifiche.Notifiche!); + textWriter.Flush(); + data = stream.ToArray(); + } + return Results.File(data!, mime, filename); + } + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareConsolidatorePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetConsolidatoriNotificheByRicercaAsync( + HttpContext context, + [FromBody] NotificheRicercaRequestPagoPA request, + [FromQuery] int page, + [FromQuery] int pageSize, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map2(authInfo, page, pageSize)); + if (notifiche == null || notifiche.Count == 0) + return NotFound(); + return Ok(notifiche); + } + + #endregion + #region recapitisti + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareRecapitistaPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetRecapitistaNotificheRicercaDocumentAsync( + HttpContext context, + [FromBody] NotificheRicercaRequest request, + [FromQuery] bool? binary, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map2(authInfo, null, null)); + if (notifiche == null || notifiche.Count == 0) + return NotFound(); + + + if (binary == null) + { + byte[] data; + using (var stream = new MemoryStream()) + using (TextWriter textWriter = new StreamWriter(stream)) + using (var csv = new CsvWriter(textWriter, new CultureInfo("it-IT"))) + { + csv.WriteRecords(notifiche.Notifiche!); + textWriter.Flush(); + data = stream.ToArray(); + } + return Ok(new DocumentDto() { Documento = Convert.ToBase64String(data) }); + } + else if (binary == true) + { + var mime = "application/vnd.ms-excel"; + var filename = $"{Guid.NewGuid()}.xlsx"; + var dataSet = notifiche.Notifiche!.FillOneSheetRECCON(); + var content = dataSet.ToExcel(); + return Results.File(content!, mime, filename); + } + else + { + var mime = "text/csv"; + var filename = $"{Guid.NewGuid()}.csv"; + byte[] data; + using (var stream = new MemoryStream()) + using (TextWriter textWriter = new StreamWriter(stream)) + using (var csv = new CsvWriter(textWriter, new CultureInfo("it-IT"))) + { + csv.WriteRecords(notifiche.Notifiche!); + textWriter.Flush(); + data = stream.ToArray(); + } + return Results.File(data!, mime, filename); + } + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareRecapitistaPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetRecapitistiContestazioneAsync( + HttpContext context, + [FromRoute] string idNotifica, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = new AzioneContestazioneQueryGetByIdNotifica(authInfo, idNotifica); + var azione = await handler.Send(command); + + Contestazione contestazione; + if (azione!.Contestazione == null) + contestazione = new Contestazione() + { + IdNotifica = idNotifica, + StatoContestazione = azione!.Notifica!.StatoContestazione, + Anno = Convert.ToInt16(azione!.Notifica.Anno), + Mese = Convert.ToInt16(azione!.Notifica.Mese), + }; + else + contestazione = azione!.Contestazione; + + var response = new ContestazioneResponse() + { + Contestazione = contestazione, + Modifica = azione!.CreazionePermessa, + Chiusura = azione!.ChiusuraPermessa, + Risposta = azione!.RispostaPermessa + }; + return Ok(response); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareRecapitistaPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetRecapitistiNotificheByRicercaAsync( + HttpContext context, + [FromBody] NotificheRicercaRequest request, + [FromQuery] int page, + [FromQuery] int pageSize, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map2(authInfo, page, pageSize)); + if (notifiche == null || notifiche.Count == 0) + return NotFound(); + return Ok(notifiche); + } + + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCareRecapitistaPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> UpdateRecapitistaContestazioneAsync( + HttpContext context, + [FromBody] ContestazioneRecapitisti req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + + var command = new ContestazioneUpdateRecapitistaCommand(authInfo, req.IdNotifica) + { + NoteRecapitista = req.Risposta, + StatoContestazione = req.StatoContestazione + }; + + var contestazione = await handler.Send(command); + return Ok(contestazione); + } + #endregion + + #region enti + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetNotificheByRicercaAsync( + HttpContext context, + [FromBody] NotificheRicercaRequest request, + [FromQuery] int page, + [FromQuery] int pageSize, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map(authInfo, page, pageSize)); + if (notifiche == null || notifiche.Count == 0) + return NotFound(); + return Ok(notifiche); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task GetNotificheRicercaDocumentAsync( + HttpContext context, + [FromBody] NotificheRicercaRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler, + [FromQuery] bool? binary = null) + { + var authInfo = context.GetAuthInfo(); + var notifiche = await handler.Send(request.Map(authInfo, null, null)); + if (notifiche == null || notifiche.Count == 0) + { + await Results.NotFound("File not found").ExecuteAsync(context); + return; + } + + var data = await notifiche.Notifiche!.ToArray(); + + var filename = $"{Guid.NewGuid()}.csv"; + var mimeCsv = "text/csv"; + + await Results.File(data!, mimeCsv, filename, enableRangeProcessing: true).ExecuteAsync(context); + data = null; + DocsExtensions.ForceGarbageCollection(); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> CreateContestazioneAsync( + HttpContext context, + [FromBody] ContestazioneCreateRequest req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + + var command = new ContestazioneCreateCommand(authInfo) + { + IdNotifica = req.IdNotifica, + NoteEnte = req.NoteEnte, + TipoContestazione = req.TipoContestazione + }; + + var contestazione = await handler.Send(command); + return Ok(contestazione); + } + + [Authorize(Roles = $"{Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> UpdateContestazioneAsync( + HttpContext context, + [FromBody] ContestazioneUpdateRequest req, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + + var command = new ContestazioneUpdateCommand(authInfo, req.IdNotifica) + { + NoteEnte = req.NoteEnte, + RispostaEnte = req.RispostaEnte, + StatoContestazione = req.StatoContestazione, + Onere = req.Onere + }; + + var contestazione = await handler.Send(command); + return Ok(contestazione); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCarePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetContestazioneAsync( + HttpContext context, + [FromRoute] string idNotifica, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var command = new AzioneContestazioneQueryGetByIdNotifica(authInfo, idNotifica); + var azione = await handler.Send(command); + + Contestazione contestazione; + if (azione!.Contestazione == null) + contestazione = new Contestazione() + { + IdNotifica = idNotifica, + StatoContestazione = azione!.Notifica!.StatoContestazione, + Anno = Convert.ToInt16(azione!.Notifica.Anno), + Mese = Convert.ToInt16(azione!.Notifica.Mese), + }; + else + contestazione = azione!.Contestazione; + + var response = new ContestazioneResponse() + { + Contestazione = contestazione, + Modifica = azione!.CreazionePermessa, + Chiusura = azione!.ChiusuraPermessa, + Risposta = azione!.RispostaPermessa + }; + return Ok(response); + } + #endregion +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneConsolidatori.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneConsolidatori.cs new file mode 100644 index 0000000..6b9c383 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneConsolidatori.cs @@ -0,0 +1,10 @@ +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class ContestazioneConsolidatori +{ + public string? IdNotifica { get; set; } + public string? Risposta { get; set; } + public short StatoContestazione { get; set; } = (short)PortaleFatture.BE.Core.Entities.Notifiche.StatoContestazione.RispostaConsolidatore; +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneCreateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneCreateRequest.cs new file mode 100644 index 0000000..cd386c4 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneCreateRequest.cs @@ -0,0 +1,8 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class ContestazioneCreateRequest +{ + public int TipoContestazione { get; set; } + public string? IdNotifica { get; set; } + public string? NoteEnte { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazionePagoPAUpdateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazionePagoPAUpdateRequest.cs new file mode 100644 index 0000000..9e5d1c7 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazionePagoPAUpdateRequest.cs @@ -0,0 +1,11 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class ContestazionePagoPAUpdateRequest +{ + public string? IdNotifica { get; set; } + + /// PA,REC,CON + public string? Onere { get; set; } + public string? NoteSend { get; set; } + public short StatoContestazione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneRecapitisti.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneRecapitisti.cs new file mode 100644 index 0000000..09eda4d --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneRecapitisti.cs @@ -0,0 +1,10 @@ +using PortaleFatture.BE.Core.Entities.Notifiche; + +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class ContestazioneRecapitisti +{ + public string? IdNotifica { get; set; } + public string? Risposta { get; set; } + public short StatoContestazione { get; set; } = (short)PortaleFatture.BE.Core.Entities.Notifiche.StatoContestazione.RispostaRecapitista; +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneUpdateRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneUpdateRequest.cs new file mode 100644 index 0000000..07481ac --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/ContestazioneUpdateRequest.cs @@ -0,0 +1,10 @@ +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class ContestazioneUpdateRequest +{ + public string? IdNotifica { get; set; } + public string? NoteEnte { get; set; } + public string? RispostaEnte { get; set; } + public short StatoContestazione { get; set; } + public string? Onere { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequest.cs new file mode 100644 index 0000000..cd07e1f --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequest.cs @@ -0,0 +1,15 @@ +using PortaleFatture.BE.Core.Entities.Notifiche; +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class NotificheRicercaRequest +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? Prodotto { get; set; } + public string? Cap { get; set; } + public string? Profilo { get; set; } + public TipoNotifica? TipoNotifica { get; set; } + public int[]? StatoContestazione { get; set; } + public string? Iun { get; set; } + public string? RecipientId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequestPagoPA.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequestPagoPA.cs new file mode 100644 index 0000000..5e16620 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Request/NotificheRicercaRequestPagoPA.cs @@ -0,0 +1,38 @@ +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Extensions; +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class NotificheRicercaRequestPagoPA +{ + public int? Anno { get; set; } + public int? Mese { get; set; } + public string? Prodotto { get; set; } + public string? Cap { get; set; } + public string? Profilo { get; set; } + public TipoNotifica? TipoNotifica { get; set; } + public int[]? StatoContestazione { get; set; } + public string? Iun { get; set; } + public string? RecipientId { get; set; } + + private string[]? _idEnti; + public string[]? IdEnti + { + get { return _idEnti; } + set { _idEnti = value!.IsNullNotAny() ? null : value; } + } + + private string[]? _recapitisti; + public string[]? Recapitisti + { + get { return _recapitisti; } + set { _recapitisti = value!.IsNullNotAny() ? null : value; } + } + + + private string[]? _consolidatori; + public string[]? Consolidatori + { + get { return _consolidatori; } + set { _consolidatori = value!.IsNullNotAny() ? null : value; } + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Response/ContestazioneResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Response/ContestazioneResponse.cs new file mode 100644 index 0000000..6ed00ab --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Payload/Response/ContestazioneResponse.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using PortaleFatture.BE.Core.Entities.Notifiche; +namespace PortaleFatture.BE.Api.Modules.Notifiche.Payload.Request; + +public class ContestazioneResponse +{ + [JsonPropertyOrder(-1)] + public Contestazione? Contestazione { get; set; } + + [JsonPropertyOrder(-2)] + public bool Chiusura { get; set; } + + [JsonPropertyOrder(-3)] + public bool Modifica { get; set; } + + [JsonPropertyOrder(-3)] + public bool Risposta { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Extensions/TipologieExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Extensions/TipologieExtensions.cs new file mode 100644 index 0000000..656aea0 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Extensions/TipologieExtensions.cs @@ -0,0 +1,26 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Response; +using PortaleFatture.BE.Core.Entities.Scadenziari; +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Api.Modules.DatiFatturazioni.Extensions; +public static class TipologieExtensions +{ + private static CultureInfo culture = new("it-IT"); + + public static IEnumerable Mapper(this IEnumerable models) + { + return models.Select(x => + new CalendarioContestazioniResponse() + { + AnnoContestazione = x.AnnoContestazione, + DataFine = x.DataFine.ToString("dd MMMM yyyy",culture), + DataInizio = x.DataInizio.ToString("dd MMMM yyyy", culture), + MeseContestazione = x.MeseContestazione.GetMonth(), + DataRecapitistaFine = x.DataVerifica.ToString("dd MMMM yyyy", culture), + DataRecapitistaInizio = x.DataFine.AddDays(1).ToString("dd MMMM yyyy", culture) + } + ); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneProfiloRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneProfiloRequest.cs new file mode 100644 index 0000000..882071b --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneProfiloRequest.cs @@ -0,0 +1,23 @@ +using PortaleFatture.BE.Core.Extensions; + +namespace PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Request; + +public sealed class EnteRicercaByDescrizioneProfiloRequest +{ + + private string[]? _idEnti; + public string[]? IdEnti + { + get { return _idEnti; } + set { _idEnti = value!.IsNullNotAny() ? null : value; } + } + public string? Prodotto { get; set; } + public string? Profilo { get; set; } +} + +public sealed class EnteRicercaByRequest +{ + public string? Descrizione { get; set; } + public string? Prodotto { get; set; } + public string? Profilo { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneRequest.cs new file mode 100644 index 0000000..d0ae421 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByDescrizioneRequest.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Request; + +public sealed class EnteRicercaByDescrizioneRequest +{ + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByRecapitistiConsolidatoriRequest.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByRecapitistiConsolidatoriRequest.cs new file mode 100644 index 0000000..06e1fc0 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Request/EnteRicercaByRecapitistiConsolidatoriRequest.cs @@ -0,0 +1,6 @@ +namespace PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Request; + +public sealed class EnteRicercaByRecapitistiConsolidatoriRequest +{ + public string? Tipo { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/CalendarioContestazioniResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/CalendarioContestazioniResponse.cs new file mode 100644 index 0000000..e020cc9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/CalendarioContestazioniResponse.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Response; + +public sealed class CalendarioContestazioniResponse +{ + public string? DataFine { get; set; } + public string? DataInizio { get; set; } + public string? MeseContestazione { get; set; } + public int AnnoContestazione { get; set; } + public string? DataRecapitistaFine { get; set; } + public string? DataRecapitistaInizio { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/EnteResponse.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/EnteResponse.cs new file mode 100644 index 0000000..0ea3c1d --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/Payload/Payload/Response/EnteResponse.cs @@ -0,0 +1,7 @@ +namespace PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Response; + +public class EnteResponse +{ + public string? IdEnte { get; set; } + public string? Descrizione { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieEndpoints.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieEndpoints.cs new file mode 100644 index 0000000..43d114f --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieEndpoints.cs @@ -0,0 +1,88 @@ +using Microsoft.AspNetCore.Cors; +using PortaleFatture.BE.Api.Infrastructure; + +namespace PortaleFatture.BE.Api.Modules.Tipologie; + +public partial class TipologieModule : Module, IRegistrableModule +{ + public void RegisterEndpoints(IEndpointRouteBuilder endpointRouteBuilder) + { + endpointRouteBuilder + .MapGet("api/tipologia/time", GetTimeAsync) + .WithName("Permette di visualizzare il timing") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/scadenziariocontestazioni", GetScadenziarioContestazioniByDescrizioneAsync) + .WithName("Permette di visualizzare lo scadenziario contestazioni") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/tipologia/enti", AllEntiByDescrizioneAsync) + .WithName("Permette di ottenere gli enti per ricerca descrizione e prodotto e profilo") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/tipologia/enti/completi", AllEntiCompletiByDescrizioneAsync) + .WithName("Permette di ottenere gli enti per ricerca descrizione") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/tipologia/enti/consolidatore/completi", AllEntiCompletiConsolidatoreByDescrizioneAsync) + .WithName("Permette di ottenere gli enti consolidatore per ricerca descrizione") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapPost("api/tipologia/enti/fornitori", AllEntiCompletiFornitoriByTipoAsync) + .WithName("Permette di ottenere gli enti fornitori per ricerca tipo") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/tipoprofilo", GetAllTipoProfiloAsync) + .WithName("Permette di ottenere i tipi profilo (institutionType) per la gestione dati commessa/fatturazione.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/tipocontratto", GetAllTipoContrattoAsync) + .WithName("Permette di ottenere i tipi contratti per la gestione dati commessa/fatturazione.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/tipocommessa", GetAllTipoCommessaAsync) + .WithName("Permette di ottenere i tipi commessa per la gestione dati commessa/fatturazione.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/prodotto", GetAllProdottoAsync) + .WithName("Permette di ottenere i tipi prodotti per la gestione dati configurazione modulo commessa.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/categoriaspedizione", GetAllCategoriaSpedizioneAsync) + .WithName("Permette di ottenere le categorie spedizione per la gestione dati configurazione modulo commessa.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/tipocontestazione", GetAllTipologiaContestazioniAsync) + .WithName("Permette di ottenere le tipologie di contestazione per la gestione delle notifiche.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + + endpointRouteBuilder + .MapGet("api/tipologia/flagcontestazione", GetAllFlagContestazioniAsync) + .WithName("Permette di ottenere i flag di contestazione per la gestione delle notifiche.") + .SetOpenApi(Module.DatiTipologiaLabel) + .WithMetadata(new EnableCorsAttribute(policyName: Module.CORSLabel)); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieExtensions.cs new file mode 100644 index 0000000..5fd70cd --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieExtensions.cs @@ -0,0 +1,16 @@ +using PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Response; +using PortaleFatture.BE.Core.Entities.SelfCare; + +namespace PortaleFatture.BE.Api.Modules.Tipologie; + +public static class TipologieExtensions +{ + public static EnteResponse Map(this Ente model) + { + return new EnteResponse + { + Descrizione = model.Descrizione, + IdEnte = model.IdEnte + }; + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieModule.cs new file mode 100644 index 0000000..60ab200 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Tipologie/TipologieModule.cs @@ -0,0 +1,253 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using PortaleFatture.BE.Api.Infrastructure; +using PortaleFatture.BE.Api.Modules.Asseverazione.Extensions; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Extensions; +using PortaleFatture.BE.Api.Modules.DatiFatturazioni.Payload.Response; +using PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Request; +using PortaleFatture.BE.Api.Modules.Tipologie.Payload.Payload.Response; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Entities.Notifiche; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Identity; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari.Queries; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; +using static Microsoft.AspNetCore.Http.TypedResults; + +namespace PortaleFatture.BE.Api.Modules.Tipologie; +public partial class TipologieModule +{ + [AllowAnonymous] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task, NotFound>> GetTimeAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + return Ok(await Task.Run(() => DateTime.UtcNow.ItalianTime())); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetScadenziarioContestazioniByDescrizioneAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var scadenziario = await handler.Send(new CalendarioContestazioneQueryGetAll(authInfo)); + if (scadenziario.IsNullNotAny()) + return NotFound(); + return Ok(scadenziario.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> AllEntiByDescrizioneAsync( + HttpContext context, + [FromBody] EnteRicercaByRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var enti = await handler.Send(new EnteQueryGetByRagioneSociale(authInfo, request.Descrizione, request.Prodotto, request.Profilo)); + if (enti.IsNullNotAny()) + return NotFound(); + return Ok(enti); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> AllEntiCompletiByDescrizioneAsync( + HttpContext context, + [FromBody] EnteRicercaByDescrizioneRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var enti = await handler.Send(new EnteQueryGetByDescrizione(authInfo, request.Descrizione)); + if (enti.IsNullNotAny()) + return NotFound(); + return Ok(enti.Select(x => x.Map())); + } + + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.PagoPAPolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> AllEntiCompletiFornitoriByTipoAsync( + HttpContext context, + [FromBody] EnteRicercaByRecapitistiConsolidatoriRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var enti = await handler.Send(new EnteQueryGetByRecapitistiConsolidatori(authInfo, request.Tipo)); + if (enti.IsNullNotAny()) + return NotFound(); + return Ok(enti.Select(x => x.Map())); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}", Policy = Module.SelfCareConsolidatorePolicy)] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> AllEntiCompletiConsolidatoreByDescrizioneAsync( + HttpContext context, + [FromBody] EnteRicercaByDescrizioneRequest request, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var authInfo = context.GetAuthInfo(); + var enti = await handler.Send(new EnteQueryGetByDescrizione(authInfo, request.Descrizione)); + if (enti.IsNullNotAny()) + return NotFound(); + return Ok(enti.Select(x => x.Map())); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllTipoProfiloAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var tipiProfilo = await handler.Send(new ProfiloQueryGetAll()); + if (tipiProfilo.IsNullNotAny()) + throw new ConfigurationException(localizer["DatiTipoProfiloMissing"]); + return Ok(tipiProfilo); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllTipoContrattoAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var tipiContratto = await handler.Send(new TipoContrattoQueryGetAll()); + if (tipiContratto.IsNullNotAny()) + throw new ConfigurationException(localizer["DatiTipoContrattoMissing"]); + return Ok(tipiContratto.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllTipoCommessaAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var tipiCommessa = await handler.Send(new TipoCommessaQueryGetAll()); + if (tipiCommessa.IsNullNotAny()) + throw new ConfigurationException(localizer["DatiTipoCommessaMissing"]); + return Ok(tipiCommessa.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllProdottoAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var prodotti = await handler.Send(new ProdottoQueryGetAll()); + if (prodotti.IsNullNotAny()) + throw new ConfigurationException(localizer["DatiProdottoMissing"]); + return Ok(prodotti.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllCategoriaSpedizioneAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var categorie = await handler.Send(new SpedizioneQueryGetAll()); + if (categorie.IsNullNotAny()) + throw new ConfigurationException(localizer["DatiProdottoMissing"]); + return Ok(categorie.Mapper()); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllTipologiaContestazioniAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var tipologie = await handler.Send(new TipoContestazioneGetAll()); + if (tipologie.IsNullNotAny()) + throw new ConfigurationException(localizer["TipoContestazioneMissing"]); + return Ok(tipologie); + } + + [Authorize(Roles = $"{Ruolo.OPERATOR}, {Ruolo.ADMIN}")] + [EnableCors(CORSLabel)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + private async Task>, NotFound>> GetAllFlagContestazioniAsync( + HttpContext context, + [FromServices] IStringLocalizer localizer, + [FromServices] IMediator handler) + { + var flags = await handler.Send(new FlagContestazioneQueryGetAll()); + if (flags.IsNullNotAny()) + throw new ConfigurationException(localizer["FlagContestazioneMissing"]); + return Ok(flags); + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/PortaleFatture.BE.Api.csproj b/src/Presentation/PortaleFatture.BE.Api/PortaleFatture.BE.Api.csproj new file mode 100644 index 0000000..50c188a --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/PortaleFatture.BE.Api.csproj @@ -0,0 +1,46 @@ + + + + net8.0 + enable + enable + 072fb2f2-e073-421a-a57d-e0c25e7517fd + Linux + ..\..\.. + + + + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + + + + + + diff --git a/src/Presentation/PortaleFatture.BE.Api/Program.cs b/src/Presentation/PortaleFatture.BE.Api/Program.cs new file mode 100644 index 0000000..6db21d9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/Program.cs @@ -0,0 +1,17 @@ +using PortaleFatture.BE.Api.Infrastructure; + +var builder = WebApplication.CreateBuilder(args); + +builder + .AddModules(); + +var configuredBuilder = builder + .Build() + .UseModules(); + + +configuredBuilder.Run(); + +public partial class Program +{ +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/appsettings.Development.json b/src/Presentation/PortaleFatture.BE.Api/appsettings.Development.json new file mode 100644 index 0000000..028c821 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/appsettings.Development.json @@ -0,0 +1,30 @@ +{ + "Logging:LogLevel:Microsoft.Hosting": "Debug", + "Logging:LogLevel:Microsoft.EntityFrameworkCore": "Debug", + "Logging:LogLevel:Microsoft.AspNetCore": "Debug", + "Logging:LogLevel:Microsoft": "Debug", + "Logging:LogLevel:Default": "Debug", + "Locale": "it-IT", + "PortaleFattureOptions": { + "ConnectionString": "ConnectionString", + "FattureSchema": "pfw", + "SelfCareSchema": "pfd", + "SelfCareUri": "SELF_CARE_URI", + "SelfCareCertEndpoint": "SELFCARE_CERT_ENDPOINT", + "SelfCareTimeOut": "SELF_CARE_TIMEOUT", + "SelfCareAudience": "SELF_CARE_AUDIENCE", + "AdminKey": "ADMIN_KEY", + "Vault": "KEY_VAULT_NAME", + "JWT:ValidIssuer": "JWT_VALID_ISSUER", + "JWT:ValidAudience": "JWT_VALID_AUDIENCE", + "JWT:Secret": "Secret", + "CORSOrigins": "CORS_ORIGINS", + "ApplicationInsights": "APPLICATION_INSIGHTS", + "AzureAd:Instance": "AZUREAD_INSTANCE", + "AzureAd:TenantId": "AZUREAD_TENANTID", + "AzureAd:ClientId": "AZUREAD_CLIENTID", + "AzureAd:AdGroup": "AZUREAD_ADGROUP", + "Storage:RelFolder": "STORAGE_REL_FOLDER", + "Storage:ConnectionString": "STORAGE_CONNECTIONSTRING" + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/appsettings.json b/src/Presentation/PortaleFatture.BE.Api/appsettings.json new file mode 100644 index 0000000..127e911 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/appsettings.json @@ -0,0 +1,30 @@ +{ + "Logging:LogLevel:Microsoft.Hosting": "Error", + "Logging:LogLevel:Microsoft.EntityFrameworkCore": "Error", + "Logging:LogLevel:Microsoft.AspNetCore": "Error", + "Logging:LogLevel:Microsoft": "Error", + "Logging:LogLevel:Default": "Error", + "Locale": "it-IT", + "PortaleFattureOptions": { + "ConnectionString": "ConnectionString", + "FattureSchema": "pfw", + "SelfCareSchema": "pfd", + "SelfCareUri": "SELF_CARE_URI", + "SelfCareCertEndpoint": "SELFCARE_CERT_ENDPOINT", + "SelfCareTimeOut": "SELF_CARE_TIMEOUT", + "SelfCareAudience": "SELF_CARE_AUDIENCE", + "AdminKey": "ADMIN_KEY", + "Vault": "KEY_VAULT_NAME", + "JWT:ValidIssuer": "JWT_VALID_ISSUER", + "JWT:ValidAudience": "JWT_VALID_AUDIENCE", + "JWT:Secret": "Secret", + "CORSOrigins": "CORS_ORIGINS", + "ApplicationInsights": "APPLICATION_INSIGHTS", + "AzureAd:Instance": "AZUREAD_INSTANCE", + "AzureAd:TenantId": "AZUREAD_TENANTID", + "AzureAd:ClientId": "AZUREAD_CLIENTID", + "AzureAd:AdGroup": "AZUREAD_ADGROUP", + "Storage:RelFolder": "STORAGE_REL_FOLDER", + "Storage:ConnectionString": "STORAGE_CONNECTIONSTRING" + } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.Api/libman.json b/src/Presentation/PortaleFatture.BE.Api/libman.json new file mode 100644 index 0000000..ceee271 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.Api/libman.json @@ -0,0 +1,5 @@ +{ + "version": "1.0", + "defaultProvider": "cdnjs", + "libraries": [] +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.EmailSender/Infrastructure/Documenti/primo_saldo.html b/src/Presentation/PortaleFatture.BE.EmailSender/Infrastructure/Documenti/primo_saldo.html new file mode 100644 index 0000000..180a395 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.EmailSender/Infrastructure/Documenti/primo_saldo.html @@ -0,0 +1,11 @@ +Gentile Aderente [RagioneSociale],
+con la presente siamo a comunicare che da oggi è disponibile sul Portale Fatturazione il documento utile ai fini dell'emissione della Regolare Esecuzione, come previsto al punto 7 dell'Allegato 4 dell'Accordo di Adesione SEND. +
+Tale documento è relativo ai servizi erogati dalla scrivente Società, in qualità di gestore di SEND, che risultano fatturabili nel mese di [Mese] [Anno] (mese di riferimento della emissione della Regolare Esecuzione). +
+Per prendere visione del documento è necessario accedere all'Area Riservata di PagoPA S.p.A e cliccare sul link “Fatturazione”, quindi accedere al Portale Fatturazione e cliccare sull'apposita sezione “Regolare Esecuzione”. +PagoPA S.p.A., al fine di agevolare l'Aderente nella predisposizione della Regolare Esecuzione, mette a disposizione il summenzionato documento che, una volta firmato dall'Aderente stesso, potrà essere utilizzato ai fini dell'emissione della Regolare Esecuzione una volta caricato sul Portale Fatturazione. +Per eventuali informazioni, o assistenza in merito al caricamento sul Portale del documento da parte dell'Aderente, è possibile contattare l'indirizzo: fatturazione@assistenza.pagopa.it +




+Cordiali saluti,
+il team di PagoPA S.p.A. \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.EmailSender/Models/Configurazione.cs b/src/Presentation/PortaleFatture.BE.EmailSender/Models/Configurazione.cs new file mode 100644 index 0000000..3bcd3c9 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.EmailSender/Models/Configurazione.cs @@ -0,0 +1,11 @@ +namespace PortaleFatture.BE.EmailSender.Models; + +public class Configurazione +{ + public string? ConnectionString { get; set; } + public string? From { get; set; } + public string? Smtp { get; set; } + public int SmtpPort { get; set; } + public string? SmtpAuth { get; set; } + public string? SmtpPassword { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.EmailSender/Models/Risposta.cs b/src/Presentation/PortaleFatture.BE.EmailSender/Models/Risposta.cs new file mode 100644 index 0000000..950f1fc --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.EmailSender/Models/Risposta.cs @@ -0,0 +1,12 @@ +namespace PortaleFatture.BE.EmailSender.Models; + +public sealed class Risposta +{ + public int Anno { get; set; } + public int Mese { get; set; } + public string? TipologiaFattura { get; set; } + public string? Data { get; set; } + public int? Ricalcola { get; set; } + public bool? DbConnection { get; set; } = true; + public string? Error { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.EmailSender/PortaleFatture.BE.EmailSender.csproj b/src/Presentation/PortaleFatture.BE.EmailSender/PortaleFatture.BE.EmailSender.csproj new file mode 100644 index 0000000..3f094b1 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.EmailSender/PortaleFatture.BE.EmailSender.csproj @@ -0,0 +1,28 @@ + + + + Exe + net8.0 + enable + enable + 380d02ea-6901-441b-94da-00108b2df000 + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/src/Presentation/PortaleFatture.BE.EmailSender/Program.cs b/src/Presentation/PortaleFatture.BE.EmailSender/Program.cs new file mode 100644 index 0000000..f81d095 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.EmailSender/Program.cs @@ -0,0 +1,119 @@ +using System.Reflection; +using Microsoft.Extensions.Configuration; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.EmailSender.Models; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Services; +using PortaleFatture.BE.Infrastructure.Common.Documenti; +using PortaleFatture.BE.Infrastructure.Gateway.Email; + +var risposta = new Risposta(); +try +{ + IConfiguration config = new ConfigurationBuilder() + .AddUserSecrets() + .Build(); + + // config + var connectionString = config.GetValue("PortaleFattureOptions:ConnectionString"); + var from = config.GetValue("PortaleFattureOptions:FROM"); + var smtp = config.GetValue("PortaleFattureOptions:SMTP"); + var smtpPort = Convert.ToInt32(config.GetValue("PortaleFattureOptions:SMTP_PORT")); + var smtpAuth = config.GetValue("PortaleFattureOptions:SMTP_AUTH"); + var smtpPassword = config.GetValue("PortaleFattureOptions:SMTP_PASSWORD"); + + var fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location); + var path = fileInfo.Directory!.FullName; + + // params + var anno = 2024; + var mese = 4; + var tipologiafattura = "PRIMO SALDO"; + var data = DateTime.UtcNow.ItalianTime().ToString("yyyy-MM-dd HH:mm:ss"); + var ricalcola = 0; + + Console.WriteLine("Ready to send"); + + // response + risposta = new Risposta() + { + Anno = anno, + Mese = mese, + TipologiaFattura = tipologiafattura, + Data = data, + Ricalcola = ricalcola + }; + + var builder = new DocumentBuilder(path); + + var subject = $"Notifica Regolare Esecuzione {tipologiafattura} Mese di {mese.GetMonth()}"; + var sender = new EmailSender(smtpSource: smtp!, + smtpPort: smtpPort!, + smtpUser: smtpAuth!, + smtpPassword: smtpPassword!, + from: from!); + + var emailService = new EmailRelService(connectionString!); + + // import csv + List enti = []; + var values = Array.Empty(); + var dir = $"Infrastructure/Documenti/"; + var fileEnti = "enti.csv"; + var filePath = Path.Combine([dir, fileEnti]); + + using (var reader = new StreamReader(filePath)) + { + var count = 0; + while (!reader.EndOfStream) + { + var line = reader.ReadLine(); + if (count == 0) + { + count++; + continue; + } + values = line!.Split(';'); + enti.Add(new RelEmail() + { + IdEnte = values[0], + IdContratto = values[1], + TipologiaFattura = values[2], + Anno = Convert.ToInt32(values[3]), + Mese = Convert.ToInt32(values[4]), + Pec = values[5] == null || values[5] == "NULL" ? string.Empty : values[5], + RagioneSociale = values[6], + }); + } + } + + var dummy = 0; + //foreach (var ente in enti!) + //{ + // var (msg, ver) = sender.SendEmail(ente.Pec!, subject, builder.CreateEmailHtml(ente)!); + // if (!ver) + // Console.WriteLine(msg); + + // emailService.InsertTracciatoEmail(new RelEmailTracking() + // { + // Data = data, + // IdContratto = ente.IdContratto, + // Invio = Convert.ToByte(ver == true ? 1 : 0), + // Anno = ente.Anno, + // Mese = ente.Mese, + // Messaggio = msg, + // Pec = ente.Pec, + // IdEnte = ente.IdEnte, + // RagioneSociale = ente.RagioneSociale, + // TipologiaFattura = ente.TipologiaFattura + // }); + //} +} +catch (Exception ex) +{ + risposta.DbConnection = false; + risposta.Error = ex.Message; + Console.WriteLine(ex.Message); +} + +Console.WriteLine(risposta.Serialize()); \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/.gitignore b/src/Presentation/PortaleFatture.BE.SendEmailFunction/.gitignore new file mode 100644 index 0000000..ff5b00c --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/.gitignore @@ -0,0 +1,264 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/Infrastructure/Documenti/primo_saldo.html b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Infrastructure/Documenti/primo_saldo.html new file mode 100644 index 0000000..180a395 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Infrastructure/Documenti/primo_saldo.html @@ -0,0 +1,11 @@ +Gentile Aderente [RagioneSociale],
+con la presente siamo a comunicare che da oggi è disponibile sul Portale Fatturazione il documento utile ai fini dell'emissione della Regolare Esecuzione, come previsto al punto 7 dell'Allegato 4 dell'Accordo di Adesione SEND. +
+Tale documento è relativo ai servizi erogati dalla scrivente Società, in qualità di gestore di SEND, che risultano fatturabili nel mese di [Mese] [Anno] (mese di riferimento della emissione della Regolare Esecuzione). +
+Per prendere visione del documento è necessario accedere all'Area Riservata di PagoPA S.p.A e cliccare sul link “Fatturazione”, quindi accedere al Portale Fatturazione e cliccare sull'apposita sezione “Regolare Esecuzione”. +PagoPA S.p.A., al fine di agevolare l'Aderente nella predisposizione della Regolare Esecuzione, mette a disposizione il summenzionato documento che, una volta firmato dall'Aderente stesso, potrà essere utilizzato ai fini dell'emissione della Regolare Esecuzione una volta caricato sul Portale Fatturazione. +Per eventuali informazioni, o assistenza in merito al caricamento sul Portale del documento da parte dell'Aderente, è possibile contattare l'indirizzo: fatturazione@assistenza.pagopa.it +




+Cordiali saluti,
+il team di PagoPA S.p.A. \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Configurazione.cs b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Configurazione.cs new file mode 100644 index 0000000..067f6a0 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Configurazione.cs @@ -0,0 +1,11 @@ +namespace PortaleFatture_BE_SendEmailFunction.Models; + +public static class Configurazione +{ + public static string? ConnectionString { get; set; } + public static string? From { get; set; } + public static string? Smtp { get; set; } + public static int SmtpPort { get; set; } + public static string? SmtpAuth { get; set; } + public static string? SmtpPassword { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Risposta.cs b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Risposta.cs new file mode 100644 index 0000000..8dfcebe --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Models/Risposta.cs @@ -0,0 +1,12 @@ +namespace PortaleFatture_BE_SendEmailFunction.Models; + +public sealed class Risposta +{ + public int Anno { get; set; } + public int Mese { get; set; } + public string? TipologiaFattura { get; set; } + public string? Data { get; set; } + public int? Ricalcola { get; set; } + public bool? DbConnection { get; set; } = true; + public string? Error { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/PortaleFatture_BE_SendEmailFunction.csproj b/src/Presentation/PortaleFatture.BE.SendEmailFunction/PortaleFatture_BE_SendEmailFunction.csproj new file mode 100644 index 0000000..4e145c1 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/PortaleFatture_BE_SendEmailFunction.csproj @@ -0,0 +1,37 @@ + + + net8.0 + v4 + Exe + enable + enable + + + + + + + + + + + Always + + + Always + Never + + + Always + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/Program.cs b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Program.cs new file mode 100644 index 0000000..51336f3 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/Program.cs @@ -0,0 +1,7 @@ +using Microsoft.Extensions.Hosting; + +var host = new HostBuilder() + .ConfigureFunctionsWorkerDefaults() + .Build(); + +host.Run(); diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/SendEmail.cs b/src/Presentation/PortaleFatture.BE.SendEmailFunction/SendEmail.cs new file mode 100644 index 0000000..bc08d15 --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/SendEmail.cs @@ -0,0 +1,126 @@ +using System.Net; +using System.Reflection; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Extensions.Logging; +using PortaleFatture.BE.Core.Entities.DatiRel.Dto; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiRel.Services; +using PortaleFatture.BE.Infrastructure.Common.Documenti; +using PortaleFatture.BE.Infrastructure.Gateway.Email; +using PortaleFatture_BE_SendEmailFunction.Models; + +namespace PortaleFatture_BE_SendEmailFunction; + +public class SendEmail(ILoggerFactory loggerFactory) +{ + private readonly ILogger _logger = loggerFactory.CreateLogger(); + + [Function("SendEmail")] + public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req) + { + var risposta = new Risposta(); + try + { + // config + Configurazione.ConnectionString = GetEnvironmentVariable("PortaleFattureOptions:ConnectionString"); + Configurazione.From = GetEnvironmentVariable("PortaleFattureOptions:FROM"); + Configurazione.Smtp = GetEnvironmentVariable("PortaleFattureOptions:SMTP"); + Configurazione.SmtpPort = Convert.ToInt32(GetEnvironmentVariable("PortaleFattureOptions:SMTP_PORT")); + Configurazione.SmtpAuth = GetEnvironmentVariable("PortaleFattureOptions:SMTP_AUTH"); + Configurazione.SmtpPassword = GetEnvironmentVariable("PortaleFattureOptions:SMTP_PASSWORD"); + if (String.IsNullOrEmpty(Configurazione.ConnectionString) || + String.IsNullOrEmpty(Configurazione.From) || + String.IsNullOrEmpty(Configurazione.Smtp) || + String.IsNullOrEmpty(Configurazione.SmtpAuth) || + String.IsNullOrEmpty(Configurazione.SmtpPassword)) + { + Configurazione.ConnectionString = GetEnvironmentVariable("CONNECTION_STRING"); + Configurazione.From = "send-fatturazione@pec.pagopa.it"; + Configurazione.Smtp = GetEnvironmentVariable("SMTP"); + Configurazione.SmtpPort = Convert.ToInt32(GetEnvironmentVariable("SMTP_PORT")); + Configurazione.SmtpAuth = GetEnvironmentVariable("SMTP_AUTH"); + Configurazione.SmtpPassword = GetEnvironmentVariable("SMTP_PASSWORD"); + }; + + + + var fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location); + string path = fileInfo.Directory!.FullName; + + // params + var anno = Convert.ToInt32(req.Query["anno"]); + var mese = Convert.ToInt32(req.Query["mese"]); + var tipologiafattura = req.Query["tipologiafattura"]; + var data = req.Query["data"]; + var ricalcola = Convert.ToInt32(req.Query["ricalcola"]); + + _logger.LogInformation("HTTP trigger function processed a request."); + + // response + risposta = new Risposta() + { + Anno = anno, + Mese = mese, + TipologiaFattura = tipologiafattura, + Data = data, + Ricalcola = ricalcola + }; + + var builder = new DocumentBuilder(path); + + if(String.IsNullOrEmpty(data)) + { + data = DateTime.UtcNow.ItalianTime().ToString("yyyy-MM-dd HH:mm:ss"); + } + + var subject = $"Notifica Regolare Esecuzione {tipologiafattura} Mese di {mese.GetMonth()}"; + var sender = new EmailSender(smtpSource: Configurazione.Smtp!, + smtpPort: Configurazione.SmtpPort!, + smtpUser: Configurazione.SmtpAuth!, + smtpPassword: Configurazione.SmtpPassword!, + from: Configurazione.From!); + var emailService = new EmailRelService(Configurazione.ConnectionString!); + var enti = emailService.GetSenderEmail(risposta.Anno, risposta.Mese, risposta.TipologiaFattura!); + foreach (var ente in enti!) + if (ente.Pec != null) + { + var (msg, ver) = sender.SendEmail(ente.Pec, subject, builder.CreateEmailHtml(ente)!); + if (!ver) + { + _logger.LogInformation(msg); + } + emailService.InsertTracciatoEmail(new RelEmailTracking() + { + Data = data, + IdContratto = ente.IdContratto, + Invio = Convert.ToByte(ver == true ? 1 : 0), + Anno = ente.Anno, + Mese = ente.Mese, + Messaggio = msg, + Pec = ente.Pec, + IdEnte = ente.IdEnte, + RagioneSociale = ente.RagioneSociale, + TipologiaFattura = ente.TipologiaFattura + }); + } + } + catch (Exception ex) + { + risposta.DbConnection = false; + risposta.Error = ex.Message; + _logger.LogInformation(ex.Message); + } + + var response = req.CreateResponse(HttpStatusCode.OK); + response.Headers.Add("Content-Type", "application/json; charset=utf-8"); + response.WriteString(risposta.Serialize()); + return response; + } + + private static string? GetEnvironmentVariable(string name) + { + return Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process); + } + +} diff --git a/src/Presentation/PortaleFatture.BE.SendEmailFunction/host.json b/src/Presentation/PortaleFatture.BE.SendEmailFunction/host.json new file mode 100644 index 0000000..ee5cf5f --- /dev/null +++ b/src/Presentation/PortaleFatture.BE.SendEmailFunction/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/tests/.env b/tests/.env new file mode 100644 index 0000000..2decffd --- /dev/null +++ b/tests/.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=portalefatture \ No newline at end of file diff --git a/tests/Data/Dockerfile b/tests/Data/Dockerfile new file mode 100644 index 0000000..ec01e06 --- /dev/null +++ b/tests/Data/Dockerfile @@ -0,0 +1,10 @@ +FROM mcr.microsoft.com/mssql/server + +ENV ACCEPT_EULA=Y +ENV SA_PASSWORD=52JdGnzZaANhf; + +COPY ./Data /scripts + + +ENTRYPOINT [ "/bin/bash", "/scripts/entrypoint.sh" ] +CMD [ "/opt/mssql/bin/sqlservr" ] \ No newline at end of file diff --git a/tests/Data/entrypoint.sh b/tests/Data/entrypoint.sh new file mode 100644 index 0000000..311ec0e --- /dev/null +++ b/tests/Data/entrypoint.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +if [ "$1" = '/opt/mssql/bin/sqlservr' ]; then + # If this is the container's first run, initialize the application database + if [ ! -f /tmp/app-initialized ]; then + # Initialize the application database asynchronously in a background process. This allows a) the SQL Server process to be the main process in the container, which allows graceful shutdown and other goodies, and b) us to only start the SQL Server process once, as opposed to starting, stopping, then starting it again. + function initialize_app_database() { + # Wait a bit for SQL Server to start. SQL Server's process doesn't provide a clever way to check if it's up or not, and it needs to be up before we can import the application database + sleep 15s + + #run the setup script to create the DB and the schema in the DB + /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 52JdGnzZaANhf -d master -i /scripts/setup.sql + + # Note that the container has been initialized so future starts won't wipe changes to the data + touch /tmp/app-initialized + } + initialize_app_database & + fi +fi + +exec "$@" \ No newline at end of file diff --git a/tests/Data/setup.sql b/tests/Data/setup.sql new file mode 100644 index 0000000..5064f2b --- /dev/null +++ b/tests/Data/setup.sql @@ -0,0 +1,282 @@ +IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'pfw') + BEGIN + EXEC ('CREATE SCHEMA pfw;'); + END; + +IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'pfd') + BEGIN + EXEC ('CREATE SCHEMA pfd;'); + END; + +CREATE TABLE pfw.CategoriaSpedizione ( + IdCategoriaSpedizione int IDENTITY(1,1) NOT NULL, + Descrizione nvarchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + Tipo nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT PK__Categori__0E5B57A455A55002 PRIMARY KEY (IdCategoriaSpedizione) +); + + +CREATE TABLE pfw.Form ( + IdForm int NOT NULL, + Descrizione varchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT PK__Form__007D03D97A238DBC PRIMARY KEY (IdForm) +); + + +CREATE TABLE pfw.Log ( + FkIdEnte nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + IdUtente nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + DataEvento datetime NOT NULL, + DescrizioneEvento nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + JsonTransazione text COLLATE SQL_Latin1_General_CP1_CI_AS NULL +); + + +CREATE TABLE pfw.Prodotti ( + Prodotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + CONSTRAINT PK__Prodotti__3EE5F2F6209BD2F1 PRIMARY KEY (Prodotto) +); + + + +CREATE TABLE pfw.Stato ( + Stato nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + [Default] bit NULL, + CONSTRAINT PK__Stato__BA803DA6AD8CBD05 PRIMARY KEY (Stato) +); + + + +CREATE TABLE pfw.Step ( + IdStep int NOT NULL, + Descrizione varchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT PK__Step__A3FC8BAD5173134C PRIMARY KEY (IdStep) +); + + + +CREATE TABLE pfw.TipoCommessa ( + TipoCommessa nvarchar(1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + Descrizione nvarchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT PK__TipoComm__E5339F96F1E97E24 PRIMARY KEY (TipoCommessa) +); + + + +CREATE TABLE pfw.TipoContratto ( + IdTipoContratto bigint IDENTITY(1,1) NOT NULL, + Descrizione nvarchar(3) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + CONSTRAINT PK__TipoCont__D8826341BD065CDF PRIMARY KEY (IdTipoContratto) +); + + + +CREATE TABLE pfw.DatiFatturazione ( + IdDatiFatturazione bigint IDENTITY(1,1) NOT NULL, + Cup nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + Cig nvarchar(10) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + CodCommessa nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + DataDocumento datetime NOT NULL, + SplitPayment bit NOT NULL, + FkIdEnte nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + IdDocumento nvarchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + DataCreazione datetime NOT NULL, + DataModifica datetime NULL, + [Map] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + FkTipoCommessa nvarchar(1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + PEC nvarchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FkProdotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + CONSTRAINT PK__DatiFatt__5A190E0F178A5F57 PRIMARY KEY (IdDatiFatturazione), + CONSTRAINT FkProdotto_DatiFatturazione FOREIGN KEY (FkProdotto) REFERENCES pfw.Prodotti(Prodotto), + CONSTRAINT FkTipoCommessaDatiFatturazione FOREIGN KEY (FkTipoCommessa) REFERENCES pfw.TipoCommessa(TipoCommessa) +); + + +CREATE TABLE pfw.DatiFatturazioneContatti ( + FkIdDatiFatturazione bigint NOT NULL, + Email nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + CONSTRAINT FkIdDatiFatturazioneContatti FOREIGN KEY (FkIdDatiFatturazione) REFERENCES pfw.DatiFatturazione(IdDatiFatturazione) +); + + + +CREATE TABLE pfw.DatiModuloCommessaTotali ( + FkIdEnte nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FkIdTipoContratto bigint NOT NULL, + FkProdotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + AnnoValidita int NOT NULL, + MeseValidita int NOT NULL, + FkIdCategoriaSpedizione int NOT NULL, + FkStato nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + TotaleCategoria decimal(9,2) NOT NULL, + CONSTRAINT PK_DatiModuloCommessaTotali PRIMARY KEY (FkIdEnte,FkIdTipoContratto,FkProdotto,AnnoValidita,MeseValidita,FkIdCategoriaSpedizione), + CONSTRAINT FK_DatiModuloCommessaTotali_CategoriaSpedizione FOREIGN KEY (FkIdCategoriaSpedizione) REFERENCES pfw.CategoriaSpedizione(IdCategoriaSpedizione), + CONSTRAINT FK_DatiModuloCommessaTotali_Prodotti FOREIGN KEY (FkProdotto) REFERENCES pfw.Prodotti(Prodotto), + CONSTRAINT FK_DatiModuloCommessaTotali_Stato FOREIGN KEY (FkStato) REFERENCES pfw.Stato(Stato), + CONSTRAINT FK_DatiModuloCommessaTotali_TipoContratto FOREIGN KEY (FkIdTipoContratto) REFERENCES pfw.TipoContratto(IdTipoContratto) +); + + + +CREATE TABLE pfw.PercentualeAnticipo ( + FkProdotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FkIdTipoContratto bigint NOT NULL, + FkIdCategoriaSpedizione int NOT NULL, + Percentuale int NOT NULL, + Descrizione varchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + DataInizioValidita datetime NOT NULL, + DataFineValidita datetime NULL, + DataCreazione datetime NOT NULL, + DataModifica datetime NULL, + CONSTRAINT FkIdCategoriaSpedizioneAnticipo FOREIGN KEY (FkIdCategoriaSpedizione) REFERENCES pfw.CategoriaSpedizione(IdCategoriaSpedizione), + CONSTRAINT FkIdTipoContratto FOREIGN KEY (FkIdTipoContratto) REFERENCES pfw.TipoContratto(IdTipoContratto), + CONSTRAINT FkProdotto FOREIGN KEY (FkProdotto) REFERENCES pfw.Prodotti(Prodotto) +); + + + +CREATE TABLE pfw.Scadenziario ( + FkIdProdotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FkIdStep int NOT NULL, + FkIdForm int NULL, + Ordine int NOT NULL, + GiornoInizio int NOT NULL, + OraInizio time NULL, + GiornoFine int NOT NULL, + OraFine time NULL, + ProcessoBatch bit NULL, + CONSTRAINT FK_Scadenziario_Form FOREIGN KEY (FkIdForm) REFERENCES pfw.Form(IdForm), + CONSTRAINT FK_Scadenziario_Prodotti FOREIGN KEY (FkIdProdotto) REFERENCES pfw.Prodotti(Prodotto), + CONSTRAINT FK_Scadenziario_Step FOREIGN KEY (FkIdStep) REFERENCES pfw.Step(IdStep) +); + + + +CREATE TABLE pfw.TipoSpedizione ( + IdTipoSpedizione int IDENTITY(1,1) NOT NULL, + Descrizione nvarchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FkIdCategoriaSpedizione int NOT NULL, + Tipo nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT PK__TipoSped__33BE995DD9717E6A PRIMARY KEY (IdTipoSpedizione), + CONSTRAINT FkIdCategoriaSpedizione FOREIGN KEY (FkIdCategoriaSpedizione) REFERENCES pfw.CategoriaSpedizione(IdCategoriaSpedizione) +); + + +CREATE TABLE pfw.CostoNotifiche ( + MediaNotificaNazionale decimal(5,2) NOT NULL, + MediaNotificaInternazionale decimal(5,2) NULL, + FkIdTipoSpedizione int NOT NULL, + FkIdTipoContratto bigint NOT NULL, + FkProdotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + DataInizioValidita datetime NOT NULL, + DataFineValidita datetime NULL, + DataCreazione datetime NOT NULL, + DataModifica datetime NULL, + Descrizione varchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT FkProdottoNotifiche FOREIGN KEY (FkProdotto) REFERENCES pfw.Prodotti(Prodotto), + CONSTRAINT FkTipoContratto FOREIGN KEY (FkIdTipoContratto) REFERENCES pfw.TipoContratto(IdTipoContratto), + CONSTRAINT FkTipoSpedizione FOREIGN KEY (FkIdTipoSpedizione) REFERENCES pfw.TipoSpedizione(IdTipoSpedizione) +); + + + +CREATE TABLE pfw.DatiModuloCommessa ( + NumeroNotificheNazionali int NOT NULL, + NumeroNotificheInternazionali int NOT NULL, + FkIdTipoSpedizione int NOT NULL, + DataCreazione datetime NOT NULL, + DataModifica datetime NULL, + FkIdEnte nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FKIdTipoContratto bigint NOT NULL, + FkIdStato nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + FkProdotto nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + AnnoValidita int NOT NULL, + MeseValidita int NOT NULL, + CONSTRAINT PK_DatiModuloCommessa PRIMARY KEY (FkIdEnte,FKIdTipoContratto,FkProdotto,AnnoValidita,MeseValidita,FkIdTipoSpedizione), + CONSTRAINT FKIdStatoCommessa FOREIGN KEY (FkIdStato) REFERENCES pfw.Stato(Stato), + CONSTRAINT FK_DatiModuloCommessa_Prodotti FOREIGN KEY (FkProdotto) REFERENCES pfw.Prodotti(Prodotto), + CONSTRAINT FK_DatiModuloCommessa_TipoContratto FOREIGN KEY (FKIdTipoContratto) REFERENCES pfw.TipoContratto(IdTipoContratto), + CONSTRAINT FK_DatiModuloCommessa_TipoSpedizione FOREIGN KEY (FkIdTipoSpedizione) REFERENCES pfw.TipoSpedizione(IdTipoSpedizione) +); + +INSERT INTO pfw.TipoContratto +( Descrizione) +VALUES('PAL'); +INSERT INTO pfw.TipoContratto +(Descrizione) +VALUES('PAC'); + +INSERT INTO pfw.Prodotti +(Prodotto) +VALUES('prod-pn'); + +INSERT INTO pfw.CategoriaSpedizione +(Descrizione) +VALUES('Analogico'); + +INSERT INTO pfw.CategoriaSpedizione +(Descrizione) +VALUES('Digitale'); + +INSERT INTO pfw.TipoSpedizione +(Tipo, Descrizione, FkIdCategoriaSpedizione) +VALUES('Analog. A/R', 'Numero complessivo delle notifiche da processare in via analogica tramite Raccomandata A/R nel mese di riferimento +', 1); + +INSERT INTO pfw.TipoSpedizione +(Tipo, Descrizione, FkIdCategoriaSpedizione) +VALUES('Analog. L. 890/82', 'Numero complessivo delle notifiche da processare in via analogica del tipo notifica ex L. 890/1982 nel mese di riferimento +', 1); + +INSERT INTO pfw.TipoSpedizione +(Tipo, Descrizione, FkIdCategoriaSpedizione) +VALUES('Digitale', 'Numero complessivo delle notifiche da processare in via digitale nel mese di riferimento', 2); + +INSERT INTO pfw.TipoCommessa (TipoCommessa,Descrizione) VALUES + (N'1',N'Ordine'), + (N'2',N'Contratto'); + +INSERT INTO pfw.Stato (Stato,[Default]) VALUES + (N'Apera/Non Caricato',0), + (N'Aperta/Caricato',1), + (N'Archiviato',0), + (N'Chiusa/Caricato',0), + (N'Chiusa/Stimato',0); + +CREATE TABLE pfd.Contratti ( + internalistitutionid nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + product nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + filename nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + onboardingtokenid nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + pricingplan nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + updatedat nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + createdat datetime2 NULL, + closedat datetime2 NULL, + [year] int NULL, + [month] int NULL, + daily nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + LastModified datetime2 NULL, + FkIdTipoContratto bigint NULL +); + +CREATE TABLE pfd.Enti ( + InternalIstitutionId nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + institutionType nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + description nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + digitalAddress nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + address nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + originId nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + zipCode nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + istatCode nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + city nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + country nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + county nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + subUnitCode nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + subUnitType nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + paymentServiceProvider nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + vatnumber nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + publicservices nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + LastModified datetime2 NULL, + Category nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT PK__Enti__16EA308B3ABC1682 PRIMARY KEY (InternalIstitutionId) +); \ No newline at end of file diff --git a/tests/PortaleFatture.BE.IntegrationTest/GlobalUsings.cs b/tests/PortaleFatture.BE.IntegrationTest/GlobalUsings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/tests/PortaleFatture.BE.IntegrationTest/PortaleFatture.BE.IntegrationTest.csproj b/tests/PortaleFatture.BE.IntegrationTest/PortaleFatture.BE.IntegrationTest.csproj new file mode 100644 index 0000000..6f5b0ce --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/PortaleFatture.BE.IntegrationTest.csproj @@ -0,0 +1,43 @@ + + + + net8.0 + enable + enable + + false + true + 27e0801e-8863-4e92-af93-631a5685fed4 + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + Always + + + Always + + + + diff --git a/tests/PortaleFatture.BE.IntegrationTest/SelfCareHttpClientTests.cs b/tests/PortaleFatture.BE.IntegrationTest/SelfCareHttpClientTests.cs new file mode 100644 index 0000000..a839c1e --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/SelfCareHttpClientTests.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Infrastructure.Gateway; + +namespace PortaleFatture.BE.IntegrationTest; + +public class SelfCareHttpClientTests +{ + private ILogger _logger; + private ISelfCareHttpClient _client; + private IConfiguration _conf; + [SetUp] + public void Setup() + { + _logger = ServiceProvider.GetRequiredService>(); + _client = ServiceProvider.GetRequiredService(); + _conf = ServiceProvider.GetRequiredService(); + } + + [Test] + public async Task GetCertificates_ShouldSucceed_ReturnList() + { + var certificates = await _client.GetCertificatesAsync(); + ClassicAssert.IsNotNull(certificates); + ClassicAssert.True(certificates.Count > 0); + } + + [Test] + public void GetSelfCareToken_ShouldSucceed_ReturnJWT() + { + var selfCareToken = _conf.GetSection("PortaleFattureOptions:JWT:TestToken").Value; + var jwt = _client.GetSelfCareTokenAsync(selfCareToken); + ClassicAssert.NotNull(jwt); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.IntegrationTest/SelfCareTokenServiceTests.cs b/tests/PortaleFatture.BE.IntegrationTest/SelfCareTokenServiceTests.cs new file mode 100644 index 0000000..b501a9e --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/SelfCareTokenServiceTests.cs @@ -0,0 +1,46 @@ +using System.Security; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Infrastructure.Gateway; + +namespace PortaleFatture.BE.IntegrationTest; + + +public class SelfCareTokenServiceTests +{ + private ILogger _logger; + private ISelfCareTokenService _service; + private IConfiguration _conf; + [SetUp] + public void Setup() + { + _logger = ServiceProvider.GetRequiredService>(); + _service = ServiceProvider.GetRequiredService(); + _conf = ServiceProvider.GetRequiredService(); + } + + [Test] + public async Task GetSelfCareToken_ShouldSucceed_ReturnJWT() + { + var selfCareToken = _conf.GetSection("PortaleFattureOptions:JWT:TestToken").Value; + var (_, result) = await _service.Validate(selfCareToken!); + ClassicAssert.True(result); + } + + [Test] + public async Task GetSelfCareTokenContent_ShouldSucceed_ReturnData() + { + var selfCareToken = _conf.GetSection("PortaleFattureOptions:JWT:TestToken").Value; + var result = await _service.ValidateContent(selfCareToken!); + ClassicAssert.IsNotNull(result); + } + + + [Test] + public void GetSelfCareToken_ShouldFail_ReturnFalse() + { + var selfCareToken = _conf.GetSection("PortaleFattureOptions:JWT:TestToken").Value; + Assert.ThrowsAsync(async () => await _service.Validate(selfCareToken!, true)); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.IntegrationTest/ServiceProvider.cs b/tests/PortaleFatture.BE.IntegrationTest/ServiceProvider.cs new file mode 100644 index 0000000..8de9b7e --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/ServiceProvider.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Gateway; + +namespace PortaleFatture.BE.IntegrationTest; + +public static class ServiceProvider +{ + private static IServiceProvider Provider() + { + var services = new ServiceCollection(); + var configurationBuilder = new ConfigurationBuilder() + .AddJsonFile("appsettings.Development.json", optional: true) + .AddUserSecrets("27e0801e-8863-4e92-af93-631a5685fed4") + .AddEnvironmentVariables() + .Build(); + services.AddSingleton(configurationBuilder); + + var configuration = services + .BuildServiceProvider() + .GetRequiredService(); + + PortaleFattureOptions options = new(); + configuration.GetSection(nameof(PortaleFattureOptions)).Bind(options); + + services.AddSingleton(options); + + var sconf = configuration!.GetSection(nameof(PortaleFattureOptions)); + services.Configure(o => + { + o.SelfCareCertEndpoint = configuration.GetSection("PortaleFattureOptions:SelfCareCertEndpoint").Value; + o.ConnectionString = configuration.GetSection("PortaleFattureOptions:ConnectionString").Value; + o.SelfCareUri = configuration.GetSection("PortaleFattureOptions:SelfCareUri").Value; + }); + + var dbConnectionString = options.ConnectionString ?? + throw new ConfigurationException("Db connection string not configured"); + + services.AddSingleton(new DbContextFactory(dbConnectionString, "pfw")); + + services.AddMediatR(x => x.RegisterServicesFromAssembly(typeof(RootInfrastructure).Assembly)); + + services.AddLogging(); + + services.AddLocalization(options => options.ResourcesPath = "Resources"); + + services.AddHttpClient(); + + services.AddSingleton(); + services.AddSingleton(); + + return services.BuildServiceProvider(); + } + + public static T GetRequiredService() where T : class + { + var provider = Provider(); + return provider.GetRequiredService(); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.IntegrationTest/appsettings.Development.json b/tests/PortaleFatture.BE.IntegrationTest/appsettings.Development.json new file mode 100644 index 0000000..a38cd88 --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/appsettings.Development.json @@ -0,0 +1,20 @@ +{ + "Logging:LogLevel:Microsoft.Hosting": "Debug", + "Logging:LogLevel:Microsoft.EntityFrameworkCore": "Debug", + "Logging:LogLevel:Microsoft.AspNetCore": "Debug", + "Logging:LogLevel:Microsoft": "Debug", + "Logging:LogLevel:Default": "Debug", + "Locale": "it-IT", + "PortaleFattureOptions": { + "ConnectionString": "xxx", + "FattureSchema": "xxx", + "SelfCareSchema": "xxx", + "SelfCareUri": "", + "SelfCareCertEndpoint": "", + "Vault": "", + "JWT:ValidIssuer": "xxx", + "JWT:ValidAudience": "xxx", + "JWT:Secret": "xxx", + "JWT:TestToken": "xxx" + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.IntegrationTest/appsettings.json b/tests/PortaleFatture.BE.IntegrationTest/appsettings.json new file mode 100644 index 0000000..a38cd88 --- /dev/null +++ b/tests/PortaleFatture.BE.IntegrationTest/appsettings.json @@ -0,0 +1,20 @@ +{ + "Logging:LogLevel:Microsoft.Hosting": "Debug", + "Logging:LogLevel:Microsoft.EntityFrameworkCore": "Debug", + "Logging:LogLevel:Microsoft.AspNetCore": "Debug", + "Logging:LogLevel:Microsoft": "Debug", + "Logging:LogLevel:Default": "Debug", + "Locale": "it-IT", + "PortaleFattureOptions": { + "ConnectionString": "xxx", + "FattureSchema": "xxx", + "SelfCareSchema": "xxx", + "SelfCareUri": "", + "SelfCareCertEndpoint": "", + "Vault": "", + "JWT:ValidIssuer": "xxx", + "JWT:ValidAudience": "xxx", + "JWT:Secret": "xxx", + "JWT:TestToken": "xxx" + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/Common/CommonFactory.cs b/tests/PortaleFatture.BE.UnitTest/Common/CommonFactory.cs new file mode 100644 index 0000000..a3ddb9a --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/Common/CommonFactory.cs @@ -0,0 +1,73 @@ +using MediatR; +using PortaleFatture.BE.Core.Entities.DatiModuloCommesse; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +namespace PortaleFatture.BE.UnitTest.Common; + +public static class CommonFactory +{ + public static async Task CreateDatiCommessaConfiguration( + IMediator handler, + long idTipoContratto, + string? nomeProdotto, + decimal? expectedMediaNazionale = 1.0M, + decimal? expectedMediaInternazionale = 2.0M, + int? expectedPercentuale = 50) + { + var reqProdotti = new ProdottoQueryGetAll(); + var prodotti = await handler.Send(reqProdotti); + var prodotto = prodotti.Where(x => x.Nome == nomeProdotto).FirstOrDefault(); + var reqSpedizioni = new SpedizioneQueryGetAll(); + var rCategoriaSpedizioni = await handler.Send(reqSpedizioni); + var spedizioni = rCategoriaSpedizioni.SelectMany(x => x.TipoSpedizione!); + + var reqContratti = new TipoContrattoQueryGetAll(); + var contratti = await handler.Send(reqContratti); + var contratto = contratti.Where(x => x.Id == idTipoContratto).FirstOrDefault(); + + var adesso = DateTime.UtcNow.ItalianTime(); + var expectedDescrizione = "descrizione"; + expectedPercentuale = expectedPercentuale == null ? 30 : expectedPercentuale; + + expectedMediaNazionale = expectedMediaNazionale == null ? (decimal)new Random().NextDouble() : expectedMediaNazionale; + expectedMediaInternazionale = expectedMediaInternazionale == null ? (decimal)new Random().NextDouble() : expectedMediaInternazionale; + + var command = new DatiConfigurazioneModuloCommessaCreateCommand + { + Tipi = [], + Categorie = [] + }; + foreach (var tipo in spedizioni) + { + command.Tipi.Add(new DatiConfigurazioneModuloCommessaCreateTipoCommand() + { + IdTipoSpedizione = tipo.Id, + DataCreazione = adesso, + DataInizioValidita = adesso, + Descrizione = expectedDescrizione, + MediaNotificaInternazionale = expectedMediaNazionale.Value + tipo.Id, + MediaNotificaNazionale = expectedMediaInternazionale.Value + tipo.Id, + Prodotto = prodotto!.Nome, + IdTipoContratto = contratto!.Id + }); + } + foreach (var cat in rCategoriaSpedizioni) + { + + command.Categorie.Add(new DatiConfigurazioneModuloCommessaCreateCategoriaCommand() + { + Percentuale = expectedPercentuale.Value + cat.Id, + DataCreazione = adesso, + DataInizioValidita = adesso, + Descrizione = expectedDescrizione, + Prodotto = prodotto!.Nome, + IdTipoContratto = contratto!.Id, + IdCategoriaSpedizione = cat.Id + }); ; + } + + return await handler.Send(command); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/Common/TestExtensions.cs b/tests/PortaleFatture.BE.UnitTest/Common/TestExtensions.cs new file mode 100644 index 0000000..0855fe2 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/Common/TestExtensions.cs @@ -0,0 +1,33 @@ +using System.Reflection.Metadata; +using MediatR; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Tipologie.Queries; + +namespace PortaleFatture.BE.UnitTest.Common; + +public static class TestExtensions +{ + public static long GetRandomId() + { + var rand = new Random(); + return rand.Next(1, int.MaxValue); + } + + public static string GetRandomIdEnte() + { + return Guid.NewGuid().ToString(); + } + + public static AuthenticationInfo GetAuthInfo(string? idEnte, string? prodotto, string? ruolo = Ruolo.ADMIN, long? idTipoContratto = 1) + { + return new AuthenticationInfo() + { + IdEnte = idEnte ?? Guid.NewGuid().ToString(), + Prodotto = prodotto ?? "prod-pn", + Ruolo = ruolo, + IdTipoContratto = idTipoContratto + }; + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/DatiConfigurazioneModuloCommessaCreateCommandTests.cs b/tests/PortaleFatture.BE.UnitTest/DatiConfigurazioneModuloCommessaCreateCommandTests.cs new file mode 100644 index 0000000..f19e746 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/DatiConfigurazioneModuloCommessaCreateCommandTests.cs @@ -0,0 +1,45 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.UnitTest.Common; + +namespace PortaleFatture.BE.UnitTest; + +public class DatiConfigurazioneModuloCommessaCreateCommandTests +{ + private IDbContextFactory _factory; + private ILogger _logger; + private IStringLocalizer _localizer; + private IMediator _handler; + + [SetUp] + public void Setup() + { + _factory = ServiceProvider.GetRequiredService(); + _logger = ServiceProvider.GetRequiredService>(); + _localizer = ServiceProvider.GetRequiredService>(); + _handler = ServiceProvider.GetRequiredService(); + } + + [Test] + public async Task Create_ShouldSucceed_True() + { + + var conf = await CommonFactory.CreateDatiCommessaConfiguration(_handler, 1, "prod-pn"); + ClassicAssert.IsNotNull(conf); + ClassicAssert.IsNotNull(conf.Categorie); + ClassicAssert.IsTrue(conf.Categorie.Where(x => x.IdCategoriaSpedizione == 1).FirstOrDefault()!.Percentuale == 51); + ClassicAssert.IsTrue(conf.Categorie.Where(x => x.IdCategoriaSpedizione == 2).FirstOrDefault()!.Percentuale == 52); + ClassicAssert.IsNotNull(conf.Tipi); + ClassicAssert.IsNotNull(conf.Tipi.Where(x => x.IdTipoSpedizione == 1).FirstOrDefault()!.MediaNotificaInternazionale == 2.0M + 1); + ClassicAssert.IsNotNull(conf.Tipi.Where(x => x.IdTipoSpedizione == 1).FirstOrDefault()!.MediaNotificaNazionale == 1.0M + 1); + ClassicAssert.IsNotNull(conf.Tipi.Where(x => x.IdTipoSpedizione == 2).FirstOrDefault()!.MediaNotificaInternazionale == 2.0M + 2); + ClassicAssert.IsNotNull(conf.Tipi.Where(x => x.IdTipoSpedizione == 2).FirstOrDefault()!.MediaNotificaNazionale == 1.0M + 2); + ClassicAssert.IsNotNull(conf.Tipi.Where(x => x.IdTipoSpedizione == 3).FirstOrDefault()!.MediaNotificaInternazionale == 2.0M + 3); + ClassicAssert.IsNotNull(conf.Tipi.Where(x => x.IdTipoSpedizione == 3).FirstOrDefault()!.MediaNotificaNazionale == 1.0M + 3); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneCreateCommandTests.cs b/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneCreateCommandTests.cs new file mode 100644 index 0000000..31f3a05 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneCreateCommandTests.cs @@ -0,0 +1,162 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.UnitTest.Common; + +namespace PortaleFatture.BE.UnitTest; + +public class DatiFatturazioneCreateCommandTests +{ + private IDbContextFactory _factory; + private ILogger _logger; + private IStringLocalizer _localizer; + private IMediator _handler; + + [SetUp] + public void Setup() + { + _factory = ServiceProvider.GetRequiredService(); + _logger = ServiceProvider.GetRequiredService>(); + _localizer = ServiceProvider.GetRequiredService>(); + _handler = ServiceProvider.GetRequiredService(); + } + + [Test] + public async Task CreateCommand_ShouldSucceed_True() + { + string? expectedCup = null; + bool expectedNotaLegale = false; + string? expectedCodCommessa = null; + DateTime? expectedDataDocumento = null; + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = null; + DateTime expectedDataCreazione = DateTime.UtcNow; + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + + var req = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = expectedContatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + var datiFatturazione = await _handler.Send(req); + + ClassicAssert.IsNotNull(datiFatturazione); + ClassicAssert.IsNull(datiFatturazione.DataDocumento); + } + + [Test] + public void CreateCommand_ShouldFail_WithoutContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = false; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow; + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow; + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + + var req = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = null, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + ClassicAssert.ThrowsAsync(async () => await _handler.Send(req)); + } + + [Test] + public async Task CreateCommand_ShouldSucceed_WithContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = true; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow; + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow; + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + var req = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = expectedContatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + var actualDatiFatturazione = await _handler.Send(req); + ClassicAssert.IsNotNull(actualDatiFatturazione); + var contatti = actualDatiFatturazione.Contatti!.OrderBy(x => x.Email).ToList(); + ClassicAssert.True(contatti.Count == 2); + ClassicAssert.True(contatti[0].Email == "expected1@pippo.com"); + ClassicAssert.True(contatti[1].Email == "expected2@pippo.com"); + ClassicAssert.IsNull(actualDatiFatturazione.DataModifica); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneGetByIdQueryTests.cs b/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneGetByIdQueryTests.cs new file mode 100644 index 0000000..355b9e1 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneGetByIdQueryTests.cs @@ -0,0 +1,151 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Queries; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.UnitTest.Common; + +namespace PortaleFatture.BE.UnitTest; + +public class DatiFatturazioneGetByIdQueryTests +{ + private IDbContextFactory _factory; + private ILogger _logger; + private IStringLocalizer _localizer; + private IMediator _handler; + + [SetUp] + public void Setup() + { + _factory = ServiceProvider.GetRequiredService(); + _logger = ServiceProvider.GetRequiredService>(); + _localizer = ServiceProvider.GetRequiredService>(); + _handler = ServiceProvider.GetRequiredService(); + } + + [Test] + public async Task GetById_ShouldFail_WithoutContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = false; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow; + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow; + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + var req = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = null, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + ClassicAssert.ThrowsAsync(async () => await _handler.Send(req)); + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + + req.Contatti = expectedContatti; + + var actualDatiFatturazione = await _handler.Send(req); + ClassicAssert.IsNotNull(actualDatiFatturazione); + + var id = actualDatiFatturazione.Id; + var select = new DatiFatturazioneQueryGetById() + { + Id = id + }; + ; + actualDatiFatturazione = await _handler.Send(select); + ClassicAssert.IsNotNull(actualDatiFatturazione); + ClassicAssert.True(actualDatiFatturazione.NotaLegale == expectedNotaLegale); + ClassicAssert.True(actualDatiFatturazione.CodCommessa == expectedCodCommessa); + ClassicAssert.IsNull(actualDatiFatturazione.DataModifica); + } + + [Test] + public async Task GetById_ShouldSucceed_WithContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = true; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow; + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow; + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + var req = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = expectedContatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + var actualDatiFatturazione = await _handler.Send(req); + ClassicAssert.IsNotNull(actualDatiFatturazione); + + var id = actualDatiFatturazione.Id; + var select = new DatiFatturazioneQueryGetById() + { + Id = id + }; + ; + actualDatiFatturazione = await _handler.Send(select); + + var contatti = actualDatiFatturazione.Contatti!.OrderBy(x => x.Email).ToList(); + ClassicAssert.True(contatti.Count == 2); + ClassicAssert.True(contatti[0].Email == "expected1@pippo.com"); + ClassicAssert.True(contatti[1].Email == "expected2@pippo.com"); + ClassicAssert.IsNull(actualDatiFatturazione.DataModifica); + ClassicAssert.IsTrue(actualDatiFatturazione.NotaLegale); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneUpdateCommandTests .cs b/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneUpdateCommandTests .cs new file mode 100644 index 0000000..2c15fbc --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/DatiFatturazioneUpdateCommandTests .cs @@ -0,0 +1,347 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiFatturazioni.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.UnitTest.Common; + +namespace PortaleFatture.BE.UnitTest; + +public class DatiFatturazioneUpdateCommandTests +{ + private IDbContextFactory _factory; + private ILogger _logger; + private IStringLocalizer _localizer; + private IMediator _handler; + + [SetUp] + public void Setup() + { + _factory = ServiceProvider.GetRequiredService(); + _logger = ServiceProvider.GetRequiredService>(); + _localizer = ServiceProvider.GetRequiredService>(); + _handler = ServiceProvider.GetRequiredService(); + } + + [Test] + public async Task UpdateCommand_ShouldSucceed_WithoutContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = true; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow.ItalianTime(); + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow.ItalianTime(); + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + var expectedContatto = "pippo@gmail.com"; + List contatti = + [ + new DatiFatturazioneContattoCreateCommand() + { + Email = expectedContatto + }, + ]; + + var request = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = contatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + var actualDatiFatturazione = await _handler.Send(request); + ClassicAssert.IsNotNull(actualDatiFatturazione); + + DateTime expectedDataModifica = DateTime.UtcNow.AddMinutes(1); + var expectedUpdatedPec = "modified@pec.it"; + expectedNotaLegale = false; + + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + + var updateRequest = new DatiFatturazioneUpdateCommand(authInfo) + { + Id = actualDatiFatturazione.Id, + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = expectedContatti, + Cup = expectedCup, + DataModifica = expectedDataModifica, + DataDocumento = expectedDataDocumento, + Pec = expectedUpdatedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + actualDatiFatturazione = await _handler.Send(updateRequest); + + ClassicAssert.True(actualDatiFatturazione.NotaLegale == expectedNotaLegale); + ClassicAssert.True(actualDatiFatturazione.CodCommessa == expectedCodCommessa); + ClassicAssert.True(actualDatiFatturazione.Pec == expectedUpdatedPec); + ClassicAssert.IsNotNull(actualDatiFatturazione.Contatti); + } + + + [Test] + public async Task UpdateCommand_ShouldSucceed_WithEmptyContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = true; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow.ItalianTime(); + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow.ItalianTime(); + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + var expectedContatto = "pippo@gmail.com"; + List contatti = + [ + new DatiFatturazioneContattoCreateCommand() + { + Email = expectedContatto + }, + ]; + + var request = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = contatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + var actualDatiFatturazione = await _handler.Send(request); + ClassicAssert.IsNotNull(actualDatiFatturazione); + + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + + DateTime expectedDataModifica = DateTime.UtcNow.AddMinutes(1); + var expectedUpdatedPec = "modified@pec.it"; + expectedNotaLegale = false; + var updateRequest = new DatiFatturazioneUpdateCommand(authInfo) + { + Id = actualDatiFatturazione.Id, + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = expectedContatti, + Cup = expectedCup, + DataModifica = expectedDataModifica, + DataDocumento = expectedDataDocumento, + Pec = expectedUpdatedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + actualDatiFatturazione = await _handler.Send(updateRequest); + + ClassicAssert.True(actualDatiFatturazione.NotaLegale == expectedNotaLegale); + ClassicAssert.True(actualDatiFatturazione.CodCommessa == expectedCodCommessa); + ClassicAssert.True(actualDatiFatturazione.Pec == expectedUpdatedPec); + ClassicAssert.IsNotNull(actualDatiFatturazione.Contatti); + } + + [Test] + public async Task UpdateCommand_ShouldSucceed_WithDifferentContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = true; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow.ItalianTime(); + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow.ItalianTime(); + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + + var expectedContatti = new List() + { new() + { + Email = "expected1@pippo.com" + }, + new() + { + Email = "expected2@pippo.com" + }, + }; + + var request = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = expectedContatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + var actualDatiFatturazione = await _handler.Send(request); + ClassicAssert.IsNotNull(actualDatiFatturazione); + + DateTime expectedDataModifica = DateTime.UtcNow.AddMinutes(1); + var expectedUpdatedPec = "modified@pec.it"; + var expectedContatto = "pippo@gmail.com"; + expectedNotaLegale = false; + List contatti = + [ + new DatiFatturazioneContattoCreateCommand() + { + Email = expectedContatto, + IdDatiFatturazione = actualDatiFatturazione.Id + }, + ]; + + var updateRequest = new DatiFatturazioneUpdateCommand(authInfo) + { + Id = actualDatiFatturazione.Id, + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = contatti, + Cup = expectedCup, + DataModifica = expectedDataModifica, + DataDocumento = expectedDataDocumento, + Pec = expectedUpdatedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + actualDatiFatturazione = await _handler.Send(updateRequest); + + ClassicAssert.True(actualDatiFatturazione.NotaLegale == expectedNotaLegale); + ClassicAssert.True(actualDatiFatturazione.CodCommessa == expectedCodCommessa); + ClassicAssert.True(actualDatiFatturazione.Contatti!.Count() == 1); + ClassicAssert.True(actualDatiFatturazione.Contatti!.ToList()[0].Email == expectedContatto); + } + + [Test] + public async Task UpdateCommand_ShouldSucceed_WithSameContatti() + { + string? expectedCup = "ecup"; + bool expectedNotaLegale = true; + string? expectedCodCommessa = "ecommmessa"; + DateTime expectedDataDocumento = DateTime.UtcNow.ItalianTime(); + bool? expectedSplitPayment = false; + string? expectedTipoCommessa = "1"; + string? expectedIdDocumento = "eiddocumento"; + string? expectedMap = "emap"; + DateTime expectedDataCreazione = DateTime.UtcNow.ItalianTime(); + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedPec = "pippo@pec.it"; + string? expectedProdotto = "prod-pn"; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto); + var expectedContatto = "pippo@gmail.com"; + List contatti = + [ + new DatiFatturazioneContattoCreateCommand() + { + Email = expectedContatto + }, + ]; + + var request = new DatiFatturazioneCreateCommand(authInfo) + { + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = contatti, + Cup = expectedCup, + DataCreazione = expectedDataCreazione, + DataDocumento = expectedDataDocumento, + Pec = expectedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + var actualDatiFatturazione = await _handler.Send(request); + ClassicAssert.IsNotNull(actualDatiFatturazione); + + DateTime expectedDataModifica = DateTime.UtcNow.AddMinutes(1); + var expectedUpdatedPec = "modified@pec.it"; + + + var updateRequest = new DatiFatturazioneUpdateCommand(authInfo) + { + Id = actualDatiFatturazione.Id, + NotaLegale = expectedNotaLegale, + CodCommessa = expectedCodCommessa, + Contatti = contatti, + Cup = expectedCup, + DataModifica = expectedDataModifica, + DataDocumento = expectedDataDocumento, + Pec = expectedUpdatedPec, + TipoCommessa = expectedTipoCommessa, + IdDocumento = expectedIdDocumento, + Map = expectedMap, + SplitPayment = expectedSplitPayment + }; + + actualDatiFatturazione = await _handler.Send(updateRequest); + + ClassicAssert.True(actualDatiFatturazione.NotaLegale == expectedNotaLegale); + ClassicAssert.True(actualDatiFatturazione.CodCommessa == expectedCodCommessa); + ClassicAssert.True(actualDatiFatturazione.Contatti!.Count() == 1); + ClassicAssert.True(actualDatiFatturazione.Contatti!.ToList()[0].Email == expectedContatto); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/DatiModuloCommessaCreateTests.cs b/tests/PortaleFatture.BE.UnitTest/DatiModuloCommessaCreateTests.cs new file mode 100644 index 0000000..ee67b83 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/DatiModuloCommessaCreateTests.cs @@ -0,0 +1,108 @@ +using MediatR; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using NUnit.Framework.Legacy; +using PortaleFatture.BE.Core.Auth; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Core.Extensions; +using PortaleFatture.BE.Core.Resources; +using PortaleFatture.BE.Infrastructure.Common.DatiModuloCommesse.Commands; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.UnitTest.Common; + +namespace PortaleFatture.BE.UnitTest; + +public class DatiModuloCommessaCreateTests +{ + private IDbContextFactory _factory; + private ILogger _logger; + private IStringLocalizer _localizer; + private IMediator _handler; + + [SetUp] + public void Setup() + { + _factory = ServiceProvider.GetRequiredService(); + _logger = ServiceProvider.GetRequiredService>(); + _localizer = ServiceProvider.GetRequiredService>(); + _handler = ServiceProvider.GetRequiredService(); + } + + [Test] + public void CreateCommand_ShouldFailNoAdmin_True() + { + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedProdotto = "prod-pn"; + var expectedTipoContratto = 1; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto, Ruolo.OPERATOR, expectedTipoContratto); + var (anno, mese, _, _) = Time.YearMonthDayFatturazione(); + + List cmds = []; + + for (var i = 1; i < 4; i++) + { + var request = new DatiModuloCommessaCreateCommand() + { + AnnoValidita = anno, + MeseValidita = mese, + IdEnte = expectedIdEnte, + IdTipoContratto = expectedTipoContratto, + IdTipoSpedizione = i, + NumeroNotificheInternazionali = 1, + NumeroNotificheNazionali = 1, + }; + cmds.Add(request); + } + var command = new DatiModuloCommessaCreateListCommand(authInfo) + { + DatiModuloCommessaListCommand = cmds + }; + + Assert.ThrowsAsync(async () => await _handler.Send(command)); + } + + [Test] + public async Task CreateCommand_ShouldSucceed_True() + { + string? expectedIdEnte = TestExtensions.GetRandomIdEnte(); + string? expectedProdotto = "prod-pn"; + var expectedTipoContratto = 1; + var authInfo = TestExtensions.GetAuthInfo(expectedIdEnte, expectedProdotto, Ruolo.ADMIN, expectedTipoContratto); + var (anno, mese, _, _) = Time.YearMonthDayFatturazione(); + + var conf = await CommonFactory.CreateDatiCommessaConfiguration(_handler, expectedTipoContratto, expectedProdotto); + List cmds = new(); + + for (var i = 1; i < 4; i++) + { + var request = new DatiModuloCommessaCreateCommand() + { + AnnoValidita = anno, + MeseValidita = mese, + IdEnte = expectedIdEnte, + IdTipoContratto = expectedTipoContratto, + IdTipoSpedizione = i, + NumeroNotificheInternazionali = 1, + NumeroNotificheNazionali = 1, + }; + cmds.Add(request); + } + var command = new DatiModuloCommessaCreateListCommand(authInfo) + { + DatiModuloCommessaListCommand = cmds + }; + + var moduloCommessa = await _handler.Send(command); + var commesse = moduloCommessa!.DatiModuloCommessa; + ClassicAssert.NotNull(commesse); + ClassicAssert.IsTrue(commesse.Count() == 3); + + var commess1 = commesse.Where(x => x.IdTipoSpedizione == 1).FirstOrDefault(); + ClassicAssert.IsNotNull(commess1); + ClassicAssert.IsTrue(commess1.IdEnte == expectedIdEnte); + ClassicAssert.IsTrue(commess1.MeseValidita == mese); + ClassicAssert.IsTrue(commess1.AnnoValidita == anno); + ClassicAssert.IsTrue(commess1.IdTipoContratto == expectedTipoContratto); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/GlobalUsings.cs b/tests/PortaleFatture.BE.UnitTest/GlobalUsings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/PortaleFatture.BE.UnitTest.csproj b/tests/PortaleFatture.BE.UnitTest/PortaleFatture.BE.UnitTest.csproj new file mode 100644 index 0000000..213a88c --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/PortaleFatture.BE.UnitTest.csproj @@ -0,0 +1,43 @@ + + + + net8.0 + enable + enable + + false + true + d0dd11cf-4318-484a-844d-058470676f42 + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + Always + + + Always + + + + diff --git a/tests/PortaleFatture.BE.UnitTest/ServiceProvider.cs b/tests/PortaleFatture.BE.UnitTest/ServiceProvider.cs new file mode 100644 index 0000000..cbb83ef --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/ServiceProvider.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using PortaleFatture.BE.Core.Common; +using PortaleFatture.BE.Core.Exceptions; +using PortaleFatture.BE.Infrastructure; +using PortaleFatture.BE.Infrastructure.Common.Persistence; +using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas; +using PortaleFatture.BE.Infrastructure.Common.Scadenziari; + +namespace PortaleFatture.BE.UnitTest; + +public static class ServiceProvider +{ + private static IServiceProvider Provider() + { + var services = new ServiceCollection(); + var configurationBuilder = new ConfigurationBuilder() + .AddJsonFile("appsettings.Development.json", optional: true) + .AddUserSecrets("d0dd11cf-4318-484a-844d-058470676f42") + .AddEnvironmentVariables() + .Build(); + + services.AddSingleton(configurationBuilder); + + var configuration = services + .BuildServiceProvider() + .GetRequiredService(); + + PortaleFattureOptions options = new(); + configuration.GetSection(nameof(PortaleFattureOptions)).Bind(options); + + services.AddSingleton(options); + + var sconf = configuration!.GetSection(nameof(PortaleFattureOptions)); + services.Configure(o => { o.SelfCareCertEndpoint = configuration.GetSection("PortaleFattureOptions:SelfCareCertEndpoint").Value; + o.ConnectionString = configuration.GetSection("PortaleFattureOptions:ConnectionString").Value; + o.SelfCareUri = configuration.GetSection("PortaleFattureOptions:SelfCareUri").Value; + }); + + var dbConnectionString = options.ConnectionString ?? + throw new ConfigurationException("Db connection string not configured"); + + services.AddSingleton(new DbContextFactory(dbConnectionString, "pfd")); + services.AddSingleton(new DbContextFactory(dbConnectionString, "pfw")); + services.AddSingleton(); + + services.AddMediatR(x => x.RegisterServicesFromAssembly(typeof(RootInfrastructure).Assembly)); + + services.AddLogging(); + + services.AddLocalization(options => options.ResourcesPath = "Resources"); + + return services.BuildServiceProvider(); + } + + public static T GetRequiredService() where T : class + { + var provider = Provider(); + return provider.GetRequiredService(); + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/appsettings.Development.json b/tests/PortaleFatture.BE.UnitTest/appsettings.Development.json new file mode 100644 index 0000000..a38cd88 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/appsettings.Development.json @@ -0,0 +1,20 @@ +{ + "Logging:LogLevel:Microsoft.Hosting": "Debug", + "Logging:LogLevel:Microsoft.EntityFrameworkCore": "Debug", + "Logging:LogLevel:Microsoft.AspNetCore": "Debug", + "Logging:LogLevel:Microsoft": "Debug", + "Logging:LogLevel:Default": "Debug", + "Locale": "it-IT", + "PortaleFattureOptions": { + "ConnectionString": "xxx", + "FattureSchema": "xxx", + "SelfCareSchema": "xxx", + "SelfCareUri": "", + "SelfCareCertEndpoint": "", + "Vault": "", + "JWT:ValidIssuer": "xxx", + "JWT:ValidAudience": "xxx", + "JWT:Secret": "xxx", + "JWT:TestToken": "xxx" + } +} \ No newline at end of file diff --git a/tests/PortaleFatture.BE.UnitTest/appsettings.json b/tests/PortaleFatture.BE.UnitTest/appsettings.json new file mode 100644 index 0000000..a947f00 --- /dev/null +++ b/tests/PortaleFatture.BE.UnitTest/appsettings.json @@ -0,0 +1,20 @@ +{ + "Logging:LogLevel:Microsoft.Hosting": "Debug", + "Logging:LogLevel:Microsoft.EntityFrameworkCore": "Debug", + "Logging:LogLevel:Microsoft.AspNetCore": "Debug", + "Logging:LogLevel:Microsoft": "Debug", + "Logging:LogLevel:Default": "Debug", + "Locale": "it-IT", + "PortaleFattureOptions": { + "ConnectionString": "xxx", + "FattureSchema": "pfw", + "SelfCareSchema": "pfd", + "SelfCareUri": "", + "SelfCareCertEndpoint": "", + "Vault": "", + "JWT:ValidIssuer": "xxx", + "JWT:ValidAudience": "xxx", + "JWT:Secret": "xxx", + "JWT:TestToken": "xxx" + } +} \ No newline at end of file diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100644 index 0000000..a9307ce --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + database: + container_name: portalefatture_db + hostname: PortaleFatture.BE.Api.Tests + image: portalefatture_mssql/server + build: + context: . + dockerfile: data/Dockerfile + restart: unless-stopped + environment: + SA_PASSWORD: "52JdGnzZaANhf" + ACCEPT_EULA: "Y" + ports: + - "1433:1433" + volumes: + - mssqldata:/var/opt/mssql +volumes: + mssqldata: \ No newline at end of file