kereru-forms/backend/internal/api/mapping.go

203 lines
5.5 KiB
Go
Raw Normal View History

package api
import (
"encoding/json"
"github.com/google/uuid"
"kereru.forms/internal/database"
)
func toAPIForm(f *database.Form) Form {
questions := make([]Question, 0, len(f.Questions))
for _, q := range f.Questions {
questions = append(questions, toAPIQuestion(q))
}
return Form{
Id: uuid.MustParse(f.ID),
FormGroupId: uuid.MustParse(f.FormGroupID),
Version: f.Version,
Title: f.Title,
Description: f.Description,
Introduction: f.Introduction,
IsActive: f.IsActive,
RequiresAccessCode: f.RequiresAccessCode,
SignatureRequired: boolPtrIfSet(f.SignatureRequired, true),
ExternalReferenceRequired: boolPtrIfSet(f.ExternalReferenceRequired, true),
ExternalReferenceLabel: f.ExternalReferenceLabel,
LogoUrl: f.LogoURL,
PdfUrl: f.PDFURL,
CompanyName: f.CompanyName,
ContactEmail: f.ContactEmail,
ContactPhone: f.ContactPhone,
ContactUrl: f.ContactURL,
CreatedAt: f.CreatedAt,
UpdatedAt: f.UpdatedAt,
Questions: questions,
}
}
func toAPIQuestion(q database.Question) Question {
out := Question{
Id: uuid.MustParse(q.ID),
Key: q.Key,
Label: q.Label,
Description: q.Description,
Type: QuestionType(q.Type),
Required: q.Required,
Placeholder: q.Placeholder,
Multiline: boolPtrIfSet(q.Multiline, QuestionType(q.Type) == Text),
}
if q.MinValue != nil {
v := float32(*q.MinValue)
out.MinValue = &v
}
if q.MaxValue != nil {
v := float32(*q.MaxValue)
out.MaxValue = &v
}
if len(q.Options) > 0 {
opts := make([]QuestionOption, 0, len(q.Options))
for _, o := range q.Options {
opts = append(opts, QuestionOption{Value: o.Value, Label: o.Label})
}
out.Options = &opts
}
return out
}
func boolPtrIfSet(v bool, include bool) *bool {
if !include && !v {
return nil
}
b := v
return &b
}
func toAPIFormSummary(f database.FormSummary) FormSummary {
return FormSummary{
Id: uuid.MustParse(f.ID),
FormGroupId: uuid.MustParse(f.FormGroupID),
Version: f.Version,
Title: f.Title,
Description: f.Description,
LogoUrl: f.LogoURL,
PdfUrl: f.PDFURL,
ExternalReferenceRequired: boolPtrIfSet(f.ExternalReferenceRequired, true),
ExternalReferenceLabel: f.ExternalReferenceLabel,
IsActive: f.IsActive,
QuestionCount: f.QuestionCount,
CreatedAt: f.CreatedAt,
UpdatedAt: f.UpdatedAt,
}
}
func toAPIAnswerRecord(a database.Answer) AnswerRecord {
var value interface{}
_ = json.Unmarshal(a.Value, &value)
return AnswerRecord{
QuestionId: uuid.MustParse(a.QuestionID),
QuestionKey: a.QuestionKey,
Value: value,
}
}
func toAPISubmission(s *database.Submission) Submission {
answers := make([]AnswerRecord, 0, len(s.Answers))
for _, a := range s.Answers {
answers = append(answers, toAPIAnswerRecord(a))
}
out := Submission{
Id: uuid.MustParse(s.ID),
FormId: uuid.MustParse(s.FormID),
FormVersion: s.FormVersion,
UserId: s.UserID,
UserIdType: UserIdType(s.UserIDType),
SubmittedAt: s.SubmittedAt,
Answers: answers,
ExternalReference: s.ExternalReference,
OfflinePdfName: s.OfflinePDFName,
}
if s.Signature != nil {
out.Signature = &Signature{
Type: SignatureType(s.Signature.Type),
DataUrl: s.Signature.DataURL,
Name: s.Signature.Name,
Title: s.Signature.Title,
SignedAt: s.Signature.SignedAt,
}
}
if hasTracking(s) {
out.Tracking = &Tracking{
IpAddress: s.IPAddress,
UserAgent: s.UserAgent,
Locale: s.Locale,
Timezone: s.Timezone,
Place: s.Place,
Referer: s.Referer,
}
}
return out
}
func hasTracking(s *database.Submission) bool {
return s.IPAddress != nil || s.UserAgent != nil || s.Locale != nil ||
s.Timezone != nil || s.Place != nil || s.Referer != nil
}
func toAPISubmissionSummary(s database.SubmissionSummary) SubmissionSummary {
return SubmissionSummary{
Id: uuid.MustParse(s.ID),
FormId: uuid.MustParse(s.FormID),
FormVersion: s.FormVersion,
UserId: s.UserID,
UserIdType: UserIdType(s.UserIDType),
ExternalReference: s.ExternalReference,
SubmittedAt: s.SubmittedAt,
}
}
func toAPIAccessCode(c database.AccessCode) AccessCode {
return AccessCode{
Id: uuid.MustParse(c.ID),
FormId: uuid.MustParse(c.FormID),
Code: c.Code,
Used: c.Used,
UsedAt: c.UsedAt,
CreatedAt: c.CreatedAt,
}
}
func questionInputsToRecords(inputs []QuestionInput) []database.Question {
out := make([]database.Question, 0, len(inputs))
for i, q := range inputs {
rec := database.Question{
Position: i,
Key: q.Key,
Label: q.Label,
Description: q.Description,
Type: string(q.Type),
Required: q.Required,
Placeholder: q.Placeholder,
}
if q.MinValue != nil {
v := float64(*q.MinValue)
rec.MinValue = &v
}
if q.MaxValue != nil {
v := float64(*q.MaxValue)
rec.MaxValue = &v
}
if q.Multiline != nil {
rec.Multiline = *q.Multiline
}
if q.Options != nil {
for _, o := range *q.Options {
rec.Options = append(rec.Options, database.QuestionOption{Value: o.Value, Label: o.Label})
}
}
out = append(out, rec)
}
return out
}