Sistemato magazzino
This commit is contained in:
@@ -4,6 +4,18 @@ CREATE TYPE "stato_materiale" AS ENUM ('proposto', 'approvato', 'rifiutato');
|
||||
-- CreateEnum
|
||||
CREATE TYPE "stato_magazzino_voce" AS ENUM ('buono', 'da_riparare', 'mancante');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "stato_lista" AS ENUM ('bozza', 'privato', 'gruppo', 'pubblico');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "stato_moderazione_lista" AS ENUM ('proposto', 'approvato', 'rifiutato');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "stato_categoria" AS ENUM ('confermata', 'da_approvare');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "tipo_notifica" AS ENUM ('MATERIALE_PROPOSTO', 'CATEGORIA_PROPOSTA', 'TIPO_EVENTO_PROPOSTO', 'LISTA_PROPOSTA');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "materiale" (
|
||||
"id" TEXT NOT NULL,
|
||||
@@ -21,35 +33,35 @@ CREATE TABLE "materiale" (
|
||||
CREATE TABLE "tipo_evento" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nome" TEXT NOT NULL,
|
||||
"stato" "stato_categoria" NOT NULL DEFAULT 'confermata',
|
||||
"creato_da_org_id" TEXT,
|
||||
"creato_il" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "tipo_evento_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "lista_modello" (
|
||||
CREATE TABLE "categoria" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nome" TEXT NOT NULL,
|
||||
"tipo_evento_id" TEXT NOT NULL,
|
||||
"pubblica" BOOLEAN NOT NULL DEFAULT true,
|
||||
"stato" "stato_categoria" NOT NULL DEFAULT 'confermata',
|
||||
"creato_da_org_id" TEXT,
|
||||
"creato_il" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "lista_modello_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "lista_modello_voce" (
|
||||
"lista_modello_id" TEXT NOT NULL,
|
||||
"materiale_id" TEXT NOT NULL,
|
||||
"quantita" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "lista_modello_voce_pkey" PRIMARY KEY ("lista_modello_id","materiale_id")
|
||||
CONSTRAINT "categoria_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "lista" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nome" TEXT NOT NULL,
|
||||
"org_id" TEXT NOT NULL,
|
||||
"org_id" TEXT,
|
||||
"creata_da_user_id" TEXT,
|
||||
"stato" "stato_lista" NOT NULL DEFAULT 'bozza',
|
||||
"creata_il" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"stato_moderazione" "stato_moderazione_lista",
|
||||
"tipo_evento_id" TEXT,
|
||||
"parent_id" TEXT,
|
||||
|
||||
CONSTRAINT "lista_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
@@ -63,6 +75,14 @@ CREATE TABLE "lista_voce" (
|
||||
CONSTRAINT "lista_voce_pkey" PRIMARY KEY ("lista_id","materiale_id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "lista_sotto_lista" (
|
||||
"lista_id" TEXT NOT NULL,
|
||||
"sotto_lista_id" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "lista_sotto_lista_pkey" PRIMARY KEY ("lista_id","sotto_lista_id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "magazzino_voce" (
|
||||
"id" TEXT NOT NULL,
|
||||
@@ -72,10 +92,22 @@ CREATE TABLE "magazzino_voce" (
|
||||
"stato" "stato_magazzino_voce" NOT NULL,
|
||||
"posizione" TEXT,
|
||||
"note" TEXT,
|
||||
"gruppo_id" TEXT,
|
||||
|
||||
CONSTRAINT "magazzino_voce_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "gruppo_magazzino" (
|
||||
"id" TEXT NOT NULL,
|
||||
"org_id" TEXT NOT NULL,
|
||||
"nome" TEXT NOT NULL,
|
||||
"parent_id" TEXT,
|
||||
"creato_il" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "gruppo_magazzino_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "evento" (
|
||||
"id" TEXT NOT NULL,
|
||||
@@ -97,14 +129,41 @@ CREATE TABLE "evento_check" (
|
||||
CONSTRAINT "evento_check_pkey" PRIMARY KEY ("evento_id","materiale_id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_modello" ADD CONSTRAINT "lista_modello_tipo_evento_id_fkey" FOREIGN KEY ("tipo_evento_id") REFERENCES "tipo_evento"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
-- CreateTable
|
||||
CREATE TABLE "notifica" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"tipo" "tipo_notifica" NOT NULL,
|
||||
"messaggio" TEXT NOT NULL,
|
||||
"link" TEXT,
|
||||
"letta" BOOLEAN NOT NULL DEFAULT false,
|
||||
"data_creazione" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "notifica_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "lista_stato_stato_moderazione_idx" ON "lista"("stato", "stato_moderazione");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "lista_tipo_evento_id_idx" ON "lista"("tipo_evento_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "lista_parent_id_idx" ON "lista"("parent_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "gruppo_magazzino_org_id_idx" ON "gruppo_magazzino"("org_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "gruppo_magazzino_parent_id_idx" ON "gruppo_magazzino"("parent_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "magazzino_voce_gruppo_id_idx" ON "magazzino_voce"("gruppo_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_modello_voce" ADD CONSTRAINT "lista_modello_voce_lista_modello_id_fkey" FOREIGN KEY ("lista_modello_id") REFERENCES "lista_modello"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "lista" ADD CONSTRAINT "lista_tipo_evento_id_fkey" FOREIGN KEY ("tipo_evento_id") REFERENCES "tipo_evento"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_modello_voce" ADD CONSTRAINT "lista_modello_voce_materiale_id_fkey" FOREIGN KEY ("materiale_id") REFERENCES "materiale"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "lista" ADD CONSTRAINT "lista_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "lista"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_voce" ADD CONSTRAINT "lista_voce_lista_id_fkey" FOREIGN KEY ("lista_id") REFERENCES "lista"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -112,9 +171,21 @@ ALTER TABLE "lista_voce" ADD CONSTRAINT "lista_voce_lista_id_fkey" FOREIGN KEY (
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_voce" ADD CONSTRAINT "lista_voce_materiale_id_fkey" FOREIGN KEY ("materiale_id") REFERENCES "materiale"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_sotto_lista" ADD CONSTRAINT "lista_sotto_lista_lista_id_fkey" FOREIGN KEY ("lista_id") REFERENCES "lista"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lista_sotto_lista" ADD CONSTRAINT "lista_sotto_lista_sotto_lista_id_fkey" FOREIGN KEY ("sotto_lista_id") REFERENCES "lista"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "magazzino_voce" ADD CONSTRAINT "magazzino_voce_materiale_id_fkey" FOREIGN KEY ("materiale_id") REFERENCES "materiale"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "magazzino_voce" ADD CONSTRAINT "magazzino_voce_gruppo_id_fkey" FOREIGN KEY ("gruppo_id") REFERENCES "gruppo_magazzino"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "gruppo_magazzino" ADD CONSTRAINT "gruppo_magazzino_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "gruppo_magazzino"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "evento" ADD CONSTRAINT "evento_lista_id_fkey" FOREIGN KEY ("lista_id") REFERENCES "lista"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
|
||||
@@ -23,6 +23,68 @@ enum StatoMagazzinoVoce {
|
||||
@@map("stato_magazzino_voce")
|
||||
}
|
||||
|
||||
enum StatoLista {
|
||||
bozza
|
||||
privato
|
||||
gruppo
|
||||
pubblico
|
||||
|
||||
@@map("stato_lista")
|
||||
}
|
||||
|
||||
enum StatoModerazioneLista {
|
||||
proposto
|
||||
approvato
|
||||
rifiutato
|
||||
|
||||
@@map("stato_moderazione_lista")
|
||||
}
|
||||
|
||||
enum StatoCategoria {
|
||||
confermata
|
||||
da_approvare
|
||||
|
||||
@@map("stato_categoria")
|
||||
}
|
||||
|
||||
enum TipoNotifica {
|
||||
MATERIALE_PROPOSTO
|
||||
CATEGORIA_PROPOSTA
|
||||
TIPO_EVENTO_PROPOSTO
|
||||
LISTA_PROPOSTA
|
||||
|
||||
@@map("tipo_notifica")
|
||||
}
|
||||
|
||||
// Coda di notifiche di moderazione (nuove proposte di materiale/categoria/tipo
|
||||
// evento/lista in attesa di revisione): visibile solo a chi ha ruolo 'moderatore',
|
||||
// non ci sono ancora notifiche personali nel dominio magazzino.
|
||||
model Notifica {
|
||||
id Int @id @default(autoincrement())
|
||||
tipo TipoNotifica
|
||||
messaggio String
|
||||
link String?
|
||||
letta Boolean @default(false)
|
||||
dataCreazione DateTime @default(now()) @map("data_creazione")
|
||||
|
||||
@@map("notifica")
|
||||
}
|
||||
|
||||
// Tassonomia delle categorie di materiale, gestita dal moderatore (CRUD diretto,
|
||||
// sempre creata "confermata") con un flusso di proposta aperto a qualsiasi org
|
||||
// autenticata (crea in "da_approvare", poi approvata/rifiutata dal moderatore).
|
||||
// Materiale.categoria resta per ora un campo stringa libero, non collegato a questa
|
||||
// tabella: introdurla come FK è un passo successivo, fuori scope qui.
|
||||
model Categoria {
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
stato StatoCategoria @default(confermata)
|
||||
creatoDaOrgId String? @map("creato_da_org_id")
|
||||
creatoIl DateTime @default(now()) @map("creato_il")
|
||||
|
||||
@@map("categoria")
|
||||
}
|
||||
|
||||
model Materiale {
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
@@ -32,56 +94,67 @@ model Materiale {
|
||||
propostoDaOrgId String @map("proposto_da_org_id")
|
||||
creatoIl DateTime @default(now()) @map("creato_il")
|
||||
|
||||
listaModelloVoci ListaModelloVoce[]
|
||||
listaVoci ListaVoce[]
|
||||
magazzinoVoci MagazzinoVoce[]
|
||||
eventoCheck EventoCheck[]
|
||||
listaVoci ListaVoce[]
|
||||
magazzinoVoci MagazzinoVoce[]
|
||||
eventoCheck EventoCheck[]
|
||||
|
||||
@@map("materiale")
|
||||
}
|
||||
|
||||
model TipoEvento {
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
// Stessa semantica/enum di Categoria.stato: un tipo evento creato dal moderatore
|
||||
// nasce 'confermata', uno proposto da un'organizzazione nasce 'da_approvare'.
|
||||
stato StatoCategoria @default(confermata)
|
||||
creatoDaOrgId String? @map("creato_da_org_id")
|
||||
creatoIl DateTime @default(now()) @map("creato_il")
|
||||
|
||||
listeModello ListaModello[]
|
||||
liste Lista[]
|
||||
|
||||
@@map("tipo_evento")
|
||||
}
|
||||
|
||||
model ListaModello {
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
tipoEventoId String @map("tipo_evento_id")
|
||||
pubblica Boolean @default(true)
|
||||
|
||||
tipoEvento TipoEvento @relation(fields: [tipoEventoId], references: [id])
|
||||
voci ListaModelloVoce[]
|
||||
|
||||
@@map("lista_modello")
|
||||
}
|
||||
|
||||
model ListaModelloVoce {
|
||||
listaModelloId String @map("lista_modello_id")
|
||||
materialeId String @map("materiale_id")
|
||||
quantita Int
|
||||
|
||||
listaModello ListaModello @relation(fields: [listaModelloId], references: [id])
|
||||
materiale Materiale @relation(fields: [materialeId], references: [id])
|
||||
|
||||
@@id([listaModelloId, materialeId])
|
||||
@@map("lista_modello_voce")
|
||||
}
|
||||
|
||||
model Lista {
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
orgId String @map("org_id")
|
||||
creataIl DateTime @default(now()) @map("creata_il")
|
||||
id String @id @default(uuid())
|
||||
nome String
|
||||
// Valorizzato solo per le liste in stato 'gruppo' (condivise con l'organizzazione):
|
||||
// le liste 'bozza'/'privato'/'pubblico' sono personali e non hanno alcuna org, anche
|
||||
// per un utente che ha un'organizzazione attiva sul token al momento della creazione.
|
||||
orgId String? @map("org_id")
|
||||
// Nullable perché le liste create prima di questo campo non hanno un autore noto;
|
||||
// da qui in poi è sempre valorizzato da req.auth.userId alla creazione.
|
||||
creataDaUserId String? @map("creata_da_user_id")
|
||||
stato StatoLista @default(bozza)
|
||||
creataIl DateTime @default(now()) @map("creata_il")
|
||||
|
||||
// Moderazione, ortogonale a `stato`: nullo per bozza/privato/gruppo, valorizzato
|
||||
// solo quando stato = pubblico (proposto/approvato/rifiutato, vedi liste.service.ts).
|
||||
statoModerazione StatoModerazioneLista? @map("stato_moderazione")
|
||||
|
||||
// Ex campo obbligatorio di ListaModello, ora opzionale su tutte le liste: serve solo
|
||||
// a filtrare il catalogo pubblico per tipo evento.
|
||||
tipoEventoId String? @map("tipo_evento_id")
|
||||
tipoEvento TipoEvento? @relation(fields: [tipoEventoId], references: [id])
|
||||
|
||||
// Lineage self-referenziato: da quale lista pubblica approvata è stata forkata questa
|
||||
// (fork = "usa come base"). Best-effort/storico: cancellare l'origine non deve
|
||||
// bloccare né trascinare i figli, quindi SetNull.
|
||||
parentId String? @map("parent_id")
|
||||
parent Lista? @relation("ListaParent", fields: [parentId], references: [id], onDelete: SetNull)
|
||||
figlie Lista[] @relation("ListaParent")
|
||||
|
||||
voci ListaVoce[]
|
||||
eventi Evento[]
|
||||
|
||||
// Sotto-liste agganciate a questa lista personale: un solo livello di nesting
|
||||
// (una sotto-lista non può avere a sua volta sotto-liste), validato in liste.service.ts.
|
||||
sottoListe ListaSottoLista[] @relation("SottoListePadre")
|
||||
usataComeSottoListaIn ListaSottoLista[] @relation("SottoListaFiglia")
|
||||
|
||||
@@index([stato, statoModerazione])
|
||||
@@index([tipoEventoId])
|
||||
@@index([parentId])
|
||||
@@map("lista")
|
||||
}
|
||||
|
||||
@@ -97,6 +170,35 @@ model ListaVoce {
|
||||
@@map("lista_voce")
|
||||
}
|
||||
|
||||
model ListaSottoLista {
|
||||
listaId String @map("lista_id")
|
||||
sottoListaId String @map("sotto_lista_id")
|
||||
|
||||
lista Lista @relation("SottoListePadre", fields: [listaId], references: [id])
|
||||
sottoLista Lista @relation("SottoListaFiglia", fields: [sottoListaId], references: [id])
|
||||
|
||||
@@id([listaId, sottoListaId])
|
||||
@@map("lista_sotto_lista")
|
||||
}
|
||||
|
||||
model GruppoMagazzino {
|
||||
id String @id @default(uuid())
|
||||
orgId String @map("org_id")
|
||||
nome String
|
||||
// Un solo livello di nesting (uno scaffale contiene kit, un kit non contiene
|
||||
// a sua volta altri gruppi), validato in gruppiMagazzino.service.ts.
|
||||
parentId String? @map("parent_id")
|
||||
creatoIl DateTime @default(now()) @map("creato_il")
|
||||
|
||||
parent GruppoMagazzino? @relation("GruppoMagazzinoParent", fields: [parentId], references: [id], onDelete: SetNull)
|
||||
figli GruppoMagazzino[] @relation("GruppoMagazzinoParent")
|
||||
voci MagazzinoVoce[]
|
||||
|
||||
@@index([orgId])
|
||||
@@index([parentId])
|
||||
@@map("gruppo_magazzino")
|
||||
}
|
||||
|
||||
model MagazzinoVoce {
|
||||
id String @id @default(uuid())
|
||||
orgId String @map("org_id")
|
||||
@@ -105,9 +207,14 @@ model MagazzinoVoce {
|
||||
stato StatoMagazzinoVoce
|
||||
posizione String?
|
||||
note String?
|
||||
// Nullo finché la giacenza non viene organizzata in un gruppo (scaffale/kit):
|
||||
// eliminare il gruppo non elimina la voce, la riporta solo tra le "non organizzate".
|
||||
gruppoId String? @map("gruppo_id")
|
||||
|
||||
materiale Materiale @relation(fields: [materialeId], references: [id])
|
||||
materiale Materiale @relation(fields: [materialeId], references: [id])
|
||||
gruppo GruppoMagazzino? @relation(fields: [gruppoId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([gruppoId])
|
||||
@@map("magazzino_voce")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
import { PrismaClient, StatoMateriale } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// Placeholder di orgId per il materiale di catalogo seedato manualmente (non riconducibile
|
||||
// a nessuna organizzazione reale), analogo a UTENTE_MODIFICA="MANUALE" nel seed di attivita-be.
|
||||
const ORG_SISTEMA = "SISTEMA";
|
||||
|
||||
async function main() {
|
||||
const materiali = [
|
||||
{ id: "materiale-corda", nome: "Corda", categoria: "Attrezzatura", unitaMisura: "pz" },
|
||||
{ id: "materiale-torcia", nome: "Torcia", categoria: "Attrezzatura", unitaMisura: "pz" },
|
||||
{
|
||||
id: "materiale-kit-primo-soccorso",
|
||||
nome: "Kit primo soccorso",
|
||||
categoria: "Sicurezza",
|
||||
unitaMisura: "kit",
|
||||
},
|
||||
{ id: "materiale-tenda", nome: "Tenda", categoria: "Campeggio", unitaMisura: "pz" },
|
||||
{
|
||||
id: "materiale-fornello-campo",
|
||||
nome: "Fornello da campo",
|
||||
categoria: "Campeggio",
|
||||
unitaMisura: "pz",
|
||||
},
|
||||
{
|
||||
id: "materiale-zaino",
|
||||
nome: "Zaino",
|
||||
categoria: "Equipaggiamento personale",
|
||||
unitaMisura: "pz",
|
||||
},
|
||||
{
|
||||
id: "materiale-sacco-a-pelo",
|
||||
nome: "Sacco a pelo",
|
||||
categoria: "Equipaggiamento personale",
|
||||
unitaMisura: "pz",
|
||||
},
|
||||
{
|
||||
id: "materiale-borraccia",
|
||||
nome: "Borraccia",
|
||||
categoria: "Equipaggiamento personale",
|
||||
unitaMisura: "pz",
|
||||
},
|
||||
{ id: "materiale-garze", nome: "Garze", categoria: "Sicurezza", unitaMisura: "pz" },
|
||||
{ id: "materiale-cerotti", nome: "Cerotti", categoria: "Sicurezza", unitaMisura: "pz" },
|
||||
{
|
||||
id: "materiale-disinfettante",
|
||||
nome: "Disinfettante",
|
||||
categoria: "Sicurezza",
|
||||
unitaMisura: "flacone",
|
||||
},
|
||||
];
|
||||
await Promise.all(
|
||||
materiali.map((materiale) =>
|
||||
prisma.materiale.upsert({
|
||||
where: { id: materiale.id },
|
||||
update: {
|
||||
...materiale,
|
||||
stato: StatoMateriale.approvato,
|
||||
propostoDaOrgId: ORG_SISTEMA,
|
||||
},
|
||||
create: {
|
||||
...materiale,
|
||||
stato: StatoMateriale.approvato,
|
||||
propostoDaOrgId: ORG_SISTEMA,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const tipiEvento = [
|
||||
{ id: "tipo-evento-uscita-giorno", nome: "Uscita di un giorno" },
|
||||
{ id: "tipo-evento-campo-estivo", nome: "Campo estivo" },
|
||||
{ id: "tipo-evento-riunione-settimanale", nome: "Riunione settimanale" },
|
||||
];
|
||||
await Promise.all(
|
||||
tipiEvento.map((tipoEvento) =>
|
||||
prisma.tipoEvento.upsert({
|
||||
where: { id: tipoEvento.id },
|
||||
update: { nome: tipoEvento.nome },
|
||||
create: tipoEvento,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Le ex "liste modello" sono ora liste unificate: pubbliche, già approvate dalla
|
||||
// moderazione, senza autore/org (scritte direttamente dal seed, come farebbe un
|
||||
// moderatore in bypass della coda di proposte).
|
||||
const listeModello = [
|
||||
{
|
||||
id: "lista-modello-uscita-giorno",
|
||||
nome: "Materiale base uscita giornaliera",
|
||||
tipoEventoId: "tipo-evento-uscita-giorno",
|
||||
},
|
||||
{
|
||||
id: "lista-modello-campo-estivo",
|
||||
nome: "Materiale base campo estivo",
|
||||
tipoEventoId: "tipo-evento-campo-estivo",
|
||||
},
|
||||
// Sotto-lista "foglia" (nessuna sotto-lista propria): allegata come sotto-lista sia a
|
||||
// "uscita di un giorno" sia a "campo estivo", al posto del vecchio materiale generico
|
||||
// "materiale-kit-primo-soccorso", per verificare il nesting a un livello.
|
||||
{
|
||||
id: "lista-modello-kit-primo-soccorso",
|
||||
nome: "Kit di pronto soccorso",
|
||||
tipoEventoId: "tipo-evento-uscita-giorno",
|
||||
},
|
||||
];
|
||||
for (const listaModello of listeModello) {
|
||||
await prisma.lista.upsert({
|
||||
where: { id: listaModello.id },
|
||||
update: { ...listaModello, stato: "pubblico", statoModerazione: "approvato" },
|
||||
create: {
|
||||
...listaModello,
|
||||
orgId: null,
|
||||
creataDaUserId: null,
|
||||
stato: "pubblico",
|
||||
statoModerazione: "approvato",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const listeModelloVoci = [
|
||||
{ listaId: "lista-modello-uscita-giorno", materialeId: "materiale-zaino", quantita: 1 },
|
||||
{
|
||||
listaId: "lista-modello-uscita-giorno",
|
||||
materialeId: "materiale-borraccia",
|
||||
quantita: 1,
|
||||
},
|
||||
{ listaId: "lista-modello-uscita-giorno", materialeId: "materiale-torcia", quantita: 1 },
|
||||
{ listaId: "lista-modello-campo-estivo", materialeId: "materiale-tenda", quantita: 1 },
|
||||
{
|
||||
listaId: "lista-modello-campo-estivo",
|
||||
materialeId: "materiale-sacco-a-pelo",
|
||||
quantita: 1,
|
||||
},
|
||||
{
|
||||
listaId: "lista-modello-campo-estivo",
|
||||
materialeId: "materiale-fornello-campo",
|
||||
quantita: 1,
|
||||
},
|
||||
{ listaId: "lista-modello-campo-estivo", materialeId: "materiale-corda", quantita: 2 },
|
||||
// Voci della sotto-lista "Kit di pronto soccorso" (foglia, allegata sotto a due liste diverse).
|
||||
{ listaId: "lista-modello-kit-primo-soccorso", materialeId: "materiale-garze", quantita: 3 },
|
||||
{
|
||||
listaId: "lista-modello-kit-primo-soccorso",
|
||||
materialeId: "materiale-cerotti",
|
||||
quantita: 10,
|
||||
},
|
||||
{
|
||||
listaId: "lista-modello-kit-primo-soccorso",
|
||||
materialeId: "materiale-disinfettante",
|
||||
quantita: 1,
|
||||
},
|
||||
];
|
||||
|
||||
// Rimuove il vecchio materiale generico "kit primo soccorso" piazzato direttamente nelle due
|
||||
// liste padre: da questo seed in poi il kit è la sotto-lista dedicata, non più una singola voce.
|
||||
await prisma.listaVoce.deleteMany({
|
||||
where: {
|
||||
materialeId: "materiale-kit-primo-soccorso",
|
||||
listaId: { in: ["lista-modello-uscita-giorno", "lista-modello-campo-estivo"] },
|
||||
},
|
||||
});
|
||||
|
||||
for (const voce of listeModelloVoci) {
|
||||
await prisma.listaVoce.upsert({
|
||||
where: {
|
||||
listaId_materialeId: {
|
||||
listaId: voce.listaId,
|
||||
materialeId: voce.materialeId,
|
||||
},
|
||||
},
|
||||
update: { quantita: voce.quantita },
|
||||
create: voce,
|
||||
});
|
||||
}
|
||||
|
||||
const sottoListe = [
|
||||
{ listaId: "lista-modello-uscita-giorno", sottoListaId: "lista-modello-kit-primo-soccorso" },
|
||||
{ listaId: "lista-modello-campo-estivo", sottoListaId: "lista-modello-kit-primo-soccorso" },
|
||||
];
|
||||
for (const sottoLista of sottoListe) {
|
||||
await prisma.listaSottoLista.upsert({
|
||||
where: {
|
||||
listaId_sottoListaId: {
|
||||
listaId: sottoLista.listaId,
|
||||
sottoListaId: sottoLista.sottoListaId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: sottoLista,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user