Introduktion
Har du nogensinde åbnet en salgsordre, en projektopgave eller en produktionsordre i Odoo? Så har du allerede mødt et datofelt — det er her, man gemmer leveringsdatoer, betalingsfrister, kontraktstart og andre tidspunkter, der kun handler om datoen, ikke om klokkeslættet.
For slutbrugerne er datofeltet simpelt: klik, vælg i kalenderen, eller skriv datoen. Men for udviklere og konsulenter gemmer der sig nogle vigtige antagelser i databasen og i Odoo-ORM’en. Når du forstår, hvad der gemmes og hvad der ikke gemmes, undgår du typiske faldgruber som tidszoneeffekter og forkerte beregninger i rapporter.
Denne guide samler de praktiske pointer om datofeltet i Odoo: hvad feltet repræsenterer, hvordan det oprettes, hvor du helst bruger det i forretningen, og hvilke designvalg der gør dine arbejdsgange mere robuste.
Hvad er et datofelt i Odoo
I Odoos objekt-relationelle lag er et datofelt beregnet til alene at repræsentere en kalenderdato — år, måned og dag. Der er ingen timer, minutter eller sekunder med i billedet; værdien er udelukkende en dato som 2026-03-06.
I databasen svarer et sådant felt til en DATE-kolonne i PostgreSQL. Det står i kontrast til et DateTime-felt, som bruger TIMESTAMP og indeholder et fuldt tidspunkt ned til sekunder og ofte håndteres i UTC.
I brugerfladen vises datofeltet typisk som et tekstfelt med en kalenderpicker. Brugere kan taste direkte eller vælge i kalenderen, og i lister formateres datoen efter brugerens lokale indstillinger.
Et datofelt defineres typisk i din Python-model, og det ser sådan ud i struktur — men navngivning, hjælpetekst og andre attributter vælger du ud fra behovet.
Eksempel på en modeltilføjelse (konceptuelt):
from odoo import fields, models
class ProjectTask(models.Model):
_inherit = 'project.task'
x_deadline_confirmed = fields.Date(
string='Confirmed Deadline',
help='The officially confirmed deadline agreed with the customer.',
)
Når du opretter felter via Odoo Studio får de automatisk et x_studio_-præfiks. Bygger du felter i kode eller via API, bestemmer du selv det tekniske navn — ret praktisk i versionstyrede projekter.
Hvordan feltet fungerer
Date vs. DateTime: hvad er forskellen
Det essentielle ved et datofelt er, hvad det ikke indeholder: tid på døgnet. Der sker ingen tidszonekonvertering, og der følger ingen timer eller minutter med — kun kalenderdatoen.
Et DateTime-felt indeholder derimod et komplet tidsstempel, typisk gemt i UTC. Ved visning konverterer Odoo dette til brugerens tidszone, hvilket ofte er årsagen til forvirring, når datoer tilsyneladende 'rykker sig' en dag for brugere i forskellige tidszoner.
Med et datofelt er der ingen overraskelser: hvis du gemmer 2026-03-15, så er det 2026-03-15 for alle brugere uanset hvor de sidder henne.
Vigtige feltattributter
Her er de mest nyttige parametre, du bør kende til, når du arbejder med datofelter i Odoo:
- required: Gør feltet obligatorisk i både interface og på modelniveau.
- default: Angiver en standardværdi. fields.Date.today bruges ofte for at sætte dags dato ved oprettelse.
- index: Laver et databaseindeks, hvilket gør filtre og søgninger meget hurtigere på store datamængder.
- compute: Tillader, at feltet beregnes via en Python-metode.
- store: Kombineret med compute gemmer du det beregnede resultat i databasen, så det kan bruges i søgninger og rapporter.
- readonly: Forhindrer direkte redigering i brugerfladen.
- copy: Bestemmer om værdien medtages ved duplikering af poster — som standard True.
Hvordan feltet vises i views
I formularer får du et indtastningsfelt med kalenderpopup; i lister vises en lokaliseret dato; i søgninger kan brugere vælge standardintervaller som "denne uge", "denne måned" eller lave præcise sammenligninger (før, efter, på dato).
Formatet følger brugerens sprogindstillinger — dansk vises typisk som DD/MM/YYYY — men internt gemmes datoen altid i ISO-format (YYYY-MM-DD).
Interaktion med Odoo ORM'en
Når du læser et datofelt gennem ORM'en får du et Python datetime.date-objekt eller False, hvis feltet er tomt. Når du skriver via ORM'en, kan du give enten et datetime.date-objekt eller en streng i 'YYYY-MM-DD' format. XML-RPC arbejder typisk med strengrepræsentationer.
Der er ingen skjulte, komplekse transformationer: Odoo og databasen tager sig af formatering og lagring, hvilket gør datofeltet praktisk og pålideligt i udvikling og drift.
Forretningsscenarier
Praktiske eksempler fra forretningen
CRM: kontraktstart og -ophør
I salgsarbejdet registreres ofte kontraktens start- og slutdato som datofelter. Det gør det nemt at se, hvornår en aftale træder i kraft, og hvornår den udløber.
Kombineret med automatisering kan du lade systemet sende påmindelser eller skifte statuses, når en kontrakt nærmer sig sin udløbsdato — det reducerer risikoen for glemte fornyelser betydeligt.
Salg: ønsket leveringsdato
Kunder angiver ofte en ønsket leveringsdato ved ordre. Et dedikeret datofelt på salgsordren giver driftsteamet en klar, enkel dato at planlægge efter.
Ved at bruge datofelt i stedet for DateTime undgår man tidspåvirkede misforståelser mellem salg og lager; alle ser den samme dato uden konverteringsfejl.
Lager: udløbsdatoer på partier
I fødevare-, pharma- og kemibranchen skal partier spore udløbs- og bedst-før-datoer. Lagerpartier i Odoo gemmer disse som datofelter.
Det gør det muligt at picke FEFO (først udløb først) og sende automatiske advarsler ved nært forestående udløb, hvilket beskytter både compliance og produktkvalitet.
Regnskab: forfaldsdatoer for fakturaer
Fakturaers forfaldsdatoer er datofelter. De styrer rykkere, overtræksidentifikation og aldersfordelte rapporter.
Forkerte forfaldsdatoer ødelægger likviditetsopfølgning og automatiserede betalingsflows — det er en af de mest operationelt kritiske anvendelser af datofeltet.
HR: ansættelses- og certificeringsdatoer
HR bruger datofelter til ansættelsesdatoer, prøvetidsophør, kontraktperioder og certifikatudløb. Disse datoer trigger ofte e-mails, påmindelser og lønberegninger.
Et robust HR-setup i Odoo hviler på korrekte og konsistente datofelter for medarbejdere; mange kritiske processer er afhængige af disse værdier.
Oprettelse og tilpasning af datofeltet
Der er tre almindelige måder at tilføje et datofelt på, afhængig af hvor teknisk du vil være: Studio, Python-moduler eller API-baseret oprettelse.
Brug af Odoo Studio (ingen kode)
Studio er den hurtigste vej for ikke-udviklere til at få et datofelt ind i en formular — ideelt til konsulenter og superbrugere, der hurtigt vil spore datoer uden udviklingsindsats:
- Åbn Odoo Studio fra hovedmenuen.
- Gå til den formular, hvor feltet skal være.
- Træk et Date-felt ind fra sidepanelet og placer det på formen.
- Sæt etiketten, vælg om feltet er obligatorisk, og angiv eventuelt en standardværdi.
- Gem og luk Studio.
Studio opretter feltet med x_studio_-præfiks og placerer det i view'et straks — ingen database-migration kræves manuelt.
Brug af Python i et custom modul
Udviklere definerer datofelter i Python-modeller. Denne metode er den rigtige, når ændringer skal versionsstyres og rulles ud til flere miljøer:
Eksempel på kode (konceptuelt):
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_customer_requested_date = fields.Date(
string='Customer Requested Date',
index=True,
copy=False,
help='Delivery date requested by the customer at time of order.',
)
Efter at feltet er føjet til modellen skal det også indsættes i den relevante view-XML, så brugerne kan se og redigere det. Ved installation eller opgradering opretter Odoo databasekolonnen automatisk.
Brug af XML-RPC API'en
Hvis du opsætter felter programmatisk som led i en udrulning, kan du også skabe datofelter via XML-RPC:
Eksempel på opkald (konceptuelt):
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_customer_requested_date',
'field_description': 'Customer Requested Date',
'model_id': model_id,
'ttype': 'date',
'state': 'manual',
}]
)
Til et datofelt bruger du ttype='date'. Angivelsen state='manual' markerer, at feltet er oprettet ad-hoc og ikke som led i et modul — nyttigt i scripts og automatiserede konfigurationer.
Gode fremgangsmåder
1. Brug Date, ikke DateTime, når tidspunkt ikke betyder noget
Hvis kun datoen er vigtig (f.eks. frister, fødselsdatoer eller udløbsdatoer), så vælg fields.Date. DateTime tilføjer tidszonekompleksitet uden værdi og er ofte kilden til 'forkerte datoer' i tværgående teams.
2. Sæt en meningsfuld standardværdi, når det giver mening
Felt som 'Forventet leveringsdato' har ofte fordel af en standard som dags dato eller dags dato + N dage. Brug default=fields.Date.today (uden parentes) for at evaluere datoen ved oprettelse og ikke ved klasseindlæsning.
3. Indekser datofelter, der bruges i rapporter og filtre
Hvis brugerne ofte filtrerer efter et datofelt (efterløbne fakturaer, kommende fornyelser), så sæt index=True. På store tabeller giver det markant bedre ydeevne for søgninger og rapportudkørsel.
4. Brug copy=False for datoer, der ikke skal kopieres
Datoer som kontraktstart eller udløbsdato skal normalt ikke kopieres ved duplikering. copy=False gør, at brugeren aktivt skal angive en ny dato på den kopierede post, hvilket undgår stiltiende fejl.
5. Tilføj valideringer når to datoer danner et interval
Har du både start- og slutdato, så lav en @api.constrains-validering, der sikrer slutdatoen ikke ligger før startdatoen. Det forhindrer ulogiske data, som senere bryder beregninger og rapporter.
Almindelige fejl
Forveksling af Date og DateTime
Den hyppigste fejl er at bruge DateTime, når en simpel dato var tilstrækkelig. DateTime gemmes i UTC og konverteres ved visning — det er den typiske årsag til, at en dato ser ud til at være rykket en dag for andre brugere i andre tidszoner.
Vælg altid det simpleste felttype, der opfylder forretningens behov.
Ignorering af server-tidszone i planlagte jobs
Når du laver planlagte handlinger eller rapporter baseret på 'i dag', skal du være opmærksom på at fields.Date.today() bruger serverens UTC-dato. For distribuerede teams kan det give en-dagsafvigelser i automatisk logik — test dine jobs fra forskellige tidszoner, hvis det er relevant.
Manglende validering af datointervaller
Mange systemer har separate felt for start og slut, men ingen kontrol som sikrer logikken. Uden constraints kan ugyldige intervaller komme ind i systemet og skabe forkerte varighedsberegninger og fejlbehæftede filtreringer.
Glemme at indeksere datofelter, der bruges i filtre
Filtrering som 'dato mindre end i dag' er kostbart uden indeks — det fører til fulde tabelscanninger. På store modeller som fakturaer eller lagerbevægelser kan manglende indeks gøre daglig drift langsommere.
At gemme datoer som tekst
Nogle vælger at gemme datoer i Char-felter for at bevare et specifikt format eller undgå pickeren. Det ødelægger sortering, filtrering, dato-aritmetik og rapporter. Brug altid fields.Date; Odoo og PostgreSQL håndterer formatering og lokalisering bedre.
Ofte stillede spørgsmål (FAQ)
Hvad er forskellen på Date og DateTime i Odoo?
Date gemmer kun kalenderdato (år, måned, dag). DateTime gemmer et fuldt tidsstempel (timer, minutter, sekunder), typisk i UTC og konverteres til brugerens tidszone ved visning. Brug Date når tid på dagen er irrelevant; brug DateTime når du skal registrere præcis tidspunkt for en begivenhed.
Hvordan sætter jeg dags dato som standard for et datofelt?
I Python brug default=fields.Date.today (uden parentes). Det er en callable, der evalueres ved oprettelse, så standarden altid er den aktuelle dato. I Odoo Studio vælger du 'Today' i feltets indstillinger.
Kan jeg beregne et datofelt ud fra andre felter?
Ja. Definér feltet med compute='_compute_my_date' og skriv en metode med @api.depends([...]) som angiver hvilke felter, der udløser genberegning. Brug datetime.date og datetime.timedelta til beregninger, og tilføj store=True hvis resultatet skal gemmes i databasen.
Hvordan filtrerer jeg poster inden for et datointerval i et Odoo-domæne?
Brug standard sammenligningsoperatorer i domænet. For eksempel for at finde poster i marts 2026:
[
('x_date_field', '>=', '2026-03-01'),
('x_date_field', '<=', '2026-03-31')
]
Brug altid ISO-format (YYYY-MM-DD) i domæner når du skriver datoer som strenge.
Kan jeg gøre et datofelt obligatorisk kun under visse betingelser?
Bagenden i Odoo håndhæver ikke betinget obligatoriskhed uden kode. Du kan bruge attrs i view-XML for at vise et felt som påkrævet i UI, men ægte server-side validering kræver en Python @api.constrains. Odoo Studio tilbyder nogle visuelle regler som ofte er tilstrækkelige uden at kode.
Konklusion
Datofeltet er et af de mest praktiske felttyper i Odoo: enkelt at forstå, nemt at bruge og stærkt nok til at drive påmindelser, forfaldstjek og tidsbaserede rapporter.
De vigtigste pointer at huske er: vælg Date fremfor DateTime når kun kalenderdatoen betyder noget, brug fornuftige defaults og indeks på felter der søges meget på, og tilføj altid valideringer når to datoer danner et interval.
At bygge et velfungerende datamodel i Odoo begynder med små, men vigtige valg som at vælge korrekt felttype. De rette valg fra starten gør systemet mere pålideligt og lettere at vedligeholde.
Vi hos Dasolo hjælper virksomheder med at implementere, tilpasse og optimere Odoo på tværs af afdelinger. Om det er datamodellering, custom felter, workflows eller komplette moduler, så står vores team klar til at assistere. Kontakt os og lad os tage en snak om dit Odoo-projekt.