Project G - Analyseer omzetgegevens

01 - Projectoverzicht
  • In dit project maak je een Python-script dat omzetgegevens analyseert uit een CSV-bestand.
  • Het script helpt wanneer je snel wilt weten welke maand, klant of productgroep de meeste omzet oplevert.
  • Je gebruikt een CSV-bestand met verkoopregels, bijvoorbeeld datum, klant, product, aantal en verkoopbedrag.
  • Het script groepeert de regels en berekent totalen per maand, klant of product.
  • Het resultaat is een overzicht met omzetcijfers dat je kunt tonen in de terminal of opslaan als nieuw CSV-bestand.
  • Je gebruikt AI om code te laten genereren die de berekeningen uitlegbaar houdt voor beginners.
  • Je voert de code uit in VS Code en vergelijkt de uitkomst met een paar handmatig gecontroleerde regels.
  • Als de analyse niet klopt, verbeter je de prompt met voorbeeldregels uit het CSV-bestand en de gewenste berekening.
02 - Projectmap en Python-omgeving

Voorkennis: doorloop de voorgaande projecten. Het doel en gebruik van .venv zijn uitgelegd in project A, blok 02. Voor ieder nieuw project maak je een eigen omgeving; hieronder herhaal je die bekende stappen.

  • Maak een eigen projectmap project_g en open die map in VS Code. Maak daarin straks omzet.py.
  • Deze oefeningen voer je lokaal uit in de terminal van VS Code, omdat ze bestanden op je computer lezen of schrijven. Gebruik hiervoor de Python-installatie uit de basiscursus.
  • Controleer je Python-versie. Werkt python op macOS of Linux niet, gebruik dan python3 voor het aanmaken van de omgeving.
python --version
python -m venv .venv

Activeer de omgeving. In Windows PowerShell:

.venv\Scripts\Activate.ps1

In de Windows-opdrachtprompt (cmd):

.venv\Scripts\activate.bat

Op macOS of Linux:

source .venv/bin/activate

Kies in VS Code via Python: Select Interpreter de interpreter uit .venv. Gebruik vanaf nu de geactiveerde terminal. Je verlaat de omgeving later met deactivate.

Dit project gebruikt alleen de standaardbibliotheek van Python. Extra pakketten installeren is niet nodig.

03 - Testgegevens voorbereiden

Maak verkopen.csv naast het script. prijs is de prijs per stuk exclusief btw, in euro’s. Omzet per regel is aantal × prijs. De voorbeelden gebruiken fictieve klanten.

datum,klant,product,aantal,prijs
2026-05-01,Alfa,Boek,2,25.00
2026-05-12,Beta,Pen,10,1.50
2026-06-02,Alfa,Boek,1,25.00
04 - Begrippen en hulpmiddelen vóór de opdracht
  • Je gebruikt CSV en Decimal uit project F. date.fromisoformat leest een datum in de vorm YYYY-MM-DD. int controleert of een aantal een geheel getal is.
  • defaultdict(lambda: Decimal("0")) maakt voor een nieuwe sleutel een Decimal-nul. lambda is de korte functienotatie die bij het sorteren van dictionaries in hoofdstuk 6 wordt toegelicht.
  • quantize(Decimal("0.01")) rekent om naar twee decimalen. We vergelijken met de oorspronkelijke prijs om extra decimalen te weigeren.
  • raise ... from fout geeft een melding met regelnummer en bewaart de oorspronkelijke fout als oorzaak. sum(..., Decimal("0")) telt op met Decimal als beginwaarde.
  • Eerst wordt de invoer gecontroleerd, daarna pas opgeteld. Bij ongeldige data wordt geen nieuwe CSV geschreven; een oudere uitvoer kan nog wel bestaan.
  • defaultdict begint voor elke nieuwe maand of klant op nul. De sleutel YYYY-MM sorteert in chronologische volgorde.
  • Dit is omzet exclusief btw. Kosten, winst, betalingen en retouren zijn geen onderdeel van deze eerste analyse.
05 - Een gerichte AI-prompt maken

Geef AI eerst een concrete opdracht. Kopieer bijvoorbeeld deze prompt en vergelijk het antwoord met de voorbeeldcode in het volgende blok:

Maak een script met csv, datetime, collections.defaultdict en Decimal dat
verkopen.csv analyseert. Controleer de kolommen
datum,klant,product,aantal,prijs en valideer iedere regel: ISO-datum, niet-
lege klant en product, positief geheel aantal en eindige niet-negatieve
prijs met maximaal twee decimalen. Stop met regelnummer bij ongeldige
invoer. Bereken aantal maal prijs en groepeer omzet per maand, klant en
product. Toon totalen en schrijf alleen maandtotalen naar
omzet_per_maand.csv.

Vraag om uitleg bij onbekende regels en controleer welke bestanden de code leest en schrijft voordat je haar uitvoert. Gebruik de oefengegevens uit dit project.

06 - Een werkende basisversie

Dit is een complete basisversie voor omzet.py. Neem de code over of vergelijk haar met het antwoord van AI.

from pathlib import Path
from collections import defaultdict
from datetime import date
from decimal import Decimal, InvalidOperation
import csv

BASIS = Path(__file__).resolve().parent

def main():
    maanden = defaultdict(lambda: Decimal("0"))
    klanten = defaultdict(lambda: Decimal("0"))
    producten = defaultdict(lambda: Decimal("0"))
    with (BASIS / "verkopen.csv").open(newline="", encoding="utf-8-sig") as bestand:
        lezer = csv.DictReader(bestand)
        vereist = {"datum", "klant", "product", "aantal", "prijs"}
        if not vereist.issubset(lezer.fieldnames or []):
            raise ValueError("Controleer de kolomnamen van verkopen.csv")
        for nummer, rij in enumerate(lezer, start=2):
            try:
                datum = date.fromisoformat(rij["datum"])
                klant = rij["klant"].strip()
                product = rij["product"].strip()
                aantal = int(rij["aantal"])
                prijs = Decimal(rij["prijs"])
                if not klant or not product or aantal <= 0:
                    raise ValueError("Klant/product leeg of aantal niet positief")
                if not prijs.is_finite() or prijs < 0:
                    raise ValueError("Ongeldige prijs")
                if prijs != prijs.quantize(Decimal("0.01")):
                    raise ValueError("Prijs heeft meer dan twee decimalen")
            except (ValueError, TypeError, AttributeError, InvalidOperation) as fout:
                raise ValueError(f"Controleer regel {nummer}: {fout}") from fout
            omzet = aantal * prijs
            maanden[datum.strftime("%Y-%m")] += omzet
            klanten[klant] += omzet
            producten[product] += omzet
    for titel, groep in [("Maand", maanden), ("Klant", klanten), ("Product", producten)]:
        print(titel)
        for sleutel, bedrag in sorted(groep.items()):
            print(f"  {sleutel}: EUR {bedrag:.2f}")
    print(f"Totale omzet: EUR {sum(maanden.values(), Decimal('0')):.2f}")
    with (BASIS / "omzet_per_maand.csv").open("w", newline="", encoding="utf-8") as bestand:
        schrijver = csv.writer(bestand)
        schrijver.writerow(["maand", "omzet"])
        schrijver.writerows((m, f"{b:.2f}") for m, b in sorted(maanden.items()))

if __name__ == "__main__":
    try:
        main()
    except (OSError, ValueError, csv.Error) as fout:
        print(f"Analyse niet voltooid: {fout}")
07 - Het script uitvoeren
  • Sla de volledige code op als omzet.py in je projectmap. Zet eventuele invoerbestanden op de plek die in blok 03 staat.
  • Open de geïntegreerde terminal in die projectmap en activeer .venv als dat nog niet is gebeurd.
  • Voer het script uit met:
python omzet.py

Lees eerst de terminaluitvoer en open daarna eventuele uitvoerbestanden. Controleer het resultaat met blok 08 voordat je met eigen gegevens verdergaat.

08 - Het resultaat controleren
  • Mei is EUR 65.00 en juni EUR 25.00; totaal EUR 90.00.
  • Alfa heeft EUR 75.00 omzet, Beta EUR 15.00. Boek heeft EUR 75.00 en Pen EUR 15.00.
  • Verander een datum naar 2026-02-30 of een aantal naar twee: de analyse stopt met een regelnummer. Herstel de invoer en controleer de CSV opnieuw.
09 - Fouten herkennen en oplossen
  • Een totaal is te hoog? Controleer of jouw bronbedrag al een regeltotaal is. Dit voorbeeld verwacht een prijs per stuk.
  • Dubbele verkoopregels tellen dubbel mee. Verwijder ze niet alleen op gelijke bedragen: voeg voor echte data eerst een unieke verkoop-ID toe.
10 - Uitbreiden en afronden

Probeer deze vervolgstap pas als de basis werkt:

Laat AI een top 3 klanten op omzet toevoegen, aflopend gesorteerd. Test ook gelijke omzet en minder dan drie klanten. Vraag om een apart overzicht van afgekeurde regels als je later door wilt rekenen bij invoerfouten.

Bewaar je werkende basisversie en verander één onderdeel tegelijk. Geef AI bij een fout de foutmelding, het relevante stukje code, je testinvoer en de verwachte uitkomst.

Het project is afgerond wanneer de basiscontrole uit blok 08 slaagt en je in eigen woorden kunt uitleggen welke invoer wordt gebruikt, hoe de verwerking werkt en waar de uitvoer terechtkomt.