Case study: Plannen van inkoopbestellingen

Het doel van deze applicatie

Het doel van deze applicatie is automatisch inkoopbestellingen te genereren op basis van de huidige voorraad. Deze inkoopbestellingen worden geëxporteerd en daarna gemaild.

Bestelmomenten

Verder moet dit op bepaalde tijdstippen en dagen gebeuren: bestelmomenten van de leverancier. Iedere dag plant de applicatie taken in die een potentiële inkoopbestelling genereren.

Requirements Vergaring

Allereerst begin ik met het vergaren van de requirements samen met de klant. Hieruit volgen verschillende features die ik in Azure DevOps beschrijf. De requirements voor dit project waren als volgt:

  • Productgroepen worden onderscheiden door middel van een tag in Picqer.
  • Als (vrije voorraad + vul voorraad aan tot niveau) < bestelniveau dan moet er besteld worden: vul voorraad aan tot niveau - vrije voorraad - te ontvangen.
  • Het inkoopadvies houdt rekening met minimale bestelhoeveelheid en bestel in veelvoud van.
  • Er wordt rekening gehouden met minimaal bestelbedrag leverancier.
  • Per leverancier een ander exportbestand welke gemaild wordt naar de klant.
  • Leverancier kan 0, 1 of meerdere bestelmomenten per dag hebben.
  • Iedere minuut wordt gekeken of een inkooporder gegenereerd moet worden.
  • Gemiste bestelmomenten van voorgaande dagen worden niet ingehaald.

Features

Deze requirements heb ik vervolgens opgesplitst in 4 features: Genereren inkoopadvies, genereren inkoopbestelling, inkoopbestelling mailen naar klant en plannen / plaatsen van inkoopbestellingen. Hier maak ik vervolgens een domain story van: op een visuele manier laten zien wat er gemaakt gaat worden.

Design

Per feature schrijf ik een use case, waar ik als eerste mee begin om deze te designen. Ik zal in dit voorbeeld 1 use case uitwerken om het simpel te houden. Laten we de Genereer inkoopadvies feature hiervoor gebruiken.

Voor iedere requirement van de feature schrijf ik een test. Bijvoorbeeld, er moet rekening gehouden worden met minimaal bestelhoeveelheid en bestel in veelvoud van.

/** @test */
public function it_should_generate_purchasing_advice_while_taking_minimum_purchasing_amount_and_purchase_in_multiples_of_into_account() {
    // Given
    $desiredStock = 3;
    $stock = 0;
    $stockLevel = 3;
    $purchaseInMultiplesOf = 2;
    $minimumPurchasingAmount = 5;

    $inventoryItems = InventoryItemFactory::createMultiple(2, [
        'stock' => new Stock($stock, 0, $desiredStock, $stockLevel),
        'purchaseSettings' => new PurchaseSettings($purchaseInMultiplesOf, $minimumPurchasingAmount),
        'supplierId' => $this->peitsmanSupplier->identity(),
        'tags' => collect(['Onderhoudsproducten'])
    ]);

    $this->inventoryItemRepository->saveMultiple($inventoryItems);

    $url = route('generate-purchase-recommendations');

    // When
    $response = $this->post($url, [
        'suppliers' => [
            [
                'id' => (string) $this->peitsmanSupplier->identity(),
                'tags' => [
                    'Onderhoudsproducten'
                ]
            ]
        ]
    ]);

    // Then
    $response->assertExactJson([
        'payload' => [
            'purchase_recommendations' => [
                0 => [
                    'product_code' => $inventoryItems->first()->productCode(),
                    'amount_to_be_purchased' => 6,
                    'supplier_id' => (string) $inventoryItems->first()->supplierId(),
                    'product_code_supplier' => (string) $inventoryItems->first()->externalProductCode(),
                    'tag' => 'Onderhoudsproducten'
                ],
                1 => [
                    'product_code' => $inventoryItems[1]->productCode(),
                    'amount_to_be_purchased' => 6,
                    'supplier_id' => (string) $inventoryItems[1]->supplierId(),
                    'product_code_supplier' => (string) $inventoryItems[1]->externalProductCode(),
                    'tag' => 'Onderhoudsproducten'
                ]
            ]
        ]
    ]);
}