summaryrefslogtreecommitdiff
path: root/db/seed.rkt
blob: 0284becfa059d408ea25e03d5e5f2862621d64f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#lang racket

(provide seed-database!)

(require csv-reading
         racket/runtime-path
         "conn.rkt"
         "../models/nutrient.rkt"
         "../models/nutrient-measurement.rkt"
         "../models/crop.rkt"
         "../models/crop-requirement.rkt"
         "../models/fertilizer-product.rkt")

(define (seed-database!)
  (for ([phase (in-list seed-sequence)])
    (match-define (cons entity seed-function) phase)
    (seed-function)
    (displayln (format "Seeded entity: ~a" entity))))

(define (seed-nutrients!)
  (define nutrient-names (map nutrient-name (get-nutrients)))
  (define default-nutrients
    '(("Nitrate Nitrogen" . "NNO3") ("Phosphorus" . "P")
                                    ("Potassium" . "K")
                                    ("Calcium" . "Ca")
                                    ("Magnesium" . "Mg")
                                    ("Sulfur" . "S")
                                    ("Sodium" . "Na")
                                    ("Chloride" . "Cl")
                                    ("Silicon" . "Si")
                                    ("Iron" . "Fe")
                                    ("Zinc" . "Zn")
                                    ("Boron" . "B")
                                    ("Manganese" . "Mn")
                                    ("Copper" . "Cu")
                                    ("Molybdenum" . "Mo")
                                    ("Ammonium Nitrogen" . "NNH4")))
  (with-tx (for ([pair (in-list default-nutrients)])
             (match-define (cons name formula) pair)
             ;; Ensure idempotence
             (unless (member name nutrient-names)
               (create-nutrient! name formula)))))

(define-runtime-path measurement-csv "data/dolibarr_nutrient_measurements_ppm.csv")
(define (seed-historical-nutrient-measurements!)
  (define next-row (make-csv-reader (open-input-file measurement-csv)))
  (define header (next-row))
  (define (row->seed! row)
    (define row-alist (map cons header row))
    (define measured-on (cdr (first row-alist)))
    (define nutrient-values
      (for/hash ([nm (in-list (cdr row-alist))])
        (define formula (car nm))
        (define n (get-nutrient #:formula formula))
        (define v (string->number (cdr nm)))
        (values n v)))
    (create-nutrient-measurement! measured-on nutrient-values))
  (with-tx (csv-for-each row->seed! next-row)))

(define (seed-crops!)
  (define crop-names (map crop-name (get-crops)))
  (define default-crops '("salade" "laitue" "tomate" "framboise"))
  (with-tx (for ([name (in-list default-crops)])
             ;; Ensure idempotence
             (unless (member name crop-names)
               (create-crop! name)))))

(define-runtime-path requirements-csv "data/dolibarr_crop_requirements_ppm.csv")
(define (seed-crop-requirements!)
  (define next-row (make-csv-reader (open-input-file requirements-csv)))
  (define header (next-row))
  (define (row->seed! row)
    (define row-alist (map cons header row))
    (define crop-name (string-downcase (cdr (assoc "Plante" row-alist))))
    (define profile (cdr (assoc "Profil" row-alist)))
    (define nutrient-values
      (for/hash ([crop-requirement (in-list (list-tail row-alist 2))])
        (define formula (car crop-requirement))
        (define n (get-nutrient #:formula formula))
        (define v (string->number (cdr crop-requirement)))
        (values n v)))
    (cond
      [(non-empty-string? crop-name)
       (define crop (get-crop #:name crop-name))
       (create-crop-requirement! profile nutrient-values crop)]
      [else (create-crop-requirement! profile nutrient-values)]))
  (with-tx (csv-for-each row->seed! next-row)))

(define-runtime-path fertilizer-csv "data/dolibarr_fertilizer_compositions_percentage.csv")
(define (seed-existing-fertilizer-products!)
  (define next-row (make-csv-reader (open-input-file fertilizer-csv)))
  (define header (next-row))
  (define (row->seed! row)
    (define row-alist (map cons header row))
    (define canonical-name (cdr (assoc "Libellé" row-alist)))
    (define brand-name (cdr (assoc "Nom commercial" row-alist)))
    (define nutrient-values
      (for/hash ([fertilizer-component (in-list (list-tail row-alist 3))])
        (define n (get-nutrient #:formula (car fertilizer-component)))
        (define v (string->number (cdr fertilizer-component)))
        (values n v)))
    (cond
      [(non-empty-string? brand-name)
       (create-fertilizer-product! canonical-name nutrient-values brand-name)]
      [else (create-fertilizer-product! canonical-name nutrient-values)]))
  (with-tx (csv-for-each row->seed! next-row)))

(define seed-sequence
  (list (cons "nutrients" seed-nutrients!)
        (cons "nutrient measurements" seed-historical-nutrient-measurements!)
        (cons "crops" seed-crops!)
        (cons "crop requirements" seed-crop-requirements!)
        (cons "fertilizer products" seed-existing-fertilizer-products!)))

(module+ test
  (require "migrations.rkt")
  (connect! #:path 'memory)
  (migrate-all!)
  (seed-database!))
Copyright 2019--2026 Marius PETER