@primocaredentgroup/shipping
v0.2.0
Published
Convex Component per la gestione logistica di spedizioni, consegne, vettori e tracking interno.
Readme
Shipping — Convex Component
Componente Convex per la gestione logistica di spedizioni, consegne, vettori e tracking interno a stati.
Progettato per essere condiviso tra PrimoUpCore (gestionale cliniche) e PrimoLabCore (gestionale laboratorio odontotecnico).
Obiettivo
Fornire un registro operativo logistico con:
- Gestione di mittenti e destinatari (cliniche, laboratori, soggetti esterni)
- Gestione vettori (corrieri API, corrieri manuali, padroncini interni)
- Creazione e tracciamento spedizioni con state machine esplicita
- Timeline eventi per ogni spedizione
- Allegati per spedizione
- Configurazione vettori preferiti per clinica/laboratorio
Non include: integrazione corrieri reali, tracking GPS, calcolo tariffe, generazione etichette, routing intelligente, notifiche.
Concetti di Dominio
| Concetto | Descrizione |
|---|---|
| LogisticParty | Mittente o destinatario: clinica, laboratorio o soggetto esterno. Supporta externalId opzionale per collegamento con anagrafiche esterne (PrimoUpCore / PrimoLabCore) |
| TransportProvider | Chi trasporta: corriere con API, corriere manuale, padroncino interno |
| Shipment | La spedizione, con stato, direzione, mittente, destinatario, vettore |
| ShipmentEvent | Evento nella timeline della spedizione (creazione, cambio stato, nota...) |
| ShipmentAttachment | File allegato alla spedizione (etichetta, documento, foto) |
| PreferredProviderConfig | Fino a 3 vettori preferiti per ogni clinica o laboratorio |
Direzioni Spedizione
outbound— spedizione in uscitainbound_expected— spedizione attesa in ingressointernal_transfer— trasferimento interno
Stati Spedizione (State Machine)
draft → ready → assigned → picked_up → in_transit → out_for_delivery → delivered
↘ failed ↘ delivered
↘ failed
Ogni stato può andare in → cancelled (tranne i terminali)
Stati terminali: delivered, failed, cancelledTipi Vettore
external_api— corriere con integrazione API (es. DHL)external_manual— corriere senza integrazione (es. BRT)internal_driver— padroncino interno/assunto
Struttura Progetto
shipping/
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── README.md
├── src/
│ ├── component/ # Backend Convex Component
│ │ ├── convex.config.ts # Definizione componente
│ │ ├── schema.ts # Schema tabelle (isolato)
│ │ ├── domain/
│ │ │ ├── enums.ts # Enum e validators condivisi
│ │ │ ├── stateMachine.ts # State machine transizioni
│ │ │ └── referenceCode.ts # Generazione codici SHP-XXXXXX
│ │ ├── logisticParties.ts # CRUD soggetti logistici
│ │ ├── transportProviders.ts # CRUD vettori
│ │ ├── shipments.ts # CRUD + logica spedizioni
│ │ ├── shipmentEvents.ts # Query eventi timeline
│ │ ├── shipmentAttachments.ts # CRUD allegati
│ │ └── preferredProviders.ts # Config vettori preferiti
│ ├── client/
│ │ └── index.ts # API wrapper per app consumatrici
│ └── test.ts # Helper per test con convex-test
├── example/
│ ├── convex/
│ │ ├── convex.config.ts # App config con componente installato
│ │ ├── shipping.ts # Re-export API pubblica
│ │ └── seed.ts # Dati demo
│ ├── src/
│ │ ├── main.tsx # Entry point React
│ │ ├── App.tsx # Router e layout
│ │ ├── App.css # Stili
│ │ ├── pages/
│ │ │ ├── Dashboard.tsx # Lista spedizioni con filtri
│ │ │ ├── CreateShipment.tsx # Form creazione spedizione
│ │ │ ├── ShipmentDetail.tsx # Dettaglio + timeline + azioni
│ │ │ ├── LogisticParties.tsx # Gestione soggetti
│ │ │ └── TransportProviders.tsx # Gestione vettori
│ │ └── components/
│ │ ├── StatusBadge.tsx # Badge stato/tipo
│ │ └── Timeline.tsx # Timeline eventi
│ ├── index.html
│ └── vite.config.tsCome Avviare
Prerequisiti
- Node.js 18+
- Account Convex (gratuito su convex.dev)
Installazione
Dalla root del repo (installa anche l’example tramite workspace npm):
cd shipping
npm installL’example dipende da @primocaredentgroup/shipping via file:.. così gli import restano uguali a un’installazione da npm.
Primo avvio (setup Convex)
Al primo avvio è necessario configurare il progetto Convex:
npx convex devIl CLI Convex chiederà di:
- Fare login (se non già autenticato)
- Creare un nuovo progetto Convex
Questo genera i file _generated/ e crea .env.local con le credenziali del deployment.
Sviluppo
Dopo il primo setup, avvia tutto con:
npm run devQuesto comando avvia in parallelo:
- Convex dev — backend con type-checking dei componenti
- Vite — frontend example app su
http://localhost:5173 - Build watcher — ricompila il componente ad ogni modifica
Seed Dati Demo
Dopo il primo deploy, esegui il seed per popolare i dati di esempio:
npx convex run seedQuesto crea:
- 4 soggetti logistici (Clinica Torino Centro, Clinica Rivoli, PrimoLab Torino, Studio Esterno Milano)
- 3 vettori (DHL Express, BRT Corriere, Padroncino Mario)
- 8 spedizioni in stati diversi (bozza, assegnata, in transito, attesa in ingresso, consegnata, fallita, annullata, trasferimento interno)
Demo UI
Apri http://localhost:5173 per vedere:
- Dashboard — lista spedizioni con filtri per stato e direzione
- Nuova Spedizione — form di creazione completo
- Dettaglio Spedizione — dati, timeline, azioni cambio stato, assegnazione vettore
- Soggetti Logistici — CRUD cliniche, laboratori, soggetti esterni
- Vettori — CRUD vettori con evidenza del tipo
Come Usare in un'App Esistente
1. Installa il componente
Se locale:
// convex/convex.config.ts
import { defineApp } from "convex/server";
import shipping from "../path/to/shipping/dist/component/convex.config.js";
const app = defineApp();
app.use(shipping);
export default app;2. Re-esporta l'API
// convex/shipping.ts
import { makeShippingAPI } from "@primocaredentgroup/shipping";
import { components } from "./_generated/api.js";
export const {
listShipments,
createShipment,
updateShipmentStatus,
// ... tutte le funzioni necessarie
} = makeShippingAPI(components.shipping);3. Usa dal client React
import { useQuery, useMutation } from "convex/react";
import { api } from "../convex/_generated/api";
function MyComponent() {
const shipments = useQuery(api.shipping.listShipments, { status: "in_transit" });
const create = useMutation(api.shipping.createShipment);
// ...
}Regole Funzionali
- Ogni nuova spedizione genera automaticamente un
ShipmentEventdi tipocreated - Ogni cambio stato genera un
ShipmentEventdi tipostatus_changed - Ogni assegnazione vettore genera un
ShipmentEventdi tipoassigned_provider - Le transizioni di stato invalide vengono rifiutate con errore esplicito
- Lo stato
assignedrichiede unproviderIdvalorizzato - Non è possibile assegnare un vettore disattivato (
isActive: false) providerId,senderId,recipientIdsono opzionaliPreferredProviderConfigaccetta massimo 3 provider- I codici di riferimento seguono il formato
SHP-XXXXXX(auto-incrementale)
Possibili Estensioni Future
- Adapter Pattern per corrieri: interfaccia comune per DHL, BRT, GLS con implementazioni specifiche
- Integrazione Sendcloud / ShippyPro: via adapter
- Tracking GPS padroncini: geolocalizzazione real-time
- Notifiche: webhook/email su cambio stato
- Calcolo tariffe: stima costi basata su peso, dimensioni, distanza
- Generazione etichette: PDF con barcode/QR
- Pianificazione giri: routing ottimizzato per padroncini
- Dashboard analytics: statistiche consegne, tempi medi, tassi di fallimento
- Multi-tenant: isolamento dati per clinica/laboratorio
- Webhook in ingresso: ricezione aggiornamenti da corrieri esterni
Pubblicazione su npm
Pacchetto scoped: @primocaredentgroup/shipping. Devi essere membro dell’organizzazione npm primocaredentgroup con permesso di publish.
publishConfig.access è impostato su public (pacchetto visibile e installabile senza login). Se invece deve essere solo per l’azienda (private), rimuovi publishConfig dal package.json root e usa npm publish con un piano npm che supporta pacchetti privati.
npm login
npm publishLo script prepublishOnly esegue typecheck e build prima della pubblicazione. Per un controllo senza pubblicare: npm pack --dry-run.
