Gestisci distribuzione e submission in PunxFilm OS: crea piani distribuzione, gestisci submission ai festival, traccia risultati (accettazioni, premi, rifiuti), gestisci waiver code, monitora status pipeline. Usa questa skill quando l'utente parla di submission, distribuzione, piani, premiere, queue, waiver, candidature festival, risultati selezione, o gestione della pipeline di distribuzione dei cortometraggi.
Skill per la gestione completa della distribuzione film e submission ai festival in PunxFilm OS.
PunxFilm OS e' un'app Next.js 14 con Prisma + SQLite per la distribuzione di cortometraggi nei festival. Il database e' in prisma/dev.db alla root del progetto.
Submission (
id TEXT PRIMARY KEY,
filmId TEXT NOT NULL → Film.id,
festivalEditionId TEXT NOT NULL → FestivalEdition.id,
status TEXT (draft|submitted|accepted|rejected|withdrawn),
platform TEXT (filmfreeway|festhome|direct|other),
submittedAt DATETIME,
estimatedFee REAL,
feesPaid REAL,
waiverApplied BOOLEAN DEFAULT false,
waiverCode TEXT,
result TEXT (official_selection|competition|special_mention|award),
notificationDate DATETIME,
festivalEventDate DATETIME,
prizeAmount REAL,
notes TEXT
)
UNIQUE(filmId, festivalEditionId)
DistributionPlan (
id TEXT PRIMARY KEY,
filmId TEXT NOT NULL → Film.id,
premiereLevel TEXT (world|international|european|national),
status TEXT (draft|active|completed|archived),
materialChecklistComplete BOOLEAN DEFAULT false,
aiAnalysis TEXT (JSON),
createdAt, updatedAt
)
PlanEntry (
id TEXT PRIMARY KEY,
planId TEXT NOT NULL → DistributionPlan.id,
festivalMasterId TEXT NOT NULL → FestivalMaster.id,
festivalEditionId TEXT → FestivalEdition.id,
role TEXT (premiere|queue),
position INT (0=premiere, 1+=queue order),
status TEXT (pending|approved|rejected|subscribed),
priority TEXT (A|B|C),
matchScore INT (0-100),
matchReasoning TEXT,
waiverApplied BOOLEAN,
waiverCode TEXT,
estimatedFee REAL,
actualFee REAL,
submissionId TEXT → Submission.id
)
UNIQUE(planId, festivalMasterId)
DistributionContract (
id TEXT PRIMARY KEY,
filmId TEXT → Film.id,
distributorName TEXT,
clientName TEXT,
clientEmail TEXT,
startDate DATETIME,
endDate DATETIME,
status TEXT (active|expired|terminated),
notes TEXT
)
Workflow completo (4 step):
/api/ai/analyze-film per ottenere premiereLevel consigliato/api/ai/rank-festivals per rankare festival per premiere/api/ai/suggest-queue per festival post-premiere/api/distribution-plans con entriesimport sqlite3, json, uuid
from datetime import datetime
db_path = 'prisma/dev.db'
conn = sqlite3.connect(db_path)
c = conn.cursor()
# Verifica film
c.execute("SELECT id, titleOriginal, director, status FROM Film WHERE id = ?", (film_id,))
film = c.fetchone()
# Crea piano
plan_id = uuid.uuid4().hex[:25]
c.execute("""INSERT INTO DistributionPlan (id, filmId, premiereLevel, status, createdAt, updatedAt)
VALUES (?, ?, ?, 'draft', ?, ?)""",
(plan_id, film_id, premiere_level, datetime.now().isoformat(), datetime.now().isoformat()))
# Aggiungi premiere entry
entry_id = uuid.uuid4().hex[:25]
c.execute("""INSERT INTO PlanEntry (id, planId, festivalMasterId, role, position, status, priority, matchScore)
VALUES (?, ?, ?, 'premiere', 0, 'pending', 'A', ?)""",
(entry_id, plan_id, festival_master_id, match_score))
# Aggiungi queue entries
for i, fest in enumerate(queue_festivals):
entry_id = uuid.uuid4().hex[:25]
c.execute("""INSERT INTO PlanEntry (id, planId, festivalMasterId, role, position, status, priority, matchScore)
VALUES (?, ?, ?, 'queue', ?, 'pending', ?, ?)""",
(entry_id, plan_id, fest['id'], i+1, fest['priority'], fest['score']))
conn.commit()
conn.close()
Creare una submission:
sub_id = uuid.uuid4().hex[:25]
c.execute("""INSERT INTO Submission
(id, filmId, festivalEditionId, status, platform, estimatedFee, waiverApplied, waiverCode, createdAt, updatedAt)
VALUES (?, ?, ?, 'draft', ?, ?, ?, ?, ?, ?)""",
(sub_id, film_id, edition_id, platform, fee, waiver_applied, waiver_code, now, now))
Aggiornare status submission:
draft → submitted (RICHIEDE APPROVAZIONE — conferma invio effettivo)submitted → accepted o rejected (autonomo, basato su notifica)withdrawn (RICHIEDE APPROVAZIONE)Collegare submission a PlanEntry:
c.execute("UPDATE PlanEntry SET submissionId = ?, status = 'subscribed' WHERE id = ?",
(submission_id, plan_entry_id))
# Submission per film
c.execute("""SELECT s.*, fm.name as festivalName
FROM Submission s
JOIN FestivalEdition fe ON fe.id = s.festivalEditionId
JOIN FestivalMaster fm ON fm.id = fe.festivalMasterId
WHERE s.filmId = ? ORDER BY s.createdAt DESC""", (film_id,))
# Tasso accettazione
c.execute("""SELECT
COUNT(CASE WHEN status = 'accepted' THEN 1 END) as accepted,
COUNT(CASE WHEN status IN ('accepted','rejected') THEN 1 END) as decided,
COUNT(*) as total
FROM Submission""")
# Film senza piano
c.execute("""SELECT f.id, f.titleOriginal FROM Film f
LEFT JOIN DistributionPlan dp ON dp.filmId = f.id
WHERE dp.id IS NULL AND f.status IN ('active','in_distribuzione')""")
Quando arriva un risultato (accettazione, premio, rifiuto):
Submission.status e Submission.resultSubmission.prizeAmountPlanEntry.status di conseguenzaAUTONOME:
draftsubmitted a accepted/rejected su notificaRICHIEDONO APPROVAZIONE DI SIMONE:
draft a submittedwithdrawn)