{{ define "CreateRequest"}}
// {{ FormatCamel $.Model.Name }}CreateRequest contains information needed to create a new {{ FormatCamel $.Model.Name }}.
type {{ FormatCamel $.Model.Name }}CreateRequest struct {
    {{ range $fk, $f := .Model.Fields }}{{ if and ($f.ApiCreate) (ne $f.FieldName $.Model.PrimaryField) }}{{ $optional := (FieldTagHasOption $f "validate" "omitempty") }}
    {{ $f.FieldName }} {{ if and ($optional) (not $f.FieldIsPtr) }}*{{ end }}{{ $f.FieldType }}         `json:"{{ $f.ColumnName }}" {{ FieldTag $f "validate" }}`
    {{ end }}{{ end }}
}
{{ end }}
{{ define "UpdateRequest"}}
// {{ FormatCamel $.Model.Name }}UpdateRequest defines what information may be provided to modify an existing
// {{ FormatCamel $.Model.Name }}. All fields are optional so clients can send just the fields they want
// changed. It uses pointer fields so we can differentiate between a field that
// was not provided and a field that was provided as explicitly blank.
type {{ FormatCamel $.Model.Name }}UpdateRequest struct {
    {{ range $fk, $f := .Model.Fields }}{{ if $f.ApiUpdate }}
    {{ $f.FieldName }} {{ if and (ne $f.FieldName $.Model.PrimaryField) (not $f.FieldIsPtr) }}*{{ end }}{{ $f.FieldType }}         `json:"{{ $f.ColumnName }}" {{ if ne $f.FieldName $.Model.PrimaryField }}{{ FieldTagReplaceOrPrepend $f "validate" "required" "omitempty"  }}{{ else }}{{ FieldTagReplaceOrPrepend $f "validate" "omitempty" "required" }}{{ end }}`
    {{ end }}{{ end }}
}
{{ end }}
{{ define "FindRequest"}}
// {{ FormatCamel $.Model.Name }}FindRequest defines the possible options to search for {{ FormatCamelPluralTitleLower $.Model.Name }}. By default
// archived {{ FormatCamelLowerTitle $.Model.Name }} will be excluded from response.
type {{ FormatCamel $.Model.Name }}FindRequest struct {
    Where            *string `schema:"where"`
    Args             []interface{} `schema:"args"`
    Order            []string `schema:"order"`
    Limit            *uint `schema:"limit"`
    Offset           *uint `schema:"offset"`
    IncludedArchived bool
    {{ $hasArchived := (StringListHasValue $.Model.ColumnNames "archived_at") }}{{ if $hasArchived }}IncludedArchived bool `schema:"included-archived"`{{ end }}
}
{{ end }}
{{ define "Enums"}}
{{ range $fk, $f := .Model.Fields }}{{ if $f.DbColumn }}{{ if $f.DbColumn.IsEnum }}
// {{ $f.FieldType }} represents the {{ $f.ColumnName }} of {{ FormatCamelLowerTitle $.Model.Name }}.
type {{ $f.FieldType }} string

// {{ $f.FieldType }} values define the {{ $f.ColumnName }} field of {{ FormatCamelLowerTitle $.Model.Name }}.
const (
    {{ range $evk, $ev := $f.DbColumn.EnumValues }}
    // {{ $f.FieldType }}_{{ FormatCamel $ev }} defines the {{ $f.ColumnName }} of {{ $ev }} for {{ FormatCamelLowerTitle $.Model.Name }}.
    {{ $f.FieldType }}_{{ FormatCamel $ev }} {{ $f.FieldType }} = "{{ $ev }}"
    {{ end }}
)

// {{ $f.FieldType }}_Values provides list of valid {{ $f.FieldType }} values.
var {{ $f.FieldType }}_Values = []{{ $f.FieldType }}{
    {{ range $evk, $ev := $f.DbColumn.EnumValues }}
        {{ $f.FieldType }}_{{ FormatCamel $ev }},
    {{ end }}
}

// Scan supports reading the {{ $f.FieldType }} value from the database.
func (s *{{ $f.FieldType }}) Scan(value interface{}) error {
    asBytes, ok := value.([]byte)
    if !ok {
        return errors.New("Scan source is not []byte")
    }
    *s = {{ $f.FieldType }}(string(asBytes))
    return nil
}

// Value converts the {{ $f.FieldType }} value to be stored in the database.
func (s {{ $f.FieldType }}) Value() (driver.Value, error) {
    v := validator.New()

    errs := v.Var(s, "required,oneof={{ JoinStrings $f.DbColumn.EnumValues " " }}")
    if errs != nil {
        return nil, errs
    }

    return string(s), nil
}

// String converts the {{ $f.FieldType }} value to a string.
func (s {{ $f.FieldType }}) String() string {
    return string(s)
}
{{ end }}{{ end }}{{ end }}
{{ end }}