#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!) (seed-nutrients!) (seeded "nutrients") (seed-historical-nutrient-measurements!) (seeded "historical nutrient measurements") (seed-crops!) (seeded "crops") (seed-crop-requirements!) (seeded "crop requirements") (seed-existing-fertilizer-products!) (seeded "existing fertilizer products")) (define (seeded entity) (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)]) (define name (first pair)) (define formula (second 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/list ([nm (in-list (cdr row-alist))]) (define formula (car nm)) (define n (get-nutrient #:formula formula)) (define v (string->number (cdr nm))) (cons 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/list ([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))) (cons 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/list ([fertilizer-component (in-list (list-tail row-alist 3))]) (define formula (car fertilizer-component)) (define n (get-nutrient #:formula formula)) (define v (string->number (cdr fertilizer-component))) (cons 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))) (module+ test (require "migrations.rkt") (connect! #:path "test.sqlite3" ) (migrate-all!) (seed-database!))