gestione struttura lista prodotti

aggiunta gestione quantita negli endpoint legati alle prenotazioni
gestione eccezione se id prenotazione da annullare non esiste
This commit is contained in:
Francesco Di Sciascio 2025-08-20 16:31:48 +02:00
parent 52b8936bfe
commit a5a154c7bf
9 changed files with 150 additions and 108 deletions

View File

@ -3,8 +3,6 @@ package eu.maiora.db
import eu.maiora.model.*
import kotlinx.coroutines.Dispatchers
import kotlinx.datetime.toKotlinLocalDateTime
import kotlinx.datetime.toKotlinLocalDate
import org.jetbrains.exposed.dao.*
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IdTable
@ -154,6 +152,8 @@ object ViewPrenotazioniPastiTable : IdTable<Long>("view_prenotazioni_pasti"){
val puntoDistribuzione = varchar("punto_distribuzione", 255)
val puntoCassa = varchar("punto_cassa", 255)
val modalita = varchar("modalita", 255)
val idProdotto = long("id_prodotto")
val prodotto = varchar("prodotto", 255)
}
@ -300,6 +300,8 @@ class ViewPrenotazioniPastiDao(id: EntityID<Long>) :LongEntity(id){
val puntoDistribuzione by ViewPrenotazioniPastiTable.puntoDistribuzione
val puntoCassa by ViewPrenotazioniPastiTable.puntoCassa
val modalita by ViewPrenotazioniPastiTable.modalita
val idProdotto by ViewPrenotazioniPastiTable.idProdotto
val prodotto by ViewPrenotazioniPastiTable.prodotto
}
@ -445,7 +447,7 @@ fun prenotazioniPastiDettaglioDaoToModel(dao: PrenotazioniPastiDettaglioDao) : P
)
}
fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao) : ViewPrenotazioniPasti{
/*fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao) : ViewPrenotazioniPasti{
val formatterGiorno = DateTimeFormatter.ofPattern("ddMMyyyy")
val formatterDataInizio = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm")
val formatterDataFine = DateTimeFormatter.ofPattern("ddMMyyyy HH:mm")
@ -475,6 +477,38 @@ fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao) : ViewPrenota
dao.modalita,
null
)
}*/
fun viewPrenotazioniPastiDaoToModel(dao: ViewPrenotazioniPastiDao, listaProdotti: List<ListaProdottiElement>? = null) : 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,
listaProdotti
)
}

View File

@ -0,0 +1,6 @@
package eu.maiora.model
import kotlinx.serialization.Serializable
@Serializable
data class ListaProdottiElement (val id: Long, val nome: String? = null, val quantita: Int)

View File

@ -16,6 +16,7 @@ data class Prenotazioni(
val idVassoio : Long,
val idStato : Long? = null,
val stato : String? = null,
val listaProdotti : List<ProdottiPrenotabili>? = null,
//val listaProdotti : List<ProdottiPrenotabili>? = null,
val listaProdotti: List<ListaProdottiElement>? = null,
val importoPagato : Double
)

View File

@ -7,5 +7,7 @@ data class PrenotazioniPastiDettaglio(
val id: Long? = null,
val idPrenotazione : Long,
val idProdotto : Long,
val idStato : Long
val idStato : Long,
val quantita : Int? = null,
val prodotto : String? = null
)

View File

@ -20,6 +20,6 @@ data class ViewPrenotazioniPasti(
val puntoDistribuzione: String,
val puntoCassa: String,
val modalita: String,
var listaProdotti: List<PrenotazioniPastiDettaglio>? = null
var listaProdotti: List<ListaProdottiElement>? = null
)

View File

@ -2,15 +2,19 @@ package eu.maiora.model
import eu.maiora.db.*
import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.insertAndGetId
class ViewPrenotazioniPastiRepositoryImpl : ViewPrenotazioniPastiRepository {
override suspend fun prenotazioniPastiById(id : Long): ViewPrenotazioniPasti = suspendTransaction {
// Cerca la prenotazione
ViewPrenotazioniPastiDao.find { ViewPrenotazioniPastiTable.idPrenotazione eq id }
.first() //prendo solo il primo record, dato che ci sono tanti record quanti prodotti prenotati
.let { viewPrenotazioniPastiDaoToModel(it) } // Converte il DAO in un oggetto ViewPrenotazioniPasti
val prenotazione = ViewPrenotazioniPastiDao.find { ViewPrenotazioniPastiTable.idPrenotazione eq id }
.firstOrNull() //prendo solo il primo record, dato che ci sono tanti record quanti prodotti prenotati
if (prenotazione == null) {
throw IllegalArgumentException("Prenotazione con ID $id non trovata")
}
viewPrenotazioniPastiDaoToModel(prenotazione, null)
}
override suspend fun prenotazioniPastiByIdTessera(idTessera : Long, limit : Long, offset : Long, order : String): List<ViewPrenotazioniPasti> = suspendTransaction {
@ -20,20 +24,41 @@ class ViewPrenotazioniPastiRepositoryImpl : ViewPrenotazioniPastiRepository {
else -> SortOrder.DESC // Default a DESC in caso di valore invalido
}
// Cerca la lista di prenotazioni
ViewPrenotazioniPastiDao.find { ViewPrenotazioniPastiTable.idTessera eq idTessera }
val prenotazioniRaw = ViewPrenotazioniPastiDao
.find { ViewPrenotazioniPastiTable.idTessera eq idTessera }
.orderBy(ViewPrenotazioniPastiTable.giorno to sortOrder, ViewPrenotazioniPastiTable.id to sortOrder)
.limit(limit.toInt())
.offset(offset)
.toList() // Restituisce la lista delle prenotazioni
.map { viewPrenotazioniPastiDaoToModel(it) } // Converte il DAO in un oggetto Movimenti
.toList()
//raggruppo i record per idPrenotazione e, successivamente, per idProdotto per poter calcolare le quantita
val listaPrenotazioniPasti = prenotazioniRaw
.groupBy { it.idPrenotazione }
.map { (_, dettagliPrenotazione) ->
val primaRiga = dettagliPrenotazione.first() //la prima riga la uso per leggere i dati della prenotazione
val prodottiRaggruppati = dettagliPrenotazione
.groupBy { it.idProdotto }
.map { (idProdotto, prodotti) ->
ListaProdottiElement(
id = idProdotto,
nome = prodotti.first().prodotto,
quantita = prodotti.size
)
}
viewPrenotazioniPastiDaoToModel(primaRiga, prodottiRaggruppati)
}
listaPrenotazioniPasti
}
override suspend fun countPrenotazioniPastiByIdTessera(idTessera : Long): Int = suspendTransaction {
// Conta il numero totale di prenotazioni della tessera
ViewPrenotazioniPastiDao.find { ViewPrenotazioniPastiTable.idTessera eq idTessera }
.toList() // Restituisce la lista delle prenotazioni
.count()
ViewPrenotazioniPastiDao
.find { ViewPrenotazioniPastiTable.idTessera eq idTessera }
.toList()
.map { it.idPrenotazione } // Estrai solo gli ID delle prenotazioni
.distinct() // Rimuovi duplicati
.count() // Conta le prenotazioni uniche
}
}

View File

@ -26,6 +26,7 @@ fun Route.annullaPrenotazioni(
return@patch
}
try{
val prenotazione = viewPrenotazioniPastiRepository.prenotazioniPastiById(idPrenotazione.toLong())
val statoPrenotazione = prenotazione.stato
@ -65,6 +66,11 @@ fun Route.annullaPrenotazioni(
}
call.respond(HttpStatusCode.OK, "Prenotazione $idPrenotazione annullata")
}
catch (e: IllegalArgumentException) {
call.respond(HttpStatusCode.NotFound, "Prenotazione non trovata: ${e.message}")
}
}

View File

@ -44,11 +44,6 @@ fun Route.prenotazioni(prenotazioniPastiRepository: PrenotazioniPastiRepository,
offset.toLong(),
order)
listaPrenotazioniPasti.forEach{ el ->
el.listaProdotti =
prenotazioniPastiDettaglioRepository.listaDettagliByIdPrenotazione(el.id)
}
call.respond(ListaPrenotazioni(totalRecords, listaPrenotazioniPasti))
}
@ -68,6 +63,15 @@ fun Route.prenotazioni(prenotazioniPastiRepository: PrenotazioniPastiRepository,
return@post
}
prenotazioneRequest.listaProdotti.forEach { prodotto ->
prodotto.quantita
?: throw IllegalArgumentException("Quantita non specificata per il prodotto con ID ${prodotto.id}")
if (prodotto.quantita < 1) {
throw IllegalArgumentException("Quantita non valida (${prodotto.quantita}) per il prodotto con ID ${prodotto.id}")
}
}
val prenotazionePasto = PrenotazioniPasti(
-1,
@ -83,15 +87,19 @@ fun Route.prenotazioni(prenotazioniPastiRepository: PrenotazioniPastiRepository,
val prenotazioneInserita = prenotazioniPastiRepository.insert(prenotazionePasto)
//per ogni prodotto, inserisci il dettaglio della prenotazione
prenotazioneRequest.listaProdotti?.forEach { el ->
prenotazioneRequest.listaProdotti.forEach { prodotto ->
repeat(prodotto.quantita!!) {
val dettaglioPrenotazione = PrenotazioniPastiDettaglio(
-1,
prenotazioneInserita.id,
el.id,
prodotto.id,
0L
)
listaDettagliInseriti.add(prenotazioniPastiDettaglioRepository.insert(dettaglioPrenotazione))
listaDettagliInseriti.add(
prenotazioniPastiDettaglioRepository.insert(dettaglioPrenotazione)
)
}
}
@ -117,7 +125,7 @@ fun Route.prenotazioni(prenotazioniPastiRepository: PrenotazioniPastiRepository,
catch (e: Exception){
call.respond(
HttpStatusCode.BadRequest,
"Errore nel processare la richiesta: ${e.cause}"
"Errore nel processare la richiesta: ${e.message}"
)
}
}

View File

@ -19,7 +19,6 @@ fun Route.verificaVassoio(selezionaComposizioneRepository: SelezionaComposizione
try {
val dati = call.receive<DatiVassoio>()
//val idsConcatenati = dati.listaProdotti.joinToString(separator = "|") { it.id.toString() }
val idsConcatenati = dati.listaProdotti
.flatMap { prodotto -> List(prodotto.quantita) { prodotto.id } }
.joinToString(separator = "|") { it.toString() }
@ -35,43 +34,6 @@ fun Route.verificaVassoio(selezionaComposizioneRepository: SelezionaComposizione
call.respond(HttpStatusCode.BadRequest, "Body non valido")
}
/*val idTessera = call.parameters["idTessera"]
val idVassoio = call.parameters["idVassoio"]
val data = call.parameters["data"]
if (idTessera == null) {
call.respondText("ID tessera non valido", status = HttpStatusCode.BadRequest)
return@get
}
if (idVassoio == null) {
call.respondText("ID vassoio non valido", status = HttpStatusCode.BadRequest)
return@get
}
if (data == null) {
call.respondText("data non valida", status = HttpStatusCode.BadRequest)
return@get
}
// Cerca la tessera per codice fiscale
val valorePasto = valorePastiRepository.valorePastoByTessVassData(idTessera, idVassoio, data)
val prezzo = valorePasto.split("#").get(0)
val punti = valorePasto.split("#").get(1)
if(prezzo == "-1" && punti == "-1")
call.respondText("Prezzo e punti non trovati", status = HttpStatusCode.NotFound)
call.respond( ValorePasti(idTessera.toLong(),
idVassoio.toLong(), data,
prezzo.replace(',', '.').toDouble(),
punti.toInt()))*/
}
}
@ -79,7 +41,5 @@ fun Route.verificaVassoio(selezionaComposizioneRepository: SelezionaComposizione
}
@Serializable
data class DatiVassoio (val idUtente : Long, val listaProdotti: List<Prodotti>)
data class DatiVassoio (val idUtente : Long, val listaProdotti: List<ListaProdottiElement>)
@Serializable
data class Prodotti (val id: Long, val quantita: Int)