CISA FotoGallery

Statistiche

Tot. visite contenuti : 919408
Home Articoli tecnici HowTo Gestione di un magazzino

Gestione di un magazzino

Prima di partire.

Maradona è il più grande calciatore di tutti i tempi.

Dopo questa verità indiscutibile, tutto il resto è passibile di discussione.

Mission:
il nostro software, che chiameremo Negotium (dal latino mancanza di ozio, in onore alla proverbiale efficienza e laboriosità partenopea), ci permetterà di tenere sotto controllo il flusso degli articoli in magazzino, la loro rotazione, la disponibilità e quindi il valore del magazzino, la gestione del sottoscorta, il saldo economico verso clienti e fornitori.

Piano di lavoro.
1. Premesse e convenzioni
2. Anagrafiche
3. Relazioni
4. Strutturazione query comparative
5. Realizzazione interfacce grafiche utente
6. Realizzazione report
7. Simulazione flusso logico

Premesse e convenzioni
Iniziamo col definire alcune convenzioni, tutte sicuramente discutibili, ma necessarie per potersi intendere col lettore.
Tutti i dati rimangono in linea, non verranno effettuate storicizzazioni. La ragione è quella di offrire all’utente tutto lo storico e non dati consolidati. Eventuali consolidamenti annuali saranno ricavati con delle query ad hoc.
Tutte le movimentazioni sono raccolte in un'unica tabella. Attraverso la tecnica delle subquery avremo la situazione aggiornata delle movimentazioni antagonista. Una scelta diversa avrebbe potuto indurci a creare una tabella per le “entrate” ed una per le “uscite”, in ogni caso altrettanto valida.
Non è questo u programma di contabilità ma di gestione. Questo significa che se dobbiamo archiviare un documento non ci riferiremo al numero di fattura (che comunque potremo registrare come notizia), ma al contatore che noi predisporremo. Il programma di contabilità potrà sovrapporsi a Negotium in un secondo momento.

Anagrafiche.
· Articoli di magazzino
· Movimentazioni
· Clienti e Fornitori

Cominciamo con la determinazione delle tabelle da utilizzare e delle relazioni intercorrenti.
(N.B. PK= "chiave primaria"; IDNA si intende campo indicizzato che non ammette duplicati; IDA indicizzato duplicati ammessi)

. . : ° tblArticolo ° : . .

Id Contatore PK
Codice Testo IDNA
Tipologia Intero Lungo IDA
Genere Intero Lungo IDA
Articolo Intero Lungo IDA
Um Testo IDA 10
Archivia Sì/No
Ci permetterà di archiviare un articolo (quando non più utile) e non eliminarlo, superando così il problema della conservazione delle movimentazioni storicizzate.

. . : ° tblMovimenti ° : . .
Id Contatore PK
Ricerca Numerico IDA
Qtà Numerico IDA
Prezzo Valuta IDA
IndicazioneDefinitiva Testo 255
Note Testo 255
Motivazioni Intero Lungo IDA

Può non coincidere con la motivazione del documento ma esserne una sottocategoria (Es. Motivazione Ricevuta: “Uscita”, all’interno del documento di vendita abbiamo alcune movimentazioni “vendita” o “conto visione” o “conto vendita” che potranno essere gestiti in maniera diversa.

Dataregistrazione Data/ora
Ci mettiamo un valore predefinito Date()
Rif_ricevuta Testo IDA
Iva Numerico

. . : ° tblRicevuta ° : . .
Id Contatore PK
DocumentoNum Testo IDA 50
Del Data/ora
Intestazione Testo IDA 50
Note Testo 255
Tipologia Testo IDA 10

Definisce il tipo di documento.
. . : ° tblPrezzi ° : . .
Id Contatore PK
Rif_codice Testo IDA 50
Prezzo Valuta
Listino Testo IDA 50
E’ il criterio per la determinazione del prezzo di vendita.

A ciascun cliente viene assegnato un listino e per ciascun articolo è possibile assegnare n listini

. . : ° tblMotivazioni ° : . .
Id Contatore PK
Motivazione Testo 5
Tipo Numerico (prec. Sing.) 50


Relazioni
Tabella Campo Tabella Campo
tblArticolo Codice 1-> M tblPrezzi Rif_codice
1->M tblMovimenti Ricerca

tblRicevuta DocumentoNum 1->M tblMovimenti rif_ricevuta


Query Comparative.
· Giacenza
· Saldo verso Clieni e Fornitori
· Statistiche di magazzino

Useremo la tecnica delle subquery per determinare i valori di ciascun campo sia della query Giacenza che di quella dei saldi

Giacenza

Dunque la query giacenza avrà bisogno di tutti gli articoli di magazzino e a fianco avere e movimentazioni.

In particolare avremo tutti i campi di articoli e quindi

Codice, tipologia, genere, articolo, um, archivia

e i campi calcolati
Acq Entrata
Ven Uscita
ResoAcq Entrata Reso effettuato verso i nostri fornitori
ResoVen Uscita Reso effettuato da nostri clienti
CaricoProduzione Entrata Acq effettuato da produzione interna. Prodotto Semilavorato
ScaricoProduzione Uscita Scarico materiali per produzione interna

ContoVisione UscitaTemp Merce uscita dalla disponibilità ma ancora in giacenza (perché non ancora venduta)
RitornoContoVisione EntrataTemp Partita di storno di merce di ritorno dal conto visione. A prescindere dalla motivazione (vendita o reso) verrà prodotta una partita di storno dell’uscita del conto visione.

Es. Io do 10pz in conto visione al cliente Mazza; questi mi vende 3 pz, me ne rende 4 e ne mantiene in conto visione 3pz. Dunque verrà prodotto un record per la vendita che movimenterà la giacenza, uno per il ritorno conto visione che non movimenta la giacenza ma solo il saldo articoli in conto visione e per differenza rimarranno 3 in conto visione.

Omg Uscita

Giacenza Campo calcolato tra tutti i campi Entrata e Uscita
GiacenzaContoVisione Campo calcolato tra tutti i campi EntrataTemp e UscitaTemp
Questa la query

Select codice, Tipologia, genere, Articolo, Um, archivia

(Select fctround(sum(qtà)) as Q from tblmovimenti where tblmovimenti.rif_codice = tblarticoli.codice and motivazione = ‘Acq’) as Acq,

(Select fctround(sum(qtà)) as Q from tblmovimenti where tblmovimenti.rif_codice = tblarticoli.codice and motivazione = ‘ven’) as ven,

(Select fctround(sum(qtà)) as Q from tblmovimenti where tblmovimenti.rif_codice = tblarticoli.codice and motivazione = ‘resoAcq’) as ResoAcq,

(Select fctround(sum(qtà)) as Q from tblmovimenti where tblmovimenti.rif_codice = tblarticoli.codice and motivazione = ‘ResoVen’) as resoVen

from tblArticolo

Saldo verso Clienti e Fornitori
Stessa logica altro giro di ruota per clienti e fornitori.
Da notare che lo stesso soggetto può ricoprire la duplice figura di cliente e fornitore, quindi non lascerei l’identificazione del tipo di saldo al soggetto ma cmq alla motivazione.

L’indicazione cliente e/o fornitore può essere un’indicazione di massima, assolutamente non vincolante. La lasciamo, p.e., per ordinare magari l’elenco quando facciamo una ricevuta.

Interfacce grafiche.
· Clienti e Fornitori
· Articoli
· Statistiche di magazzino

Approfondimenti

Come creare delle relazioni
Codice prodotto
Guardando alle esperienze degli altri si possono notare molti modi per creare un codice prodotto. Ognuno di loro ha pregi e difetti e sarebbe difficile sceglierne uno senza conoscere le esigenze di chi lo utilizzerà.

Andiamo perciò ad analizzare le varie possibilità e quali sono una parte dei vantaggi e degli svantaggi del loro utilizzo e come si posso ottenere.

Codice numerico incrementale

Nel caso ci trovassimo di fronte all’esigenza di aver un codice molto veloce e che non deve dirci molto (perché riportato dal resto dell’etichetta), noi possiamo utilizzare il codice numerico 1,2 etc magari formattato con gli zeri 00001.

Vantaggi

Hai un codice molto veloce, lo ottieni con una sola istruzione, non hai bisogno di una scanner laser (poiché i margini di errore sono davvero scarsi).

Svantaggi

In pratica non hai nessuna info dal codice stesso, sei cmq legato alla descrizione che deve seguire il codice stesso.

E’ consigliabile se

Il magazzino non prevede spostamenti ma si opera con i prodotti a vista.

Come si ottiene.

E’ sufficiente un dmax+1 e la formattazione del risultato

Format(Dmax(“tuocodice”,”tuatabella”)+1,”00000”)

Utilizzo codice Produttore
In molti settori merceologici ci sono già dei codici a barre stampati o attaccati sul prodotto stesso.

Vantaggi

Non si ha bisogno di alcuno strumento o anche solo il tempo di attaccare per tutti i prodotti il proprio codice a barre.

Svantaggi

Il codice del fornitore non ha alcun significato per noi ma è solo una stringa; posso avere dei codici duplicati.

E’ consigliabile se.

Il prodotto archiviato può essere solo quello e di quel produttore. Si intenda, facendo un magazzino di detersivi, il fustino LavaSciacq avrà un suo codice utilizzato dal produttore, e bisognerà riferirsi a quello anche se il fornitore tizio ne usa uno suo: infatti se viene utilizzato il codice del fornitore A e non quello del produttore, lo stesso fustino acquistato stavolta dal fornitore B dovrà avere un altro codice, altrimenti il codice del fornitore A non avrà allo stesso modo senso. In tale evenienza infatti si può usare un campo ‘codice fornitore’ che però finisce nella tabella della movimentazione non in quella dell’anagrafica dell’articolo.

Come si ottiene.

E’ superfluo dirlo, prendendo il codice sul prodotto

Codice parlato

E’ quello più interessante anche se forse più scomodo.

In pratica consiste nel codice fiscale del prodotto.
Si identificano i campi che verranno interessati e si assegneranno delle sigle ai prodotti. Dalla combinazione di queste sigle verrà fuori una stringa e si aggiunge il contatore.

(E' stato pubblicato un esempio e demo)

Vantaggi

Si ha un codice di facile lettura e con pochissima pratica verrà semplice abbinare le sigle all’indicazione del prodotto che intende.

Svantaggi

Ha bisogno di alcune righe di codice e la codifica dell’articolo è un po’ elaborata o almeno lenta.

E’ consigliabile se.

Si ha un magazzino molto esteso e non sotto occhio, o si lavora dove il pc è lontano. Si vuole decidere il itpo di informazioni che il codice deve restituirci.

Come si ottiene.

Creiamo le tabelle tblArticolo e tblArticolosigla

tblArticolo

mettiamoci i campi testo
codice
genere
contorno

ma potremmo usare qualsiasi altra cosa. (dite la verità, conoscendomi non vi sareste mai aspettato che parlassi di mangiare…)

La tabella tblArticoloSigla avrà invece i campi

Tipo
Rif_Articolo
Sigla

L’idea è: se si vuole codificare i prodotti
Pizza Pz
Pomodorino Fresco Pf

Pizza Pz
Salsiccia e Funghi SaF

Pizza Pz
Salsiccia e Peperoni SaPp

Saltimbocca Sb
Prosciutto crudo
Pcr

Abbiamo di fronte la maschera con l’anagrafica dell’articolo

Sull’evento NotInList di articolo ci mettiamo l’apertura di una form delle sigle filtrate per “tipo = ‘Genere’” della tabella tblArticoloSigla. Quindi noi avremo l’elenco di tute le sigle utilizzate per il campo genere – N.B. la stessa sigla potrebbe essere usata per Genere e Contorno, ma a seconda della posizione assumerà un significato diverso: si tenga sempre presente il concetto di codice fiscale, NTN come prime 3 lettere possono significare Newton, nel secondo trittico ad Antonio, in un eventuale trittico Non Tifoso Napoli e significa che non capisce di calcio ;-).

Stesso discorso quindi per il contorno.

Una volta avuta la stringa si aggiunge il contatore.

Suggerimenti.

Usiamo bene anche maiuscolo e minuscolo per definire cosa appartiene ad uno e cosa ad altro.

Per evitare di confondere PF Pomodoro e Funghi con Pf Pomodorino fresco, utilizziamo nel primo caso tutto maiuscolo e nel sendo maiuscolo-minuscolo: la logica sarebbe usiamo la prima lettra di un elemento n maiuscolo e le lettere che ci servono per spiegarlo meglio in minuscolo. Così differenzieremo bene un elemento con nome composto (pomodorino fresco) da una coppia di elementi (Patate e Funghi)

Altro suggerimento seppur non codificato ma visualizziamo sempre dei punti (p.e.) che dividono il genere dal contorno,

Pz.Pf.001


Subquery

La subquery è una soluzione molto performante e facile da implmentare per far riferimento da una qualsiasi tabella/query ad una serie di query correlate.

Sostituisce le query raggruppate collegata alla stessa tabella, le funzioni di aggregazione e spesso la query a campi incrociati.

Chiariamo il concetto.

Se io ho un elenco di articoli e volessi sapere la quantità venduta, prendendo la somma della quantità movimentata di quel codice e con la motivazione “ven” avrei tre strade:

Premesso che come relazioni in tutti casi ho una relazione 1 a molti tra i campi testo Codice e rif_codice

1. Predispongo una query raggruppata delle movimentazioni, mi creo una query con la tabella articoli e questa Qry_Venduto: nei join mostrerei tutti i record della tabella articoli e quelli della Qry_venduto che hanno lo stesso codice.

2. Creando una funzione di aggregazione, con dsum(“[qtà]”;”tblMovimentazioni”;”rif_codice = ‘” & codice & “’”), sicuramente poco performanti.

3. Query a campi incrociati

4. Usare le subquery.

Differenza importante però è che solo nel caso della funzione di aggregazione la query è aggiornabile, negli altri è di sola lettura.

Ma cosa sono le subquery. Come ho cercato di far arrivare è un’istruzione che relaziona una intra query di seleziona ad un campo di una tabella. Essa figura come campo della tabella a cui si relaziona e può restituire un solo valore (così come la funzione di aggregazione ma non la query raggruppata). Un solo valore significa che noi possiamo avere un solo valore per quel codice e non due record dello stesso codice: per avere due campi dalla stessa query dobbiamo prevedere i relativi due campi nella query in studio.

Come le otteniamo.

Se noi volessimo avere una query di selezione della tabella avremmo:

Select codice from articoli

E la nostra query ci restituirebbe tutti i nostri codici, se invece vogliamo inserirci anche le movimentazioni ci dobbiamo mettere

(Select
Notiamo che va inserito in una prentesi tonda. Questo perché l’intera istruzione verrà classificata con un alias.

Sum(qtà)
Sum perché come abbiamo già detto prima non possiamo pretendere più record dello stesso articolo. N.B. nel nostro caso abbiamo Sum ma andava bene Min Max e tutti gli altri tranne il raggruppamento

As Totale
Definiamo un piccolo alias di questa somma. Questo alias non verrà visualizzato e quindi non è significativo: infatti se avessimo diverse subquery potremmo usare per tutte lo stesso alis per la somma

From tblMovimentazioni

Where motivazione = “ven”
And rif_tblMovimentazioni.rif_codice = articoli.codice)

As Vendite

Funzioni
Fctround
E’ una funzione che ci permette di arrotondare in maniera commerciale le quantità sommate.
Risolve il problema della mancanza di arrotondamenti nelle somme di access.

Comprendiamola
Function fctRound(varNr As Variant, Optional varPl As Integer = 2) As Double

'by Konrad Marfurt + ("" by) Luke Chung + Karl Donaubauer
'esce se valore non numerico
If Not IsNumeric(varNr) Then Exit Function
fctRound = Fix("" & varNr * (10 ^ varPl) + Sgn(varNr) * 0.5) / (10 ^ varPl)
End Function

Function fctRound)
E’ una funzione e quindi richiamabile da qualsiasi maschera e utilizzabile anche con un valore di una query. Basterà quindi solo cingere con le parentesi la somma che ci interessa.

(varNr As Variant,
VarNr è una variabile di tipo sconosciuto, perciò è stato usato variant. Ma varNr è il valore da arrotondare che verrà gestito

Optional varPl As Integer = 2
In maniera opzionale può essere indicato anche quante cifre dopo la virgola arrotondare (N.B. diverso da visualizzare, infatti se visualizzassimo 3 cifre ma ne arrotondassimo due, la terza sarebbe inevitabilmente 0). In mancanza di diversa indicazione avremo un arrotondamento alla seconda cifra

As Double
Restituisce un campo a precisione doppia.

'by Konrad Marfurt + ("" by) Luke Chung + Karl Donaubauer
Gli autori

If Not IsNumeric(varNr) Then Exit Function
Se varNr no è numerico non verrà gestito e quindi finisce la funzione.

fctRound = Fix("" & varNr * (10 ^ varPl) + Sgn(varNr) * 0.5) / (10 ^ varPl)
Altrimenti ftround Moltiplica Varnr x 10 alla cifra di varPi () e taglia di netto con Fix i decimali (a).

A questa intera aggiunge più o meno dipende dal valore restituito da Sng(varnr) uno 0,5 (b).

Sgn restituisce 1 se il valore di varNr è maggiore di zero, 0 quando anche varNr è uguale a zero e -1 se è minore. Quindi avremo 0,5*1 se il varNr è maggiore zero(c).

E’ in buona sostanza un piccolo arrotondamento.

La cifra che viene fuori viene divisa per dieci levato al valore di varPI.

Ecco cosa subisce fctround(10,2369;2)

(a) 1023 +

(b) 10,24*1*0,5

(c) tutto diviso 1000

End Function
Fine della funzione

19.1.2007 UPDATE:
Nonostante alcuna esortazione... ho deciso di allegare un esempio all'articolo. Tale demo è in realtà molto scarno, ma riesce a dare l'idea del concetto mantenuto dell'articolo.
Tale esempio è soggetto cmq ad implementazioni su vostre sollecitazioni.

Commenti 

 
#2 Administrator 2010-11-30 18:19
Ciao
è un preparazione un ciclo di webcast dedicato a queste problematiche
 
 
#1 francesco 2010-11-30 18:07
Articolo interessante.
Non vedo pero' l'allegato