In controles waarin voorraad een materiële post vormt, is het belangrijk om te begrijpen hoe efficiënt de voorraad wordt beheerd. Want als producten lang op de plank blijven liggen, kan dat leiden tot incourantheid en afwaarderingen (en voor de klant onnodige opslagkosten). Met een eenvoudige analyse op de omloopsnelheid van voorraad krijgen we snel inzicht in welke artikelen veel worden verkocht en welke nauwelijks 'bewegen'. Deze informatie is handig bij het beoordelen van de waardering en het risicoprofiel van de voorraad.
Een andere aanvullende analyse is de analyse op leeftijd van de voorraad. In dat artikel staan we ook wat langer stil bij het verschil tussen deze twee analyses.
Wat hebben we nodig?
Voor deze analyse maken we gebruik van Python met pandas.
Mocht je onderstaand script zelf willen draaien, kun je deze uitproberen met het dummybestand met voorraadmutaties. Dit bestand bevat per product alle bewegingen (verkoop, inkoop, correcties en balansstanden). Je kunt het bestand hier downloaden:
Betrouwbaarheid
Uiteraard is het wel belangrijk dat je zeker weet dat de goederenmutaties betrouwbaar zijn. Dat wil zeggen dat je volledig bent en de juiste gegevens gebruikt worden. Daarvoor kun je eerst een goederenbeweging opstellen.
Stap 1: Verkoopvolume bepalen
Laten we dan echt aan de slag gaan. Allereerst selecteren we alleen de verkopen ('MutationType = Sales') en berekenen hoeveel er per product verkocht is:
import pandas as pd
# Inladen van de voorraadmutaties
df = pd.read_csv("dummy_stock_movements.csv", sep="|")
df['Date'] = pd.to_datetime(df['Date'])
sales = df[df['MutationType'] == 'Sales']
sales_summary = sales.groupby(['ItemID', 'ItemName'])['Quantity'].sum().reset_index(name='TotalSales')
Stap 2: Gemiddelde voorraad bepalen
We pakken de 'Balance Begin' en 'Balance End' waardes, en nemen het gemiddelde als benadering van de gemiddelde voorraadstand. Zo weten we over een jaar hoeveel de voorraad gemiddeld geweest moet zijn. In dit geval hebben we enkel de begin en eindbalans over het boekjaar. Mocht je de balans per dag hebben, dan is het betrouwbaarder om het gemiddelde daarvan te pakken.
balance = df[df['MutationType'].isin(['Balance Begin', 'Balance End'])]
avg_stock = balance.groupby(['ItemID', 'ItemName'])['Quantity'].mean().reset_index(name='AverageInventory')
Stap 3: Bereken de omloopsnelheid
Nu voegen we de datasets samen en berekenen de rotatie:
rotation = pd.merge(sales_summary, avg_stock, on=['ItemID', 'ItemName'], how='inner')
rotation['Omloopsnelheid'] = rotation['TotalSales'] / rotation['AverageInventory']
Voorbeeldresultaten
Je kunt de resultaten sorteren en bekijken:
rotation.sort_values(by='Omloopsnelheid', ascending=True, inplace=True)
print(rotation)
Product | Sales | Avg. Inventory | Omloopsnelheid |
---|---|---|---|
Ultra-High Performance Gaming Laptop | 44 | 379.5 | 0.12 |
Smart Home Security Camera | 516 | 391.5 | 1.32 |
24-Port Gigabit Ethernet Switch | 508 | 345.0 | 1.47 |
High-Speed 1TB SSD | 744 | 206.5 | 3.60 |
Multi-Port USB-C Docking Station | 434 | 110.0 | 3.95 |
Resultaten interpreteren
Een lage omloopsnelheid (bijv. < 1) betekent dat het product minder dan eens per periode (bijv. jaar) is omgezet. Dat kan duiden op:
- incourante voorraad
- overbodige inkoop
Een hoge omloopsnelheid (bijv. > 5) betekent snelle doorloop en efficiënte inzet van kapitaal.
In het geval van de dummy data zien we dat de laptops een erg lage rotatie hebben. Gedurende het jaar is er op verschillende momenten nieuw ingekocht, terwijl er maar 44 laptops zijn verkocht.
Vervolg
In het geval van de laptops, zijn er aan het eind van het jaar wel verkopen geweest. Dat betekent dat er nog wel vraag naar deze artikelen is. Je zou ook kunnen kijken of er uberhaupt verkopen plaats gevonden hebben of dat de voorraad 'dood' is.
Conclusie
Met deze simpele analyse zie je snel welke producten doorstromen en waar mogelijk risico’s of kansen liggen. Zeker bij bedrijven met veel artikelen is dit een waardevolle controle bij de jaarrekeningcontrole.