You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: crop.go
    path of file: ./repos/tania-core/backend/src/growth/domain
    
    the code of the file until where you have to start completion: package domain

import (
	"strings"
	"time"

	"github.com/gofrs/uuid"
	"github.com/usetania/tania-core/src/growth/query"
	"github.com/usetania/tania-core/src/helper/stringhelper"
)

type Crop struct {
	UID          uuid.UUID
	BatchID      string
	Status       CropStatus
	Type         CropType
	Container    CropContainer
	InventoryUID uuid.UUID
	FarmUID      uuid.UUID
	Photos       []CropPhoto

	// Fields to track crop's movement
	InitialArea      InitialArea
	MovedArea        []MovedArea
	HarvestedStorage []HarvestedStorage
	Trash            []Trash

	// Fields to track care crop
	LastFertilized time.Time
	LastPruned     time.Time
	LastPesticided time.Time

	// Notes
	Notes map[uuid.UUID]CropNote

	// Events
	Version            int
	UncommittedChanges []interface{}
}

// CropService handles crop behaviours that needs external interaction to be worked.
type CropService interface {
	FindMaterialByID(uid uuid.UUID) ServiceResult
	FindByBatchID(batchID string) ServiceResult
	FindAreaByID(uid uuid.UUID) ServiceResult
}

// ServiceResult is the container for service result.
type ServiceResult struct {
	Result interface{}
	Error  error
}

// We just recorded two crop status
// because other activities are recurring and parallel.
// So we can't have crop batch with a status, for example `HARVESTED`,
// because not all the crop has harvested.
const (
	CropActive   = "ACTIVE"
	CropArchived = "ARCHIVED"
)

type CropStatus struct {
	Code  string `json:"code"`
	Label string `json:"-"`
}

func CropStatuses() []CropStatus {
	return []CropStatus{
		{Code: CropActive, Label: "Active"},
		{Code: CropArchived, Label: "Archived"},
	}
}

func GetCropStatus(code string) CropStatus {
	for _, v := range CropStatuses() {
		if code == v.Code {
			return v
		}
	}

	return CropStatus{}
}

const (
	CropTypeSeeding = "SEEDING"
	CropTypeGrowing = "GROWING"
)

type CropType struct {
	Code  string
	Label string
}

func CropTypes() []CropType {
	return []CropType{
		{Code: CropTypeSeeding, Label: "Seeding"},
		{Code: CropTypeGrowing, Label: "Growing"},
	}
}

func GetCropType(code string) CropType {
	for _, v := range CropTypes() {
		if code == v.Code {
			return v
		}
	}

	return CropType{}
}

// CropContainerType defines the type of a container.
type CropContainerType interface {
	Code() string
}

// Tray implements CropContainerType.
type Tray struct {
	Cell int
}

func (Tray) Code() string { return "TRAY" }

// Pot implements CropContainerType.
type Pot struct{}

func (Pot) Code() string { ret
    
func (c *Crop) Dump(cropService CropService, sourceAreaUID uuid.UUID, quantity int, notes string) error {
	// Validate //
	// Check if source area is exist in DB
	serviceResult := cropService.FindAreaByID(sourceAreaUID)
	if serviceResult.Error != nil {
		return serviceResult.Error
	}

	srcArea, ok := serviceResult.Result.(query.CropAreaQueryResult)
	if !ok {
		return CropError{Code: CropDumpErrorInvalidSourceArea}
	}

	if srcArea == (query.CropAreaQueryResult{}) {
		return CropError{Code: CropDumpErrorSourceAreaNotFound}
	}

	// Check if area is already set in the crop
	isAreaValid := false
	isQuantityValid := true

	if c.InitialArea.AreaUID == sourceAreaUID {
		isAreaValid = true

		if (c.InitialArea.CurrentQuantity - quantity) < 0 {
			isQuantityValid = false
		}
	}

	for _, v := range c.MovedArea {
		if v.AreaUID == sourceAreaUID {
			isAreaValid = true

			if (v.CurrentQuantity - quantity) < 0 {
				isQuantityValid = false
			}
		}
	}

	if !isAreaValid {
		return CropError{Code: CropDumpErrorSourceAreaNotFound}
	}

	if !isQuantityValid {
		return CropError{Code: CropDumpErrorNotEnoughQuantity}
	}

	if quantity <= 0 {
		return CropError{Code: CropDumpErrorInvalidQuantity}
	}

	// Check source area existence. If already exist, then just update it
	var dumpedArea interface{}

	updatedTrash := Trash{}
	dumpDate := time.Now()

	isExist := false

	for i, v := range c.Trash {
		if v.SourceAreaUID == srcArea.UID {
			updatedTrash = v
			updatedTrash.Quantity = c.Trash[i].Quantity + quantity
			isExist = true
		}
	}

	if !isExist {
		updatedTrash.Quantity = quantity
		updatedTrash.SourceAreaUID = srcArea.UID
		updatedTrash.CreatedDate = dumpDate
		updatedTrash.LastUpdated = dumpDate
	}

	// Reduce the quantity in the area because it has been dumped
	dumpedAreaCode := ""

	if c.InitialArea.AreaUID == srcArea.UID {
		ia := c.InitialArea
		ia.CurrentQuantity -= quantity
		ia.LastUpdated = dumpDate

		dumpedArea = ia
		dumpedAreaCode = "INITIAL_AREA"
	}

	for _, v := range c.MovedArea {
		if v.AreaUID == srcArea.UID {
			ma := v
			ma.CurrentQuantity -= quantity
			ma.LastUpdated = dumpDate

			dumpedArea = ma
			dumpedAreaCode = "MOVED_AREA"
		}
	}

	// Check all the quantity in InitialArea and MovedArea,
	// if its all empty then crop status is marked to archive
	initialAreaEmpty := false

	if dumpedAreaCode == "INITIAL_AREA" {
		ia := dumpedArea.(InitialArea)

		if ia.CurrentQuantity == 0 {
			initialAreaEmpty = true
		}
	} else if c.InitialArea.CurrentQuantity == 0 {
		initialAreaEmpty = true
	}

	movedAreaEmpty := true

	if dumpedAreaCode == "MOVED_AREA" {
		for _, v := range c.MovedArea {
			ha := dumpedArea.(MovedArea)

			if v.AreaUID == ha.AreaUID {
				ha.CurrentQuantity = 0
			}

			if ha.CurrentQuantity != 0 {
				movedAreaEmpty = false
			}
		}
	} else {
		for _, v := range c.MovedArea {
			if v.CurrentQuantity != 0 {
				movedAreaEmpty = false
			}
		}
	}

	status := CropActive
	if initialAreaEmpty && movedAreaEmpty {
		status = CropArchived
	}

	// Process //
	c.TrackChange(CropBatchDumped{
		UID:            c.UID,
		CropStatus:     status,
		Quantity:       quantity,
		UpdatedTrash:   updatedTrash,
		DumpedArea:     dumpedArea,
		DumpedAreaCode: dumpedAreaCode,
		DumpDate:       time.Now(),
		Notes:          notes,
	})

	return nil
}