diff --git a/data/crops/almass/crop_data_general.csv b/data/crops/almass/crop_data_general.csv
index 806fdd7a87078e676dad57951561db6a6d45a7a8..c779dec5fa35c5777bb5363b88a81dbd8556bddc 100644
--- a/data/crops/almass/crop_data_general.csv
+++ b/data/crops/almass/crop_data_general.csv
@@ -6,7 +6,7 @@ name,minsowdate,maxsowdate,minharvestdate,maxharvestdate,mingrowthtemp,group
 "winter barley","15 September","30 September",NA,NA,0,"grain"
 "spring barley","1 March","10 April",NA,NA,0,"grain"
 "undersown spring barley",NA,NA,NA,NA,0,"grain"
-"winter rye","23 September","15 October",NA,NA,NA,NA,"grain"
+"winter rye","23 September","15 October",NA,NA,NA,"grain"
 "triticale","25 September","10 October",NA,NA,NA,"grain"
 "oats",NA,NA,NA,NA,NA,"grain"
 "maize","15 April","30 April",NA,NA,8,"grain"
diff --git a/src/crop/almass.jl b/src/crop/almass.jl
index 4e5bfe7a2a0341454f78fa4c140a93aff87cdaea..570305a4e4a3cc9c44724305ca359bd859d39197 100644
--- a/src/crop/almass.jl
+++ b/src/crop/almass.jl
@@ -22,7 +22,10 @@ import Persefone:
     cropname,
     cropheight,
     cropcover,
-    cropyield
+    cropyield,
+    sow!,
+    harvest!,
+    isharvestable
 
 using Dates: Date, month, monthday
 using CSV: CSV
@@ -86,6 +89,7 @@ mutable struct CropState
     LAItotal::Float64
     LAIgreen::Float64
     #biomass::Float64 #XXX I need to figure out how to calculate this
+    mature::Bool #TODO how do we determine this?
     events::Vector{Management}
 end
 
@@ -94,7 +98,7 @@ cropname(cs::CropState) = cropname(croptype(cs))
 cropheight(cs::CropState) = cs.height
 cropcover(cs::CropState) = 0.0  # TODO: related to LAItotal, LAIgreen?
 cropyield(cs::CropState) = 0.0  # TODO: units? needs biomass?
-isharvestable(cs::CropState) = false #FIXME how do we do this?
+isharvestable(cs::CropState) = cs.mature
 
 """
     Base.tryparse(type, str)
@@ -233,6 +237,7 @@ function growcrop!(cs::CropState, model::SimulationModel)
     points = curve.GDD[cs.phase]
     for p in 1:length(points)
         if points[p] == 99999
+            cs.mature = true #FIXME is this correct?
             return # the marker that there is no further growth this phase
         elseif points[p] == -1 # the marker to set all variables to specified values
             cs.height = curve.height[cs.phase][p]
diff --git a/src/crop/cropmodels.jl b/src/crop/cropmodels.jl
index d94725414df7fb9a941032681be9d468e43edee9..aef409f0f531326deaa706dcb58b8303bf713c71 100644
--- a/src/crop/cropmodels.jl
+++ b/src/crop/cropmodels.jl
@@ -66,7 +66,7 @@ function makecropstate(model::SimulationModel)
         cs = ALMaSS.CropState(
                 model.crops["natural grass"],
                 phase,
-                0.0, 0.0m, 0.0, 0.0, Vector{Management}()
+                0.0, 0.0m, 0.0, 0.0, false, Vector{Management}()
         )
     elseif @param(crop.cropmodel) == "simple"
         cs = SimpleCrop.CropState(
diff --git a/src/farm/farm.jl b/src/farm/farm.jl
index 108f2efeb8e31133b9cf47b8a171d4b48e5e4418..32a4d7f68a9894d9023f6d407e97e6b10fd6164c 100644
--- a/src/farm/farm.jl
+++ b/src/farm/farm.jl
@@ -3,6 +3,8 @@
 ### This file is responsible for managing the farm module(s).
 ###    
 
+##TODO what data do we need to gather from the farm submodel?
+
 """
     Farmer
 
@@ -12,6 +14,7 @@ mutable struct Farmer <: ModelAgent
     #XXX make this into an abstract type and create subtypes for different farm submodels? (#69)
     const id::Int64
     fields::Vector{Int64} # IDs of the farmplots this farmer owns
+    croprotation::Vector{String} #TODO figure this out
     totalincome::Float64
 end
 
@@ -24,7 +27,7 @@ function stepagent!(farmer::Farmer, model::SimulationModel)
     for f in farmer.fields
         field = model.farmplots[f]
         ctype = croptype(field)
-        if ctype.group != "semi-natural" && isharvestable(field) #TODO implement
+        if ctype.group != "semi-natural" && isharvestable(field)
             harvest!(field, model)
             #XXX later: calculate income based on yield and annual price
             (ctype.group != "grass") && @sow("no growth")
@@ -41,11 +44,11 @@ Initialise the model with a set of farm agents.
 """
 function initfarms!(model::SimulationModel)
     #XXX initially, we only have one farmer controlling all fields in the region
-    farmer = Farmer(1, collect(1:length(model.farmplots)), 0)
+    farmer = Farmer(1, collect(1:length(model.farmplots)), [], 0)
     model.farmers = [farmer]
-    setasides = findsetasides(farmer, model) #TODO implement
+    setasides = findsetasides(farmer, model)
     for field in model.farmplots
-        if isgrassland(field)
+        if isgrassland(field, model)
             @sow("permanent grassland (seeded)")
         elseif field.id in setasides
             @sow("permanent set-aside")
@@ -63,36 +66,18 @@ set-aside rules.
 """
 function findsetasides(farmer::Farmer, model::SimulationModel)
     @param(farm.setaside) == 0 && return []
-    croparea = reduce(f -> isgrassland(f) ? 0 : length(f.pixels), model.farmplots[farmer.fields]) *
-        @param(world.mapresolution)^2
+    croparea = @areaof(sum(f -> isgrassland(f, model) ? 0 : length(f.pixels),
+                           model.farmplots[farmer.fields]))
     setasidearea = 0m²
     setasides = []
     for f in farmer.fields #XXX should be sorted smallest-largest for highest efficiency
         field = model.farmplots[f]
-        isgrassland(f) && continue
+        isgrassland(field, model) && continue
         push!(setasides, f)
-        setasidearea += length(field.pixels)*@param(world.mapresolution)^2
+        setasidearea += @areaof(length(field.pixels))
         if setasidearea >= croparea*@param(farm.setaside)
             @debug "Farmer $(farmer.id) has set aside $(setasidearea |> ha)."
             return setasides
         end
     end
 end
-
-"""
-    @sow(cropname)
-
-Sow the named crop on the current field. Requires the variables `field` and `model`.
-"""
-macro sow(cropname)
-    :(sow!($(esc(:field)), $(esc(:model)), $(esc(cropname))))
-end
-
-"""
-    @harvest()
-
-Harvest the current field. Requires the variables `field` and `model`.
-"""
-macro harvest()
-    :(harvest!($(esc(:field)), $(esc(:model))))
-end