Skip to the content.

ADR 005 — EUDR Farm Model Separation from Supplier

Date: March 2026 Status: Accepted Author: Ezinna (Founder)


Context

AgriOps initially modelled agricultural supply chains with Supplier as the entity you procure from. During EUDR compliance planning, a critical distinction emerged: the Supplier is the trading entity (cooperative, aggregator, processor) you have a commercial relationship with, while the Farm is the physical plot of land where the commodity was actually produced.

These are not the same thing. A single Supplier may aggregate produce from dozens or hundreds of individual farms. EUDR compliance requires traceability to the farm of origin — not just the supplier entity. This distinction is explicitly required by the regulation.

This was confirmed by internal operational experience: the company’s own EUDR compliance process involves physically mapping individual farms using SW Maps, collecting GPS perimeter data per farm, and maintaining farm-level compliance documentation — separate from the supplier commercial record.


Decision Drivers


Options Considered

Option 1 — Add geolocation fields directly to Supplier model

Store farm geolocation, risk status, and compliance documents directly on the existing Supplier model.

Pros: Simple — no new model required.

Cons:

Option 2 — Separate Farm model with ForeignKey to Supplier ✅ Chosen

A dedicated Farm model sits between Company and commodity flows, linked to Supplier via ForeignKey.

Pros:

Cons:


Decision

Implement a dedicated Farm model with a ForeignKey to both Company (tenant isolation) and Supplier (commercial relationship). Farm is the unit of EUDR compliance verification.


Data Model

class Farm(models.Model):
    RISK_CHOICES = [
        ('low', 'Low Risk'),
        ('standard', 'Standard Risk'),
        ('high', 'High Risk'),
    ]

    company         = models.ForeignKey(Company, on_delete=models.CASCADE)
    supplier        = models.ForeignKey(Supplier, on_delete=models.CASCADE, related_name='farms')
    name            = models.CharField(max_length=255)
    farmer_name     = models.CharField(max_length=255, blank=True)
    geolocation     = models.JSONField(null=True, blank=True)  # GeoJSON Polygon — see ADR 004
    area_hectares   = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    country         = models.CharField(max_length=100)
    state_region    = models.CharField(max_length=100, blank=True)
    commodity       = models.CharField(max_length=100)  # e.g. Soy, Maize, Cocoa

    # EUDR Compliance
    deforestation_risk_status = models.CharField(max_length=20, choices=RISK_CHOICES, default='standard')
    mapping_date    = models.DateField(null=True, blank=True)
    mapped_by       = models.ForeignKey(
                        CustomUser, null=True, blank=True,
                        on_delete=models.SET_NULL,
                        related_name='farms_mapped'
                      )
    is_eudr_verified = models.BooleanField(default=False)
    verified_by     = models.ForeignKey(
                        CustomUser, null=True, blank=True,
                        on_delete=models.SET_NULL,
                        related_name='farms_verified'
                      )
    verified_date   = models.DateField(null=True, blank=True)
    verification_expiry = models.DateField(null=True, blank=True)

    created_at      = models.DateTimeField(auto_now_add=True)
    updated_at      = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.name}{self.supplier.name}"

Traceability Chain

The full EUDR traceability chain through the AgriOps data model:

Company (Tenant)
  └── Supplier (Trading entity)
        └── Farm (Physical plot — EUDR unit)
              └── Product (Commodity type)
                    └── Inventory (Stock held)
                          └── PurchaseOrder (Procurement record)
                                └── SalesOrder (Dispatch to buyer)

This chain supports generation of the EUDR Due Diligence Statement by joining:


Consequences


Real-World Validation

This decision is validated by the founder’s direct operational experience. The company’s soy contract with an EU buyer explicitly requires EUDR compliance including farm-level geolocation. The internal compliance process — using SW Maps and NCAN Farm Mapper to physically measure farm perimeters — maps directly to the Farm model designed here. AgriOps is digitising a process the founder has personally managed.