Logo
Afbeelding

Simpele controles op leveranciers

Geschreven door The Audit Analytics | 6 minuten

Ben je benieuwd hoe je snel en eenvoudig meer inzicht krijgt in de leveranciers en facturen? Met een paar regels Python-code kun je al heel wat opvallende patronen opsporen. In dit artikel laten we je zien hoe je belangrijke vragen beantwoordt - van welke leveranciers de meeste kosten zijn tot hoe je rare pieken in facturen kunt herkennen.

Analyse leveranciers

Allereerst, wat heb je nodig? We gaan gebruik maken van python en maken daarbij enkel gebruik van het externe package pandas. Als je dat nog niet eerder gedaan hebt, kun je pandas installeren met het volgende commando:

pip install pandas

Daarnaast werken we met dummy-data. Dat is natuurlijk erg makkelijk, want die kunnen we gemakkelijk tweaken. Toch denk ik dat de velden die we gebruiken niet heel ongebruikelijk zijn. Om het zo realistisch mogelijk te maken, zullen we beginnen met twee bestanden:

Deze zullen we vervolgens aan elkaar moeten koppelen. Dat doen we als volgt:

# Dataset inladen
invoices = pd.read_csv("dummy_crediteuren_facturen_data.csv", parse_dates=["invoice_date"])
vendors = pd.read_csv("dummy_leveranciers_stamdata.csv", parse_dates=["created_on"])

# Samenvoegen van de bestanden.
# Dit doen we door alle facturen (df) te nemen en op basis van supplier_id
# de stamgegevens aan de facturen te koppelen. 

df = df.merge(stamdata, on="supplier_id", how="left")

# Toon de eerste paar regels van de nieuwe dataset:
display(df.head())

1. Identificeren welke leveranciers het grootste deel van de uitgaven voor hun rekening nemen

Een veelvoorkomende analyse is het bepalen welke leveranciers de grootste uitgaven genereren. Zo kun je bijvoorbeeld ontdekken of 20% van de leveranciers verantwoordelijk is voor 80% van de kosten.

Stappen:

  1. Sommeer InvoiceAmount per leverancier.

  2. Sorteer de resultaten aflopend op totaal bedrag.

  3. Bepaal eventueel een cumulatief percentage om de “top X%” te bepalen.

python

# Sommeer de factuurbedragen per leverancier 
spend_per_vendor = invoices.groupby('VendorID')['InvoiceAmount'].sum().reset_index() 

# Sorteer aflopend op uitgaven 
spend_per_vendor = spend_per_vendor.sort_values(by='InvoiceAmount', ascending=False) 

# Voeg de leveranciersnaam (VendorName) toe aan het DataFrame 
spend_per_vendor = spend_per_vendor.merge(vendors[['VendorID', 'VendorName']], on='VendorID', how='left') 

# Bereken cumulatief percentage 
total_spend = spend_per_vendor['InvoiceAmount'].sum() spend_per_vendor['CumulativePercent'] = ( spend_per_vendor['InvoiceAmount'].cumsum() / total_spend * 100 ) 

print("Uitgaven per leverancier (aflopend):") 
print(spend_per_vendor)`

Interpretatie:
Je ziet snel welke leveranciers het grootste deel van de kosten voor hun rekening nemen. Zo kun je bepalen waar de grootste risico’s of kansen voor kostenbesparing liggen.

2. Eerste facturen nieuwe leveranciers

Het kan interessant zijn om te kijken naar leveranciers die nog niet lang in het systeem staan (bijvoorbeeld de afgelopen X maanden zijn aangemaakt) en te analyseren hoe snel en hoe vaak ze factureren.

Stappen:

  1. Definieer wat “nieuw” betekent. In dit voorbeeld zeggen we: een leverancier is nieuw als de CreationDate minder dan 90 dagen geleden is.

  2. Koppel facturen aan stamgegevens.

  3. Filter de facturen van deze nieuwe leveranciers en bekijk frequentie en totaalbedrag.

# Bepaal huidige datum voor de analyse
today = datetime(2023, 6, 15) 

# Voeg 'nieuw' label toe aan leveranciers (minder dan 90 dagen geleden) 
vendors['IsNew'] = vendors['CreationDate'].apply(lambda x: (today - x).days < 90) 

# Koppel factuurgegevens aan de vendorgegevens 
invoice_details = invoices.merge(vendors, on='VendorID', how='left') 

# Filter op nieuwe leveranciers 
new_vendors_invoices = invoice_details[invoice_details['IsNew']] 

# Frequentie en totale omvang per nieuwe leverancier 
analysis_new_vendors = new_vendors_invoices.groupby('VendorName').agg({ 'InvoiceID': 'count', 'InvoiceAmount': 'sum' }).rename(columns={'InvoiceID': 'InvoiceCount'}) 

print("Betalingen aan nieuwe leveranciers (<90 dagen in systeem):") 
print(analysis_new_vendors)

Interpretatie:
Nu zie je hoe vaak (en met welk bedrag) je nieuwe leveranciers betaald hebt. Op basis van deze informatie kun je risicovolle scenario’s herkennen, zoals een nieuwe leverancier die direct een hoog factuurtotaal declareert.

3. Leveranciers die veel facturen of hoge bedragen declareren in korte tijd

Om fraude of ongebruikelijke patronen te ontdekken, kun je per leverancier kijken hoe de facturen zich in de tijd opstapelen.

Stappen:

  1. Koppel de factuurgegevens aan de stamgegevens van de crediteuren.

  2. Groepeer per leverancier en een vaste periode (bijv. per maand of per week).

  3. Tel het aantal facturen en/of sommeer de bedragen in die periode.

  4. Zoek abnormale uitschieters (bijv. plotselinge toename).

# Voeg maandinformatie toe voor grouping 
invoice_details['InvoiceMonth'] = invoice_details['InvoiceDate'].dt.to_period('M') 

# Groepeer per leverancier en per maand 
monthly_stats = invoice_details.groupby(['VendorID', 'InvoiceMonth']).agg({ 'InvoiceID': 'count', 'InvoiceAmount': 'sum' }).reset_index() 

# Voorbeeld: markeer leveranciers die in een maand boven een bepaalde drempel zitten 
threshold_amount = 10000 # arbitraire drempel, afhankelijk van je situatie 
monthly_stats['HighSpending'] = monthly_stats['InvoiceAmount'] > threshold_amount 
print("Maandelijkse factuurstatistieken per leverancier:") 
print(monthly_stats) 

# Eventueel terugkoppeling naar leveranciernaam voor leesbaarheid 
monthly_stats = monthly_stats.merge(vendors[['VendorID', 'VendorName']], on='VendorID', how='left') 
print("\nMaandelijkse factuurstatistieken met leveranciernaam:") 
print(monthly_stats[['VendorName', 'InvoiceMonth', 'InvoiceID', 'InvoiceAmount', 'HighSpending']])

Interpretatie:
Je kunt hieruit afleiden welke leveranciers in een korte periode ineens veel declareren. Door de drempelwaarde (of een statistische techniek om outliers te detecteren) aan te passen, kun je meer of minder gevoelig zijn voor afwijkingen.

4. Vergelijken van de historische trend

Een andere manier om afwijkingen te vinden is door historische gemiddelden te vergelijken met de huidige periode. Zo zie je bijvoorbeeld of een leverancier plotseling 3x zoveel declareert als gebruikelijk.

Stappen:

  1. Bereken voor elke leverancier per maand de totaalbedragen.

  2. Vergelijk de meest recente maand (of periode) met het gemiddelde van eerdere maanden.

  3. Definieer een percentage of factor om afwijkingen te markeren.

# Ga uit van de monthly_stats uit de vorige stap 
# Bereken gemiddelde en standaarddeviatie (bijv. over de afgelopen n maanden) 
historical_summary = monthly_stats.groupby('VendorID')['InvoiceAmount'].agg(['mean', 'std']).reset_index() 

# Koppel de berekende statistieken terug 
monthly_stats = monthly_stats.merge(historical_summary, on='VendorID', how='left', suffixes=('', '_Hist')) 

# Stel een simpel criterium op: InvoiceAmount > mean + 2 * std 
monthly_stats['SignificantIncrease'] = monthly_stats['InvoiceAmount'] > (monthly_stats['mean'] + 2 * monthly_stats['std']) print("Vergelijking van huidige maand met historische gemiddelden:") 
print(monthly_stats[['VendorName', 'InvoiceMonth', 'InvoiceAmount', 'mean', 'std', 'SignificantIncrease']])

Interpretatie:
Zo kun je zien of een leverancier een plotselinge piek vertoont. Als de standaarddeviatie laag is en de huidige periode ver boven het gemiddelde ligt, kan dat wijzen op een abnormale activiteit die verder onderzocht moet worden.

5. Leveranciers op basis van hun vestigingsplaats

Het kan nuttig zijn te zien in welke regio’s je leveranciers gevestigd zijn, en of er leveranciers uit ongebruikelijke landen/regio’s plotseling opduiken.

Stappen:

  1. Neem de veldnaam Region (of Country).

  2. Tel het aantal leveranciers per regio of het totale factuurbedrag per regio.

  3. Zoek regio’s die afwijken van wat je normaliter verwacht.

# Tel aantal leveranciers per regio 
region_count = vendors.groupby('Region')['VendorID'].count().reset_index().rename(columns={'VendorID': 'VendorCount'}) 

# Eventueel ook totale factuurbedrag per regio (op basis van invoices) 
invoices_by_region = invoices.merge(vendors, on='VendorID', how='left') 
region_spend = invoices_by_region.groupby('Region')['InvoiceAmount'].sum().reset_index().rename(columns={'InvoiceAmount': 'TotalSpend'}) 

print("Aantal leveranciers per regio:") 
print(region_count) 

print("\nTotale uitgaven per regio:") 
print(region_spend)`

Interpretatie:

  • Als je 95% van je leveranciers en uitgaven in Nederland verwacht, kan een plotselinge toename van leveranciers uit een ander land (bijv. DE of UK) een signaal zijn voor extra risicobeoordeling of juist nieuwe kansen.