From ef2fcff779d1c0f1ebfc699f6512203c1a650b0d Mon Sep 17 00:00:00 2001 From: francescods Date: Fri, 3 Oct 2025 12:19:04 +0200 Subject: [PATCH] aggiornamento saldo tessera e inserimento movimento di storno separazione del mapping tra TESSERE e VIEW_TESSERE_API per il recupero dei dati della tessera da inserire nel movimento di storno gestione delle eccezioni per ogni query di select, insert e update legate all'annullamento (eccezione generica per il blocco) aggiunta campo VASSOIO nella VIEW_PRENOTAZIONI_PASTI --- src/main/kotlin/eu/maiora/db/Mapping.kt | 239 ++++++++++++------ .../kotlin/eu/maiora/model/DwhMovimenti.kt | 38 +++ .../eu/maiora/model/DwhMovimentiRepository.kt | 5 + .../model/DwhMovimentiRepositoryImpl.kt | 71 ++++++ src/main/kotlin/eu/maiora/model/Tessere.kt | 6 +- .../eu/maiora/model/TessereRepository.kt | 2 +- .../eu/maiora/model/TessereRepositoryImpl.kt | 14 +- .../eu/maiora/model/ViewPrenotazioniPasti.kt | 3 + .../kotlin/eu/maiora/model/ViewTessereAPI.kt | 14 + .../maiora/model/ViewTessereAPIRepository.kt | 6 + .../model/ViewTessereAPIRepositoryImpl.kt | 23 ++ src/main/kotlin/eu/maiora/plugins/Routing.kt | 8 +- .../eu/maiora/routes/AnnullaPrenotazioni.kt | 156 ++++++++++-- src/main/kotlin/eu/maiora/routes/Tessere.kt | 4 +- 14 files changed, 485 insertions(+), 104 deletions(-) create mode 100644 src/main/kotlin/eu/maiora/model/DwhMovimenti.kt create mode 100644 src/main/kotlin/eu/maiora/model/DwhMovimentiRepository.kt create mode 100644 src/main/kotlin/eu/maiora/model/DwhMovimentiRepositoryImpl.kt create mode 100644 src/main/kotlin/eu/maiora/model/ViewTessereAPI.kt create mode 100644 src/main/kotlin/eu/maiora/model/ViewTessereAPIRepository.kt create mode 100644 src/main/kotlin/eu/maiora/model/ViewTessereAPIRepositoryImpl.kt diff --git a/src/main/kotlin/eu/maiora/db/Mapping.kt b/src/main/kotlin/eu/maiora/db/Mapping.kt index 3b2de44..051b339 100644 --- a/src/main/kotlin/eu/maiora/db/Mapping.kt +++ b/src/main/kotlin/eu/maiora/db/Mapping.kt @@ -3,6 +3,8 @@ package eu.maiora.db import eu.maiora.model.* import kotlinx.coroutines.Dispatchers +import kotlinx.datetime.toKotlinLocalDate +import kotlinx.datetime.toKotlinLocalDateTime import org.jetbrains.exposed.dao.* import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.dao.id.IdTable @@ -13,8 +15,7 @@ import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransacti import java.time.format.DateTimeFormatter - -object AccountsTable : IdTable("accounts"){ +object AccountsTable : IdTable("accounts") { override val id = integer("id").entityId() val username = varchar("username", 255) val password = varchar("password", 255) @@ -22,7 +23,7 @@ object AccountsTable : IdTable("accounts"){ override val primaryKey = PrimaryKey(id) } -object ParametriTable : IdTable("parametri"){ +object ParametriTable : IdTable("parametri") { override val id = integer("id").entityId() val chiave = varchar("chiave", 255) val valore = varchar("valore", 255) @@ -30,7 +31,15 @@ object ParametriTable : IdTable("parametri"){ override val primaryKey = PrimaryKey(id) } -object TessereTable : IdTable("view_tessere_api"){ +object TessereTable : IdTable("tessere") { + override val id = long("id").entityId() + val saldo = double("saldo") + val tsUltimoUtilizzo = datetime("ts_ultimo_utilizzo") + + override val primaryKey = PrimaryKey(id) +} + +object ViewTessereAPITable : IdTable("view_tessere_api") { override val id = long("id").entityId() val idUtente = long("id_utente") val codiceFiscale = varchar("codice_fiscale", 255) @@ -41,7 +50,7 @@ object TessereTable : IdTable("view_tessere_api"){ override val primaryKey = PrimaryKey(id) } -object MovimentiTable : IdTable("view_movimenti_api"){ +object MovimentiTable : IdTable("view_movimenti_api") { override val id = long("id").entityId() val idTessera = long("id_tessera") val numero = varchar("numero_tessera", 255) @@ -49,7 +58,7 @@ object MovimentiTable : IdTable("view_movimenti_api"){ val dataMovimento = datetime("data_movimento") val transazione = varchar("transazione", 255) val dispositivo = varchar("dispositivo", 255) - val riferimento= varchar("riferimento", 255) + val riferimento = varchar("riferimento", 255) val saldoPre = double("saldo_pre") val importo = double("importo") val saldoPost = double("saldo_post") @@ -59,7 +68,36 @@ object MovimentiTable : IdTable("view_movimenti_api"){ val dettagli = varchar("dettagli", 255) } -object ComposizioniTable : IdTable("view_composizioni"){ +object DwhMovimentiTable : IdTable("dwh.movimenti") { + override val id = long("id").autoIncrement("dwh.seq_movimenti").entityId() + val idTessera = long("id_tessera") + val numero = varchar("numero", 255) + val operazione = varchar("operazione", 255) + val data = datetime("DATA") + val transazione = long("transazione") + val dispositivo = varchar("dispositivo", 255) + val riferimento = varchar("riferimento", 255) + val saldoPre = double("saldo_pre") + val importo = double("importo") + val saldoPost = double("saldo_post") + val puntiPre = long("punti_pre") + val punti = long("punti") + val puntiPost = long("punti_post") + val flagPassaggioTessera = integer("flag_passaggio_tessera") + val oggetto = varchar("oggetto", 255) + val cognome = varchar("cognome", 255) + val nome = varchar("nome", 255) + val codiceFiscale = varchar("codice_fiscale", 255) + val azienda = varchar("azienda", 255) + val categoriaUtenti = varchar("categoria_utenti", 255) + val fascia = varchar("fascia", 255) + val idTipoMovimentoConto = integer("id_tipo_movimento_conto") + val giorno = date("giorno") + val modalita = varchar("modalita", 255) + val idModalita = long("id_modalita") +} + +object ComposizioniTable : IdTable("view_composizioni") { override val id = long("id").entityId() val idVassoio = long("id_vassoio") val vassoio = varchar("vassoio", 255) @@ -68,7 +106,7 @@ object ComposizioniTable : IdTable("view_composizioni"){ val quantita = integer("quantita") } -object RicaricheTable : IdTable("ricariche_app"){ +object RicaricheTable : IdTable("ricariche_app") { override val id = long("id").autoIncrement("seq_ricariche_app").entityId() val codiceTransazione = varchar("codice_transazione", 255) val messaggio = varchar("messaggio", 255).nullable() @@ -76,7 +114,7 @@ object RicaricheTable : IdTable("ricariche_app"){ val importo = double("importo") } -object SlotPrenotabiliTable : IdTable("view_slot_prenotabili"){ +object SlotPrenotabiliTable : IdTable("view_slot_prenotabili") { override val id = long("id").entityId() val giorno = date("giorno") val dataInizio = datetime("data_inizio") @@ -94,7 +132,7 @@ object SlotPrenotabiliTable : IdTable("view_slot_prenotabili"){ val residenza = varchar("residenza", 255).nullable() } -object ProdottiPrenotabiliTable : IdTable("view_prodotti_prenotabili"){ +object ProdottiPrenotabiliTable : IdTable("view_prodotti_prenotabili") { override val id = long("id").entityId() val giorno = date("giorno") val idPuntoDistribuzione = long("id_punto_distribuzione") @@ -111,13 +149,13 @@ object ProdottiPrenotabiliTable : IdTable("view_prodotti_prenotabili"){ val modalitaPrenotazione = varchar("modalita_prenotazione", 255) } -object ResidenzeTable : IdTable("residenze"){ +object ResidenzeTable : IdTable("residenze") { override val id = long("id").entityId() val idPuntoDistribuzione = long("id_punto_distribuzione") val nome = varchar("nome", 255) } -object PrenotazioniPastiTable : IdTable("prenotazioni_pasti"){ +object PrenotazioniPastiTable : IdTable("prenotazioni_pasti") { override val id = long("id").autoIncrement("seq_prenotazioni_pasti").entityId() val idTessera = long("id_tessera") val idSlotPuntoCassa = long("id_slot_punto_cassa") @@ -127,7 +165,7 @@ object PrenotazioniPastiTable : IdTable("prenotazioni_pasti"){ val codiceRistocloud = varchar("codice_ristocloud", 255).nullable() } -object PrenotazioniPastiDettaglioTable : IdTable("prenotazioni_pasti_dettaglio"){ +object PrenotazioniPastiDettaglioTable : IdTable("prenotazioni_pasti_dettaglio") { override val id = long("id").autoIncrement("seq_pren_past_dettaglio").entityId() val idPrenotazione = long("id_prenotazione") val idProdotto = long("id_prodotto") @@ -135,7 +173,7 @@ object PrenotazioniPastiDettaglioTable : IdTable("prenotazioni_pasti_detta } -object ViewPrenotazioniPastiTable : IdTable("view_prenotazioni_pasti"){ +object ViewPrenotazioniPastiTable : IdTable("view_prenotazioni_pasti") { override val id = long("id").entityId() val idPrenotazione = long("id_prenotazione") val idStato = long("id_stato") @@ -148,6 +186,7 @@ object ViewPrenotazioniPastiTable : IdTable("view_prenotazioni_pasti"){ val dataFine = datetime("data_fine") val dataLimiteCancellazione = datetime("data_limite_cancellazione") val idVassoio = long("id_vassoio").nullable() + val vassoio = varchar("vassoio", 255) val codiceRistocloud = varchar("codice_ristocloud", 255).nullable() val importoPagato = double("importo_pagato") val puntoDistribuzione = varchar("punto_distribuzione", 255) @@ -158,31 +197,38 @@ object ViewPrenotazioniPastiTable : IdTable("view_prenotazioni_pasti"){ } -class AccountsDAO(id: EntityID) :IntEntity(id) { +class AccountsDAO(id: EntityID) : IntEntity(id) { companion object : IntEntityClass(AccountsTable) var username by AccountsTable.username var password by AccountsTable.password } -class ParametriDAO(id: EntityID) :IntEntity(id) { +class ParametriDAO(id: EntityID) : IntEntity(id) { companion object : IntEntityClass(ParametriTable) var chiave by ParametriTable.chiave var valore by ParametriTable.valore } -class TessereDao(id: EntityID) :LongEntity(id) { +class TessereDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(TessereTable) - var idUtente by TessereTable.idUtente - var codiceFiscale by TessereTable.codiceFiscale - var numero by TessereTable.numero var saldo by TessereTable.saldo - var punti by TessereTable.punti + var tsUltimoUtilizzo by TessereTable.tsUltimoUtilizzo } -class MovimentiDao(id: EntityID) :LongEntity(id) { +class ViewTessereAPIDao(id: EntityID) : LongEntity(id) { + companion object : LongEntityClass(ViewTessereAPITable) + + var idUtente by ViewTessereAPITable.idUtente + var codiceFiscale by ViewTessereAPITable.codiceFiscale + var numero by ViewTessereAPITable.numero + var saldo by ViewTessereAPITable.saldo + var punti by ViewTessereAPITable.punti +} + +class MovimentiDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(MovimentiTable) var idTessera by MovimentiTable.idTessera @@ -201,7 +247,37 @@ class MovimentiDao(id: EntityID) :LongEntity(id) { var dettagli by MovimentiTable.dettagli } -class ComposizioniDao(id: EntityID) :LongEntity(id){ +class DwhMovimentiDao(id: EntityID) : LongEntity(id) { + companion object : LongEntityClass(DwhMovimentiTable) + + var idTessera by DwhMovimentiTable.idTessera + var numero by DwhMovimentiTable.numero + var operazione by DwhMovimentiTable.operazione + var data by DwhMovimentiTable.data + var transazione by DwhMovimentiTable.transazione + var dispositivo by DwhMovimentiTable.dispositivo + var riferimento by DwhMovimentiTable.riferimento + var saldoPre by DwhMovimentiTable.saldoPre + var importo by DwhMovimentiTable.importo + var saldoPost by DwhMovimentiTable.saldoPost + var puntiPre by DwhMovimentiTable.puntiPre + var punti by DwhMovimentiTable.punti + var puntiPost by DwhMovimentiTable.puntiPost + var flagPassaggioTessera by DwhMovimentiTable.flagPassaggioTessera + var oggetto by DwhMovimentiTable.oggetto + var cognome by DwhMovimentiTable.cognome + var nome by DwhMovimentiTable.nome + var codiceFiscale by DwhMovimentiTable.codiceFiscale + var azienda by DwhMovimentiTable.azienda + var categoriaUtenti by DwhMovimentiTable.categoriaUtenti + var fascia by DwhMovimentiTable.fascia + var idTipoMovimentoConto by DwhMovimentiTable.idTipoMovimentoConto + var giorno by DwhMovimentiTable.giorno + var modalita by DwhMovimentiTable.modalita + var idModalita by DwhMovimentiTable.idModalita +} + +class ComposizioniDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(ComposizioniTable) var idVassoio by ComposizioniTable.idVassoio @@ -211,7 +287,7 @@ class ComposizioniDao(id: EntityID) :LongEntity(id){ var quantita by ComposizioniTable.quantita } -class RicaricheDao(id: EntityID) :LongEntity(id){ +class RicaricheDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(RicaricheTable) var codiceTransazione by RicaricheTable.codiceTransazione @@ -220,7 +296,7 @@ class RicaricheDao(id: EntityID) :LongEntity(id){ var importo by RicaricheTable.importo } -class SlotPrenotabiliDao(id: EntityID) :LongEntity(id) { +class SlotPrenotabiliDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(SlotPrenotabiliTable) var giorno by SlotPrenotabiliTable.giorno @@ -239,7 +315,7 @@ class SlotPrenotabiliDao(id: EntityID) :LongEntity(id) { var residenza by SlotPrenotabiliTable.residenza } -class ProdottiPrenotabiliDao(id: EntityID) :LongEntity(id) { +class ProdottiPrenotabiliDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(ProdottiPrenotabiliTable) var giorno by ProdottiPrenotabiliTable.giorno @@ -257,14 +333,14 @@ class ProdottiPrenotabiliDao(id: EntityID) :LongEntity(id) { var modalitaPrenotazione by ProdottiPrenotabiliTable.modalitaPrenotazione } -class ResidenzeDao(id: EntityID) :LongEntity(id){ +class ResidenzeDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(ResidenzeTable) val idPuntoDistribuzione by ResidenzeTable.idPuntoDistribuzione val nome by ResidenzeTable.nome } -class PrenotazioniPastiDao(id: EntityID) :LongEntity(id){ +class PrenotazioniPastiDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(PrenotazioniPastiTable) val idTessera by PrenotazioniPastiTable.idTessera @@ -275,7 +351,7 @@ class PrenotazioniPastiDao(id: EntityID) :LongEntity(id){ val codiceRistocloud by PrenotazioniPastiTable.codiceRistocloud } -class PrenotazioniPastiDettaglioDao(id: EntityID) :LongEntity(id){ +class PrenotazioniPastiDettaglioDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(PrenotazioniPastiDettaglioTable) val idPrenotazione by PrenotazioniPastiDettaglioTable.idPrenotazione @@ -283,7 +359,7 @@ class PrenotazioniPastiDettaglioDao(id: EntityID) :LongEntity(id){ val idStato by PrenotazioniPastiDettaglioTable.idStato } -class ViewPrenotazioniPastiDao(id: EntityID) :LongEntity(id){ +class ViewPrenotazioniPastiDao(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(ViewPrenotazioniPastiTable) val idPrenotazione by ViewPrenotazioniPastiTable.idPrenotazione @@ -297,6 +373,7 @@ class ViewPrenotazioniPastiDao(id: EntityID) :LongEntity(id){ val dataFine by ViewPrenotazioniPastiTable.dataFine val dataLimiteCancellazione by ViewPrenotazioniPastiTable.dataLimiteCancellazione val idVassoio by ViewPrenotazioniPastiTable.idVassoio + val vassoio by ViewPrenotazioniPastiTable.vassoio val codiceRistocloud by ViewPrenotazioniPastiTable.codiceRistocloud val importoPagato by ViewPrenotazioniPastiTable.importoPagato val puntoDistribuzione by ViewPrenotazioniPastiTable.puntoDistribuzione @@ -321,14 +398,25 @@ fun parametriDaoToModel(dao: ParametriDAO) = Parametri( fun tessereDaoToModel(dao: TessereDao) = Tessere( dao.id.value, - dao.idUtente, - dao.codiceFiscale, - dao.numero, dao.saldo, - dao.punti + dao.tsUltimoUtilizzo.toKotlinLocalDateTime() ) -fun movimentiDaoToModel(dao: MovimentiDao) :Movimenti{ + +fun viewTessereAPIDaoToModel(dao: ViewTessereAPIDao): ViewTessereAPI { + + return ViewTessereAPI( + dao.id.value, + dao.idUtente, + dao.codiceFiscale, + dao.numero, + dao.saldo, + dao.punti + ) +} + + +fun movimentiDaoToModel(dao: MovimentiDao): Movimenti { val formatter = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") val formattedDate = dao.dataMovimento.format(formatter) @@ -351,6 +439,36 @@ fun movimentiDaoToModel(dao: MovimentiDao) :Movimenti{ ) } +fun dwhMovimentiDaoToModel(dao: DwhMovimentiDao) = DwhMovimenti( + dao.id.value, + dao.idTessera, + dao.numero, + dao.operazione, + dao.data.toKotlinLocalDateTime(), + dao.transazione, + dao.dispositivo, + dao.riferimento, + dao.saldoPre, + dao.importo, + dao.saldoPost, + dao.puntiPre, + dao.punti, + dao.puntiPost, + dao.flagPassaggioTessera, + dao.oggetto, + dao.cognome, + dao.nome, + dao.codiceFiscale, + dao.azienda, + dao.categoriaUtenti, + dao.fascia, + dao.idTipoMovimentoConto, + dao.giorno.toKotlinLocalDate(), + dao.modalita, + dao.idModalita +) + + fun composizioniDaoToModel(dao: ComposizioniDao) = Composizioni( dao.id.value, dao.idVassoio, @@ -360,7 +478,7 @@ fun composizioniDaoToModel(dao: ComposizioniDao) = Composizioni( dao.quantita ) -fun puntiDistribuzioneDaoToModel(dao: SlotPrenotabiliDao) :PuntiDistribuzione{ +fun puntiDistribuzioneDaoToModel(dao: SlotPrenotabiliDao): PuntiDistribuzione { return PuntiDistribuzione( dao.id.value, dao.idPuntoDistribuzione, @@ -372,7 +490,7 @@ fun puntiDistribuzioneDaoToModel(dao: SlotPrenotabiliDao) :PuntiDistribuzione{ ) } -fun slotOrariDaoToModel(dao: SlotPrenotabiliDao) :SlotOrari{ +fun slotOrariDaoToModel(dao: SlotPrenotabiliDao): SlotOrari { val formatterGiorno = DateTimeFormatter.ofPattern("ddMMyyyy") val formatterConOra = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") val formattedGiorno = dao.giorno.format(formatterGiorno) @@ -399,7 +517,7 @@ fun slotOrariDaoToModel(dao: SlotPrenotabiliDao) :SlotOrari{ ) } -fun prodottiPrenotabiliDaoToModel(dao: ProdottiPrenotabiliDao) :ProdottiPrenotabili{ +fun prodottiPrenotabiliDaoToModel(dao: ProdottiPrenotabiliDao): ProdottiPrenotabili { val formatterGiorno = DateTimeFormatter.ofPattern("ddMMyyyy") val formattedGiorno = dao.giorno.format(formatterGiorno) @@ -421,7 +539,7 @@ fun prodottiPrenotabiliDaoToModel(dao: ProdottiPrenotabiliDao) :ProdottiPrenotab ) } -fun residenzeDaoToModel(dao: ResidenzeDao) :Residenze{ +fun residenzeDaoToModel(dao: ResidenzeDao): Residenze { return Residenze( dao.id.value, dao.idPuntoDistribuzione, @@ -429,7 +547,7 @@ fun residenzeDaoToModel(dao: ResidenzeDao) :Residenze{ ) } -fun prenotazioniPastiDaoToModel(dao: PrenotazioniPastiDao) : PrenotazioniPasti{ +fun prenotazioniPastiDaoToModel(dao: PrenotazioniPastiDao): PrenotazioniPasti { return PrenotazioniPasti( dao.id.value, dao.idTessera, @@ -441,7 +559,7 @@ fun prenotazioniPastiDaoToModel(dao: PrenotazioniPastiDao) : PrenotazioniPasti{ ) } -fun prenotazioniPastiDettaglioDaoToModel(dao: PrenotazioniPastiDettaglioDao) : PrenotazioniPastiDettaglio{ +fun prenotazioniPastiDettaglioDaoToModel(dao: PrenotazioniPastiDettaglioDao): PrenotazioniPastiDettaglio { return PrenotazioniPastiDettaglio( dao.id.value, dao.idPrenotazione, @@ -450,39 +568,11 @@ fun prenotazioniPastiDettaglioDaoToModel(dao: PrenotazioniPastiDettaglioDao) : P ) } -/*fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao) : ViewPrenotazioniPasti{ - val formatterGiorno = DateTimeFormatter.ofPattern("ddMMyyyy") - val formatterDataInizio = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") - val formatterDataFine = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") - val formatterDataLimiteCancellazione = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") - val formattedGiorno = dao.giorno.format(formatterGiorno) - val formattedDataInizio = dao.dataInizio.format(formatterDataInizio) - val formattedDataFine = dao.dataFine.format(formatterDataFine) - val formattedDataLimiteCanc = dao.dataLimiteCancellazione.format(formatterDataLimiteCancellazione) - - - return ViewPrenotazioniPasti( - dao.idPrenotazione, - dao.idStato, - dao.stato, - dao.idTessera, - dao.idSlotPuntoCassa, - formattedGiorno, - dao.turno, - formattedDataInizio, - formattedDataFine, - formattedDataLimiteCanc, - dao.idVassoio, - dao.codiceRistocloud, - dao.importoPagato, - dao.puntoDistribuzione, - dao.puntoCassa, - dao.modalita, - null - ) -}*/ - -fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao, listaProdotti: List? = null) : ViewPrenotazioniPasti{ + +fun viewPrenotazioniPastiDaoToModel( + dao: ViewPrenotazioniPastiDao, + listaProdotti: List? = null +): ViewPrenotazioniPasti { val formatterGiorno = DateTimeFormatter.ofPattern("ddMMyyyy") val formatterDataInizio = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") val formatterDataFine = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm") @@ -505,6 +595,7 @@ fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao, listaProdotti formattedDataFine, formattedDataLimiteCanc, dao.idVassoio, + dao.vassoio, dao.codiceRistocloud, dao.importoPagato, dao.puntoDistribuzione, diff --git a/src/main/kotlin/eu/maiora/model/DwhMovimenti.kt b/src/main/kotlin/eu/maiora/model/DwhMovimenti.kt new file mode 100644 index 0000000..35e7eed --- /dev/null +++ b/src/main/kotlin/eu/maiora/model/DwhMovimenti.kt @@ -0,0 +1,38 @@ +package eu.maiora.model + +import kotlinx.datetime.LocalDate +import kotlinx.datetime.LocalDateTime +import kotlinx.serialization.Serializable + + + +@Serializable +data class DwhMovimenti( + val id: Long, + val idTessera: Long, + val numero: String, + val operazione: String, + val data: LocalDateTime, + val transazione: Long, + val dispositivo: String, + val riferimento: String, + val saldoPre: Double, + val importo: Double, + val saldoPost: Double, + val puntiPre: Long, + val punti: Long, + val puntiPost: Long, + val flagPassaggioTessera: Int, + val oggetto: String, + val cognome: String, + val nome: String, + val codiceFiscale: String, + val azienda: String, + val categoriaUtenti: String, + val fascia: String, + val idTipoMovimentoConto: Int, + val giorno: LocalDate, + val modalita: String, + val idModalita: Long + +) \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/DwhMovimentiRepository.kt b/src/main/kotlin/eu/maiora/model/DwhMovimentiRepository.kt new file mode 100644 index 0000000..0b80f90 --- /dev/null +++ b/src/main/kotlin/eu/maiora/model/DwhMovimentiRepository.kt @@ -0,0 +1,5 @@ +package eu.maiora.model + +interface DwhMovimentiRepository { + suspend fun insert(movimento : DwhMovimenti): DwhMovimenti +} diff --git a/src/main/kotlin/eu/maiora/model/DwhMovimentiRepositoryImpl.kt b/src/main/kotlin/eu/maiora/model/DwhMovimentiRepositoryImpl.kt new file mode 100644 index 0000000..5e9b5ba --- /dev/null +++ b/src/main/kotlin/eu/maiora/model/DwhMovimentiRepositoryImpl.kt @@ -0,0 +1,71 @@ +package eu.maiora.model + +import eu.maiora.db.* +import kotlinx.datetime.toJavaLocalDate +import kotlinx.datetime.toJavaLocalDateTime +import org.jetbrains.exposed.sql.insertAndGetId + + +class DwhMovimentiRepositoryImpl : DwhMovimentiRepository { + + override suspend fun insert(movimento : DwhMovimenti): DwhMovimenti = suspendTransaction { + // Inserisci un nuovo movimento + // ID non definito: viene gestito dalla sequence + val idMovimentoInserted = DwhMovimentiTable.insertAndGetId { + it[idTessera] = movimento.idTessera + it[numero] = movimento.numero + it[operazione] = movimento.operazione + it[data] = movimento.data.toJavaLocalDateTime() + it[transazione] = movimento.transazione + it[dispositivo] = movimento.dispositivo + it[riferimento] = movimento.riferimento + it[saldoPre] = movimento.saldoPre + it[importo] = movimento.importo + it[saldoPost] = movimento.saldoPost + it[puntiPre] = movimento.puntiPre + it[punti] = movimento.punti + it[puntiPost] = movimento.puntiPost + it[flagPassaggioTessera] = movimento.flagPassaggioTessera + it[oggetto] = movimento.oggetto + it[cognome] = movimento.cognome + it[nome] = movimento.nome + it[codiceFiscale] = movimento.codiceFiscale + it[azienda] = movimento.azienda + it[categoriaUtenti] = movimento.categoriaUtenti + it[fascia] = movimento.fascia + it[idTipoMovimentoConto] = movimento.idTipoMovimentoConto + it[giorno] = movimento.giorno.toJavaLocalDate() + it[modalita] = movimento.modalita + it[idModalita] = movimento.idModalita + }.value + + DwhMovimenti( + idMovimentoInserted, + movimento.idTessera, + movimento.numero, + movimento.operazione, + movimento.data, + movimento.transazione, + movimento.dispositivo, + movimento.riferimento, + movimento.saldoPre, + movimento.importo, + movimento.saldoPost, + movimento.puntiPre, + movimento.punti, + movimento.puntiPost, + movimento.flagPassaggioTessera, + movimento.oggetto, + movimento.cognome, + movimento.nome, + movimento.codiceFiscale, + movimento.azienda, + movimento.categoriaUtenti, + movimento.fascia, + movimento.idTipoMovimentoConto, + movimento.giorno, + movimento.modalita, + movimento.idModalita + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/Tessere.kt b/src/main/kotlin/eu/maiora/model/Tessere.kt index 47c9108..4763942 100644 --- a/src/main/kotlin/eu/maiora/model/Tessere.kt +++ b/src/main/kotlin/eu/maiora/model/Tessere.kt @@ -1,13 +1,11 @@ package eu.maiora.model +import kotlinx.datetime.LocalDateTime import kotlinx.serialization.Serializable @Serializable data class Tessere( val id: Long, - val idUtente : Long, - val codiceFiscale : String, - val numero : String, val saldo : Double, - val punti : Int + val tsUltimoUtilizzo : LocalDateTime ) \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/TessereRepository.kt b/src/main/kotlin/eu/maiora/model/TessereRepository.kt index fd6df68..9300a82 100644 --- a/src/main/kotlin/eu/maiora/model/TessereRepository.kt +++ b/src/main/kotlin/eu/maiora/model/TessereRepository.kt @@ -1,5 +1,5 @@ package eu.maiora.model interface TessereRepository { - suspend fun tesseraByCodiceFiscale(cf : String): Tessere? + suspend fun update(tessera: Tessere): Tessere } \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/TessereRepositoryImpl.kt b/src/main/kotlin/eu/maiora/model/TessereRepositoryImpl.kt index 93dce0c..ad6104d 100644 --- a/src/main/kotlin/eu/maiora/model/TessereRepositoryImpl.kt +++ b/src/main/kotlin/eu/maiora/model/TessereRepositoryImpl.kt @@ -1,13 +1,17 @@ package eu.maiora.model import eu.maiora.db.* +import kotlinx.datetime.toJavaLocalDateTime +import org.jetbrains.exposed.sql.update class TessereRepositoryImpl : TessereRepository { - override suspend fun tesseraByCodiceFiscale(cf: String): Tessere? = suspendTransaction { - // Cerca tessere in base al codice fiscale - TessereDao.find { TessereTable.codiceFiscale eq cf } - .singleOrNull() // Restituisce un singolo risultato o null se non trovato - ?.let { tessereDaoToModel(it) } // Converte il DAO in un oggetto Tessere + override suspend fun update (tessera : Tessere): Tessere = suspendTransaction { + TessereTable.update({TessereTable.id eq tessera.id}){ + it[saldo] = tessera.saldo + it[tsUltimoUtilizzo] = tessera.tsUltimoUtilizzo.toJavaLocalDateTime() + } + + tessera } } \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/ViewPrenotazioniPasti.kt b/src/main/kotlin/eu/maiora/model/ViewPrenotazioniPasti.kt index d33b26a..b81bc3e 100644 --- a/src/main/kotlin/eu/maiora/model/ViewPrenotazioniPasti.kt +++ b/src/main/kotlin/eu/maiora/model/ViewPrenotazioniPasti.kt @@ -1,6 +1,7 @@ package eu.maiora.model import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient @Serializable data class ViewPrenotazioniPasti( @@ -15,6 +16,8 @@ data class ViewPrenotazioniPasti( val dataFine: String, val dataLimiteCancellazione: String, val idVassoio: Long? = null, + @Transient + val vassoio: String = "", val codiceRistocloud: String? = null, val importoPagato: Double, val puntoDistribuzione: String, diff --git a/src/main/kotlin/eu/maiora/model/ViewTessereAPI.kt b/src/main/kotlin/eu/maiora/model/ViewTessereAPI.kt new file mode 100644 index 0000000..009452c --- /dev/null +++ b/src/main/kotlin/eu/maiora/model/ViewTessereAPI.kt @@ -0,0 +1,14 @@ +package eu.maiora.model + +import kotlinx.serialization.Serializable +import javax.management.monitor.StringMonitor + +@Serializable +data class ViewTessereAPI( + val id: Long, + val idUtente : Long, + val codiceFiscale : String, + val numero : String, + val saldo : Double, + val punti : Int +) \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/ViewTessereAPIRepository.kt b/src/main/kotlin/eu/maiora/model/ViewTessereAPIRepository.kt new file mode 100644 index 0000000..a5ae03c --- /dev/null +++ b/src/main/kotlin/eu/maiora/model/ViewTessereAPIRepository.kt @@ -0,0 +1,6 @@ +package eu.maiora.model + +interface ViewTessereAPIRepository { + suspend fun tesseraByCodiceFiscale(cf : String): ViewTessereAPI? + suspend fun tesseraById(id : Long): ViewTessereAPI? +} \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/model/ViewTessereAPIRepositoryImpl.kt b/src/main/kotlin/eu/maiora/model/ViewTessereAPIRepositoryImpl.kt new file mode 100644 index 0000000..954f741 --- /dev/null +++ b/src/main/kotlin/eu/maiora/model/ViewTessereAPIRepositoryImpl.kt @@ -0,0 +1,23 @@ +package eu.maiora.model + +import eu.maiora.db.* +import org.jetbrains.exposed.sql.update +import java.time.LocalDateTime + +class ViewTessereAPIRepositoryImpl : ViewTessereAPIRepository { + override suspend fun tesseraByCodiceFiscale(cf: String): ViewTessereAPI? = suspendTransaction { + // Cerca tessere in base al codice fiscale + ViewTessereAPIDao.find { ViewTessereAPITable.codiceFiscale eq cf } + .singleOrNull() // Restituisce un singolo risultato o null se non trovato + ?.let { viewTessereAPIDaoToModel(it) } // Converte il DAO in un oggetto ViewTessereAPI + + } + + override suspend fun tesseraById(id: Long): ViewTessereAPI? = suspendTransaction{ + //Cerca tessera in base all'id + ViewTessereAPIDao.find{ViewTessereAPITable.id eq id} + .singleOrNull() + ?.let{viewTessereAPIDaoToModel(it)} + + } +} \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/plugins/Routing.kt b/src/main/kotlin/eu/maiora/plugins/Routing.kt index 25e5974..f587e60 100644 --- a/src/main/kotlin/eu/maiora/plugins/Routing.kt +++ b/src/main/kotlin/eu/maiora/plugins/Routing.kt @@ -13,7 +13,7 @@ fun Application.configureRouting() { } auth(AccountsRepositoryImpl()) - tessere(TessereRepositoryImpl()) + tessere(ViewTessereAPIRepositoryImpl()) movimenti(MovimentiRepositoryImpl()) composizioni(ComposizioniRepositoryImpl()) valorePasti(ValorePastiRepositoryImpl()) @@ -26,7 +26,11 @@ fun Application.configureRouting() { SlotOrariRepositoryImpl(), PrenotazioniPastiDettaglioRepositoryImpl(), ViewPrenotazioniPastiRepositoryImpl()) - annullaPrenotazioni(ViewPrenotazioniPastiRepositoryImpl(), PrenotazioniPastiDettaglioRepositoryImpl()) + annullaPrenotazioni(ViewPrenotazioniPastiRepositoryImpl(), + PrenotazioniPastiDettaglioRepositoryImpl(), + TessereRepositoryImpl(), + ViewTessereAPIRepositoryImpl(), + DwhMovimentiRepositoryImpl()) verificaVassoio(SelezionaComposizioneRepositoryImpl()) } } diff --git a/src/main/kotlin/eu/maiora/routes/AnnullaPrenotazioni.kt b/src/main/kotlin/eu/maiora/routes/AnnullaPrenotazioni.kt index 7fae535..206e171 100644 --- a/src/main/kotlin/eu/maiora/routes/AnnullaPrenotazioni.kt +++ b/src/main/kotlin/eu/maiora/routes/AnnullaPrenotazioni.kt @@ -6,14 +6,22 @@ import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.response.* import io.ktor.server.routing.* -import kotlinx.datetime.toJavaLocalDateTime +import kotlinx.datetime.toKotlinLocalDate +import kotlinx.datetime.toKotlinLocalDateTime +import kotlinx.serialization.Serializable +import org.jetbrains.exposed.sql.transactions.TransactionManager +import org.jetbrains.exposed.sql.transactions.transaction +import java.time.LocalDate import java.time.LocalDateTime import java.time.format.DateTimeFormatter fun Route.annullaPrenotazioni( viewPrenotazioniPastiRepository: ViewPrenotazioniPastiRepositoryImpl, - prenotazioniPastiDettaglioRepository: PrenotazioniPastiDettaglioRepositoryImpl + prenotazioniPastiDettaglioRepository: PrenotazioniPastiDettaglioRepositoryImpl, + tessereRepository: TessereRepositoryImpl, + viewTessereAPIRepository: ViewTessereAPIRepositoryImpl, + dwhMovimentiRepository: DwhMovimentiRepositoryImpl ) { route("/api/annullaPrenotazioni") { authenticate("auth-jwt") { @@ -26,7 +34,7 @@ fun Route.annullaPrenotazioni( return@patch } - try{ + try { val prenotazione = viewPrenotazioniPastiRepository.prenotazioniPastiById(idPrenotazione.toLong()) val statoPrenotazione = prenotazione.stato @@ -54,27 +62,143 @@ fun Route.annullaPrenotazioni( val listaProdottiPrenotati = prenotazioniPastiDettaglioRepository.listaDettagliByIdPrenotazione(idPrenotazione.toLong()) - //aggiorna lo stato di ogni prodotto per annullare la prenotazione - listaProdottiPrenotati.forEach { el -> - val prodottoDaAggiornare = PrenotazioniPastiDettaglio( - el.id, - el.idPrenotazione, - el.idProdotto, - 3L //ANNULLATA + + val tessera = viewTessereAPIRepository.tesseraById(prenotazione.idTessera) + if (tessera == null) { + call.respond( + HttpStatusCode.BadRequest, + "Prenotazione non annullata: tessera collegata alla prenotazione non trovata" ) - prenotazioniPastiDettaglioRepository.update(prodottoDaAggiornare) + return@patch + } + + //recupero i dati di tessera e utente + val datiUtenteTessera = transaction { + val query = """ + SELECT u.cognome, u.nome, a.nome as azienda, cu.nome as categoria_utenti, f.nome as fascia + FROM tessere t + LEFT JOIN utenti u ON t.id_utente = u.id + LEFT JOIN categorie_utenti cu ON u.id_categoria = cu.id + LEFT JOIN aziende a ON cu.id_azienda = a.id + LEFT JOIN categorie_utenti_fasce cuf ON cuf.id_categoria_utenti = cu.id + LEFT JOIN fasce f ON cuf.id_fascia = f.id + WHERE t.id = ? + """.trimIndent() + + val connection = TransactionManager.current().connection + val preparedStatement = connection.prepareStatement(query, true) + preparedStatement[1] = tessera.id + + val rs = preparedStatement.executeQuery() + if (rs.next()) { + DatiUtenteTessera( + cognome = rs.getString("cognome"), + nome = rs.getString("nome"), + azienda = rs.getString("azienda"), + categoriaUtenti = rs.getString("categoria_utenti"), + fascia = rs.getString("fascia") + ) + } else null + } + + + if (datiUtenteTessera == null) { + call.respond( + HttpStatusCode.BadRequest, + "Prenotazione non annullata: dati utente tessera non trovati" + ) + return@patch + } + + //aggiorna lo stato di ogni prodotto per annullare la prenotazione + try { + listaProdottiPrenotati.forEach { el -> + val prodottoDaAggiornare = PrenotazioniPastiDettaglio( + el.id, + el.idPrenotazione, + el.idProdotto, + 3L //ANNULLATA + ) + prenotazioniPastiDettaglioRepository.update(prodottoDaAggiornare) + } + } catch (e: Exception) { + println("Annulamento prenotazione non completato. Errore durante l'update dei dettagli: ${e.message}") + call.respond(HttpStatusCode.InternalServerError, "Errore durante l'update dei dettagli: ${e.message}") + } + + //effettuare l'aggiornamento del saldo della tessera + val nuovoSaldo = tessera.saldo.plus(prenotazione.importoPagato) + + try { + tessereRepository.update( + Tessere( + tessera.id, + nuovoSaldo, + LocalDateTime.now().toKotlinLocalDateTime() + ) + ) + } catch (e: Exception) { + println("Annulamento prenotazione non completato. Errore durante l'update della tessera: ${e.message}") + call.respond(HttpStatusCode.InternalServerError, "Errore durante l'update della tessera: ${e.message}") + } + + + //effettuare l'inserimento del movimento di storno + try { + dwhMovimentiRepository.insert( + DwhMovimenti( + -1L, + tessera.id, + tessera.numero, + "Storno prenotazione pre pagata", + LocalDateTime.now().toKotlinLocalDateTime(), + prenotazione.id, + "App", + "0", + tessera.saldo, + prenotazione.importoPagato, + tessera.saldo + prenotazione.importoPagato, + tessera.punti.toLong(), + 0, + tessera.punti.toLong() + 0, + 0, + prenotazione.vassoio, + datiUtenteTessera.cognome, + datiUtenteTessera.nome, + tessera.codiceFiscale, + datiUtenteTessera.azienda, + datiUtenteTessera.categoriaUtenti, + datiUtenteTessera.fascia, + 3, //Storno + LocalDate.now().toKotlinLocalDate(), + "Standard", + 1 + ) + ) + } catch (e: Exception) { + println("Annulamento prenotazione non completato. Errore durante l'insert del movimento: ${e.message}") + call.respond(HttpStatusCode.InternalServerError, "Errore durante l'insert del movimento: ${e.message}") } call.respond(HttpStatusCode.OK, "Prenotazione $idPrenotazione annullata") - } - catch (e: IllegalArgumentException) { + } catch (e: IllegalArgumentException) { call.respond(HttpStatusCode.NotFound, "Prenotazione non trovata: ${e.message}") + } catch(e: Exception){ + println("Annulamento prenotazione non completato. Errore generico: ${e.message}") + call.respond(HttpStatusCode.InternalServerError, "Errore generico: ${e.message}") } - - } } } -} \ No newline at end of file +} + +@Serializable +data class DatiUtenteTessera( + val cognome: String, + val nome: String, + val azienda: String, + val categoriaUtenti: String, + val fascia: String +) \ No newline at end of file diff --git a/src/main/kotlin/eu/maiora/routes/Tessere.kt b/src/main/kotlin/eu/maiora/routes/Tessere.kt index 328ee63..a2eb2da 100644 --- a/src/main/kotlin/eu/maiora/routes/Tessere.kt +++ b/src/main/kotlin/eu/maiora/routes/Tessere.kt @@ -1,6 +1,6 @@ package eu.maiora.routes -import eu.maiora.model.TessereRepositoryImpl +import eu.maiora.model.ViewTessereAPIRepositoryImpl import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* @@ -8,7 +8,7 @@ import io.ktor.server.response.* import io.ktor.server.routing.* -fun Route.tessere(tessereRepository: TessereRepositoryImpl){ +fun Route.tessere(tessereRepository: ViewTessereAPIRepositoryImpl){ route("/api/tessere"){ authenticate("auth-jwt") { get("{cf}"){