Archiviare correttamente i dati di vendita e combinarli successivamente può portare alla creazione di un modello predittivo con un alto tasso di accuratezza. In questo e nei prossimi articoli analizzeremo la progettazione di un database per la registrazione delle vendite.
Tutti vivono vendendo qualcosa.
Robert Louis Stevenson
Nel mondo di oggi, vendita di prodotti è onnipresente. E i venditori che hanno accesso a strumenti solidi che sfruttano i dati storici per analizzare le tendenze e consentire a un'azienda di adattare le strategie di business di conseguenza hanno un vantaggio rispetto ai loro concorrenti. Ci sono molti parametri che possono influenzare i risultati dell'azienda:l'attuale situazione economica globale, l'ubicazione dei clienti, l'età, lo stato materiale e civile e la cronologia dei contatti precedenti o delle vendite ai clienti.
Inizieremo con un esempio molto semplice:un modello di database per le vendite in un caffetteria . Negli articoli successivi estenderemo il modello alla vendita di prodotti in altri rami.
Modello di vendita
In questo articolo analizzeremo solo una parte del modello che contiene dati di vendita con altre parti mancanti.
Abbiamo ancora collegamenti a tabelle mancanti e considereremo il modello come una scatola nera presupponendo che quanto segue sia corretto per la tabella sale
:
user_has_role_id
fare riferimento all'id inuser_has_role
(come presentato nel mio precedente articolo nella sezione "Componente temporale aggiunto") e memorizza le informazioni sull'utente che ha creato il record di vendita
Questo modello ci consente di creare record di vendita con più articoli. Ogni articolo è correlato a un prodotto del nostro catalogo. Il momento in cui generiamo una vendita può essere diverso dal momento in cui la vendita viene pagata. Ad esempio, per una tazza di caffè questi momenti differiranno nel giro di pochi minuti o ore. Se il nostro negozio vendeva dispositivi di telecomunicazione, la differenza può essere di pochi giorni, forse anche di mesi.
Tabelle
Diamo un'occhiata alla definizione della tabella e spieghiamo lo scopo e l'utilizzo degli attributi.
La tabella più importante nel modello è product
. Viene utilizzato per memorizzare i dettagli sui prodotti che offriremo ai nostri clienti. I prodotti vengono solitamente consegnati a un cliente e pagati una volta, di solito al momento della consegna. Inoltre, i prodotti sono generalmente oggetti fisici come automobili, telefoni, pacchetti di zucchero o tazze di caffè.
Parleremo della vendita di cose non fisiche (servizi) nei prossimi articoli.
Attributi nel product
tabella sono:
name
– il nome del prodotto nel sistemaprice_per_unit
– costo del prodotto per unità (es. 1 tazza di caffè costa 1,8 Euro, 1 macchina costa 17.500 Euro, 1 kg di riso costa 2 Euro)basic_unit
– unità base quando vendiamo un prodotto (es. pezzo, kg, litro)tax_percentage
– percentuale del prezzo_per_unità da addebitare come imposta. Dobbiamo presumere che la percentuale di imposta non sarebbe la stessa per tutti i prodottilimited
– questo campo è impostato su Vero se abbiamo una quantità limitata in magazzino e su Falso in caso contrario (ad esempio, possiamo ordinare qualsiasi quantità di cui abbiamo bisogno per il nostro negozio da un distributore)in_stock
– if limited=True questo attributo mostra quanti ne abbiamo a disposizione per vendereactive_for_sale
– se questo attributo è False allora non stiamo offrendo quel prodotto in vendita, altrimenti possiamo offrirlo ai clienti
Possiamo ottenere un elenco di prodotti che possiamo offrire ai clienti con la seguente query:
SELECT product.id, product.price_per_unit, product.basic_unit, product.limited, product.in_stock FROM product WHERE product.active_for_sale = True AND (product.limited = False OR (product.limited = True and product.in_stock > 0))
La tabella sale_status
è solo un semplice dizionario che contiene tutti gli stati che una vendita può avere nel sistema (es. "scontrino emesso", "scontrino pagato").
La tabella
sale
è la seconda tabella più importante in questo modello. Finora, questa tabella non ha alcun collegamento con i clienti a cui abbiamo venduto i prodotti perché, nel nostro esempio di caffetteria, non abbiamo bisogno di conoscere tali informazioni. Nella parte 2, il modello sarà esteso a tali casi. Gli attributi nella tabella e il loro significato sono:
time_created
– ora in cui è stato generato un record di vendita nel sistema (ad es. ora automatica in cui il record è stato creato quando abbiamo generato una vendita di caffè nella nostra caffetteria o un tempo aggiunto manualmente se lo desideriamo)time_paid
– generalmente possiamo aspettarci che alcune vendite vengano pagate entro pochi giorni o addirittura un mese dopo la creazione (ad esempio, se consegniamo software e creiamo una ricevuta possiamo aspettare fino a 90 giorni per essere pagati in alcuni paesi, se tutto va bene la legge)sale_amount
– importo originario destinato ad essere addebitato al clientesale_amount_paid
– importo effettivamente pagato dal cliente. Può essere nullo perché al momento della creazione di una ricevuta non sempre abbiamo queste informazionitax_amount
– somma di tutti gli importi delle tasse per gli articoli su quella ricevutasale_status_id
– riferimento asale_status
tabellauser_has_role_id
– riferimento all'utente e al suo ruolo nel momento in cui ha inserito la ricevuta nel sistema
Possiamo ottenere l'importo emesso e pagato (in base a time_created) entro un periodo di tempo con una query come questa:
SELECT SUM(sale.sale_amount) AS amount_issued, SUM(sale.sale_amount_paid) AS amount_paid FROM sale WHERE sale.time_created >= @start_time AND sale.time_created <= @end_time;
Per ottenere l'importo esatto pagato entro un periodo di tempo dobbiamo utilizzare una query come questa:
SELECT SUM(sale.sale_amount_paid) AS amount_paid FROM sale WHERE sale.time_paid >= @start_time AND sale.time_paid <= @end_time;
La query seguente calcolerà l'importo emesso e pagato entro un periodo di tempo con la data di emissione e la data di pagamento verificate separatamente:
SELECT SUM(CASE WHEN sale.time_created >= @start_time AND sale.time_created <= @end_time THEN sale.sale_amount END) AS amount_issued, SUM(CASE WHEN sale.time_paid >= @start_time AND sale.time_paid <= @end_time THEN sale.sale_amount_paid END) AS amount_paid FROM sale
In tutti gli esempi @start_time
e @end_time
sono variabili contenenti l'ora di inizio e l'ora di fine del periodo per il quale vogliamo controllare la SOMMA emessa e pagata.
La tabella sale_item
collega prodotti e vendite. Ovviamente, dobbiamo presumere che avremo più articoli su una ricevuta, quindi abbiamo bisogno che questa tabella abbia una relazione molti-a-molti.
Gli attributi e il loro significato sono:
quantity_sold
– quantità di prodotto che è stato venduto e che viene addebitato su quella vendita/scontrino (es. 3 caffè)price_per_unit
– stesso valore diproduct.price_per_unit
nel momento in cui è stata creata la vendita. Dobbiamo salvarlo perchéprice_per_unit
nelproduct
la tabella può cambiare nel tempoprice
– prodotto diquantity_sold
eprice_per_unit
; una piccola ridondanza che ci aiuta a evitare questo calcolo nelle query. In genere, la somma di tutti i prezzi degli articoli appartenenti alla stessa vendita dovrebbe essere uguale asale.sale_amount
tax_amount
– importo dell'imposta per quell'articolo al momento della ricezionesale_id
– ID della vendita a cui appartiene questo articoloproduct_id
– ID prodotto relativo a questo articolo
Ora potremmo facilmente fare un semplice rapporto, quanti prodotti/servizi abbiamo venduto nel periodo ea quale prezzo.
SELECT product.name, SUM(sale_item.quantity_sold) AS quantity, SUM(sale_item.price) AS price FROM sale, sale_item, product WHERE sale.id = sale_item.sale_id AND sale_item.product_id = product.id AND sale.time_created >= @start_time AND sale.time_created <= @end_time GROUP BY product.id