mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-03 02:55:54 +02:00
23539c10c9
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/oapi-codegen/nullable"
|
|
"github.com/phishingclub/phishingclub/validate"
|
|
"github.com/phishingclub/phishingclub/vo"
|
|
)
|
|
|
|
// ReportTemplate is a report template
|
|
type ReportTemplate struct {
|
|
ID nullable.Nullable[uuid.UUID] `json:"id"`
|
|
CreatedAt *time.Time `json:"createdAt"`
|
|
UpdatedAt *time.Time `json:"updatedAt"`
|
|
CompanyID nullable.Nullable[uuid.UUID] `json:"companyID"`
|
|
Content nullable.Nullable[vo.OptionalString1MB] `json:"content"`
|
|
|
|
Company *Company `json:"-"`
|
|
}
|
|
|
|
// Validate checks if the report template has a valid state
|
|
func (r *ReportTemplate) Validate() error {
|
|
if err := validate.NullableFieldRequired("content", r.Content); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ToDBMap converts updatable fields to a map
|
|
func (r *ReportTemplate) ToDBMap() map[string]any {
|
|
m := map[string]any{}
|
|
if r.Content.IsSpecified() {
|
|
m["content"] = nil
|
|
if content, err := r.Content.Get(); err == nil {
|
|
m["content"] = content.String()
|
|
}
|
|
}
|
|
if r.CompanyID.IsSpecified() {
|
|
if r.CompanyID.IsNull() {
|
|
m["company_id"] = nil
|
|
} else {
|
|
m["company_id"] = r.CompanyID.MustGet()
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
|
|
// ReportData is the data context passed to a report HTML template for rendering.
|
|
// Date fields are pre-formatted as "YYYY-MM-DD" strings (empty when not set).
|
|
type ReportData struct {
|
|
// Campaign identity
|
|
CampaignName string
|
|
CompanyName string
|
|
ReportDate string
|
|
CampaignStartDate string
|
|
CampaignEndDate string
|
|
CampaignClosedAt string
|
|
|
|
// Totals
|
|
TotalTargets int64
|
|
EmailsSent int64
|
|
EmailsOpened int64
|
|
|
|
// Core outcome counts
|
|
ResultClicked int64
|
|
ResultSubmitted int64
|
|
ResultReported int64
|
|
|
|
// Formatted percentages (e.g. "45.2") — ready to use directly in templates
|
|
ResultClickedPercent string
|
|
ResultSubmittedPercent string
|
|
ResultReportedPercent string
|
|
|
|
// Float percentages for custom formatting with {{printf "%.1f" .ClickRate}}
|
|
SentRate float64
|
|
OpenRate float64
|
|
ClickRate float64
|
|
SubmitRate float64
|
|
ReportRate float64
|
|
|
|
// Relative conversion rates — funnel step-to-step (formatted strings like "45.2")
|
|
OpenedOfSent string // EmailsOpened / EmailsSent
|
|
ClickedOfOpened string // ResultClicked / EmailsOpened
|
|
SubmittedOfClicked string // ResultSubmitted / ResultClicked
|
|
|
|
// Per-recipient detail — empty for anonymous or anonymized campaigns
|
|
Recipients []ReportRecipient
|
|
}
|
|
|
|
// ReportRecipient holds per-recipient result data for the recipient detail table
|
|
type ReportRecipient struct {
|
|
FirstName string
|
|
LastName string
|
|
Email string
|
|
Department string
|
|
Position string
|
|
ClickedLink bool
|
|
SubmittedData bool
|
|
Reported bool
|
|
}
|