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 }