controller

package
v0.0.0-...-d813d14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 3, 2025 License: AGPL-3.0 Imports: 48 Imported by: 0

Documentation

Overview

controller/api_init.go

controller/api_invoices.go

controller/api_tokens.go

controller/letterhead_helpers.go

controller/letterhead_previews.go

controller/api_auth.go

controller/paths.go

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddFlash

func AddFlash(c echo.Context, kind, msg string) error

AddFlash stores a flash message in the session and preserves remember-me because SessionWriter.Save() reapplies cookie options on every save.

func ClearSession

func ClearSession(c echo.Context) error

ClearSession invalidates the current session cookie and clears all values. It treats invalid/old cookies as "nothing to clear".

func DeleteSessionValue

func DeleteSessionValue(c echo.Context, key string) error

DeleteSessionValue removes a key from the session and saves immediately.

func ErrInternal

func ErrInternal(err error) *appError

func ErrInvalid

func ErrInvalid(err error, public string) *appError

func ErrNotFound

func ErrNotFound(err error) *appError

Helpers to construct common app errors.

func FlashLoader

func FlashLoader(next echo.HandlerFunc) echo.HandlerFunc

FlashLoader pulls flash messages from the session (and clears them), stores them on the Echo context, and keeps remember-me intact by using SessionWriter.

func GenerateToken

func GenerateToken(nBytes int) (string, error)

func GetSessionValue

func GetSessionValue(c echo.Context, key string) string

GetSessionValue returns a string value from the session, or "" if not found.

func NewController

func NewController(s *model.Store) error

NewController wires routes, middleware, renderer, and starts the server.

func SetSessionValue

func SetSessionValue(c echo.Context, key, value string) error

SetSessionValue sets a key/value in the session and saves immediately.

func TemplateFromContext

func TemplateFromContext(c echo.Context) *model.LetterheadTemplate

TemplateFromContext retrieves the loaded LetterheadTemplate (if available) from the Echo context. This is set by the mustBeOwnerOfTemplate middleware.

Types

type APIContactInfo

type APIContactInfo struct {
	ID        uint      `json:"id" xml:"id,attr"`
	CreatedAt time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt time.Time `json:"updated_at" xml:"updated_at"`
	Type      string    `json:"type" xml:"type"`
	Label     string    `json:"label" xml:"label"`
	Value     string    `json:"value" xml:"value"`
}

type APICustomer

type APICustomer struct {
	ID                     uint             `json:"id" xml:"id,attr"`
	Name                   string           `json:"name" xml:"name"`
	CustomerNumber         string           `json:"customer_number,omitempty" xml:"customer_number,omitempty"`
	Address1               string           `json:"address1,omitempty" xml:"address1,omitempty"`
	Address2               string           `json:"address2,omitempty" xml:"address2,omitempty"`
	Zip                    string           `json:"zip,omitempty" xml:"zip,omitempty"`
	City                   string           `json:"city,omitempty" xml:"city,omitempty"`
	Country                string           `json:"country,omitempty" xml:"country,omitempty"`
	InvoiceEmail           string           `json:"invoice_email,omitempty" xml:"invoice_email,omitempty"`
	ContactInvoice         string           `json:"contact_invoice,omitempty" xml:"contact_invoice,omitempty"`
	SupplierNumber         string           `json:"supplier_number,omitempty" xml:"supplier_number,omitempty"`
	VATID                  string           `json:"vat_id,omitempty" xml:"vat_id,omitempty"`
	Background             string           `json:"background,omitempty" xml:"background,omitempty"`
	Notes                  []APINote        `json:"notes,omitempty" xml:"notes>note,omitempty"`
	ContactInfo            []APIContactInfo `json:"contact_infos,omitempty" xml:"contact_infos>contact_info,omitempty"`
	DefaultTaxRate         string           `json:"default_tax_rate,omitempty" xml:"default_tax_rate,omitempty"`
	InvoiceCurrency        string           `json:"invoice_currency,omitempty" xml:"invoice_currency,omitempty"`
	InvoiceTaxType         string           `json:"invoice_tax_type,omitempty" xml:"invoice_tax_type,omitempty"`
	InvoiceOpening         string           `json:"invoice_opening,omitempty" xml:"invoice_opening,omitempty"`
	InvoiceFooter          string           `json:"invoice_footer,omitempty" xml:"invoice_footer,omitempty"`
	InvoiceExemptionReason string           `json:"invoice_exemption_reason,omitempty" xml:"invoice_exemption_reason,omitempty"`

	CreatedAt time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt time.Time `json:"updated_at" xml:"updated_at"`
}

type APIError

type APIError struct {
	Code    string `json:"code" xml:"code"`
	Message string `json:"message" xml:"message"`
}

type APIInvoice

type APIInvoice struct {
	ID               uint                 `json:"id" xml:"id,attr"`
	Number           string               `json:"number" xml:"number"`
	Status           string               `json:"status" xml:"status"`
	Currency         string               `json:"currency" xml:"currency"`
	NetTotal         string               `json:"net_total" xml:"net_total"`
	GrossTotal       string               `json:"gross_total" xml:"gross_total"`
	Date             time.Time            `json:"date" xml:"date"`
	DueDate          time.Time            `json:"due_date" xml:"due_date"`
	CompanyID        uint                 `json:"company_id" xml:"company_id"`
	ContactInvoice   string               `json:"contact_invoice,omitempty" xml:"contact_invoice,omitempty"`
	Counter          uint                 `json:"counter,omitempty" xml:"counter,omitempty"`
	ExemptionReason  string               `json:"exemption_reason,omitempty" xml:"exemption_reason,omitempty"`
	Footer           string               `json:"footer,omitempty" xml:"footer,omitempty"`
	Opening          string               `json:"opening,omitempty" xml:"opening,omitempty"`
	OccurrenceDate   time.Time            `json:"occurrence_date,omitempty" xml:"occurrence_date,omitempty"`
	OrderNumber      string               `json:"order_number,omitempty" xml:"order_number,omitempty"`
	BuyerReference   string               `json:"buyer_reference,omitempty" xml:"buyer_reference,omitempty"`
	SupplierNumber   string               `json:"supplier_number,omitempty" xml:"supplier_number,omitempty"`
	TaxNumber        string               `json:"tax_number,omitempty" xml:"tax_number,omitempty"`
	TaxType          string               `json:"tax_type,omitempty" xml:"tax_type,omitempty"`
	TemplateID       *uint                `json:"template_id,omitempty" xml:"template_id,omitempty"`
	IssuedAt         *time.Time           `json:"issued_at,omitempty" xml:"issued_at,omitempty"`
	PaidAt           *time.Time           `json:"paid_at,omitempty" xml:"paid_at,omitempty"`
	VoidedAt         *time.Time           `json:"voided_at,omitempty" xml:"voided_at,omitempty"`
	CreatedAt        time.Time            `json:"created_at" xml:"created_at"`
	UpdatedAt        time.Time            `json:"updated_at" xml:"updated_at"`
	InvoicePositions []APIInvoicePosition `json:"invoice_positions,omitempty" xml:"invoice_positions>position,omitempty"`
	TaxAmounts       []APITaxAmount       `json:"tax_amounts,omitempty" xml:"tax_amounts>tax_amount,omitempty"`
}

---- DTOs for invoices ----

type APIInvoiceList

type APIInvoiceList struct {
	XMLName    struct{}     `json:"-" xml:"invoices"`
	Items      []APIInvoice `json:"items" xml:"invoice"`
	NextCursor string       `json:"next_cursor,omitempty" xml:"next_cursor,omitempty"`
}

type APIInvoicePosition

type APIInvoicePosition struct {
	ID         uint   `json:"id" xml:"id"`
	Position   int    `json:"position" xml:"position"`
	UnitCode   string `json:"unit_code" xml:"unit_code"`
	Text       string `json:"text" xml:"text"`
	Quantity   string `json:"quantity" xml:"quantity"`
	TaxRate    string `json:"tax_rate" xml:"tax_rate"`
	NetPrice   string `json:"net_price" xml:"net_price"`
	GrossPrice string `json:"gross_price" xml:"gross_price"`
	LineTotal  string `json:"line_total" xml:"line_total"`
}

type APILetterheadRegion

type APILetterheadRegion struct {
	ID       uint    `json:"id" xml:"id,attr"`
	Kind     string  `json:"kind" xml:"kind"`
	Page     int     `json:"page" xml:"page"`
	XCm      float64 `json:"x_cm" xml:"x_cm"`
	YCm      float64 `json:"y_cm" xml:"y_cm"`
	WidthCm  float64 `json:"width_cm" xml:"width_cm"`
	HeightCm float64 `json:"height_cm" xml:"height_cm"`

	HAlign      string  `json:"h_align,omitempty" xml:"h_align,omitempty"`
	VAlign      string  `json:"v_align,omitempty" xml:"v_align,omitempty"`
	FontName    string  `json:"font_name,omitempty" xml:"font_name,omitempty"`
	FontSizePt  float64 `json:"font_size_pt,omitempty" xml:"font_size_pt,omitempty"`
	LineSpacing float64 `json:"line_spacing,omitempty" xml:"line_spacing,omitempty"`

	HasPage2  bool    `json:"has_page2,omitempty" xml:"has_page2,omitempty"`
	X2Cm      float64 `json:"x2_cm,omitempty" xml:"x2_cm,omitempty"`
	Y2Cm      float64 `json:"y2_cm,omitempty" xml:"y2_cm,omitempty"`
	Width2Cm  float64 `json:"width2_cm,omitempty" xml:"width2_cm,omitempty"`
	Height2Cm float64 `json:"height2_cm,omitempty" xml:"height2_cm,omitempty"`

	CreatedAt time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt time.Time `json:"updated_at" xml:"updated_at"`
}

type APILetterheadTemplate

type APILetterheadTemplate struct {
	ID              uint    `json:"id" xml:"id,attr"`
	Name            string  `json:"name" xml:"name"`
	PageWidthCm     float64 `json:"page_width_cm" xml:"page_width_cm"`
	PageHeightCm    float64 `json:"page_height_cm" xml:"page_height_cm"`
	PDFPath         string  `json:"pdf_path,omitempty" xml:"pdf_path,omitempty"`
	PreviewPage1URL string  `json:"preview_page1_url,omitempty" xml:"preview_page1_url,omitempty"`
	PreviewPage2URL string  `json:"preview_page2_url,omitempty" xml:"preview_page2_url,omitempty"`

	FontNormal string `json:"font_normal,omitempty" xml:"font_normal,omitempty"`
	FontBold   string `json:"font_bold,omitempty" xml:"font_bold,omitempty"`
	FontItalic string `json:"font_italic,omitempty" xml:"font_italic,omitempty"`

	Regions []APILetterheadRegion `json:"regions,omitempty" xml:"regions>region,omitempty"`

	CreatedAt time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt time.Time `json:"updated_at" xml:"updated_at"`
}

type APINote

type APINote struct {
	ID         uint      `json:"id" xml:"id,attr"`
	CreatedAt  time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt  time.Time `json:"updated_at" xml:"updated_at"`
	AuthorID   uint      `json:"author_id" xml:"author_id"`
	ParentID   uint      `json:"parent_id" xml:"parent_id"`
	ParentType string    `json:"parent_type" xml:"parent_type"`
	Title      string    `json:"title" xml:"title"`
	Body       string    `json:"body" xml:"body"`
	Tags       string    `json:"tags" xml:"tags"`
	EditedAt   time.Time `json:"edited_at" xml:"edited_at"`
}

type APIPerson

type APIPerson struct {
	ID           uint             `json:"id" xml:"id,attr"`
	Name         string           `json:"name" xml:"name"`
	Position     string           `json:"position,omitempty" xml:"position,omitempty"`
	Email        string           `json:"email,omitempty" xml:"email,omitempty"`
	CompanyID    int              `json:"company_id,omitempty" xml:"company_id,omitempty"`
	ContactInfos []APIContactInfo `json:"contact_infos,omitempty" xml:"contact_infos>contact_info,omitempty"`
	Notes        []APINote        `json:"notes,omitempty" xml:"notes>note,omitempty"`
	CreatedAt    time.Time        `json:"created_at" xml:"created_at"`
	UpdatedAt    time.Time        `json:"updated_at" xml:"updated_at"`
}

type APISettings

type APISettings struct {
	CompanyName           string `xml:"company_name"`
	InvoiceContact        string `xml:"invoice_contact"`
	InvoiceEMail          string `xml:"invoice_email"`
	ZIP                   string `xml:"zip"`
	Address1              string `xml:"address1"`
	Address2              string `xml:"address2"`
	City                  string `xml:"city"`
	CountryCode           string `xml:"country_code"`
	VATID                 string `xml:"vat_id"`
	TAXNumber             string `xml:"tax_number"`
	InvoiceNumberTemplate string `xml:"invoice_number_template"`
	UseLocalCounter       bool   `xml:"use_local_counter"`
	BankIBAN              string `xml:"bank_iban"`
	BankName              string `xml:"bank_name"`
	BankBIC               string `xml:"bank_bic"`
	CustomerNumberPrefix  string `xml:"customer_number_prefix"`
	CustomerNumberWidth   int    `xml:"customer_number_width"`
	CustomerNumberCounter int64  `xml:"customer_number_counter"`
}

type APITaxAmount

type APITaxAmount struct {
	Rate   string `json:"rate" xml:"rate"`
	Amount string `json:"amount" xml:"amount"`
}

type CookieCfg

type CookieCfg struct {
	IsProd       bool
	ShareSubdoms bool
	ParentDomain string
}

CookieCfg controls how the session cookie is scoped and secured. NOTE: Options are applied centrally by SessionWriter.Save() via applySessionOptionsFromPersist. This file only sets the "persist" flag (remember me) where needed.

type ExportCustomers

type ExportCustomers struct {
	XMLName   xml.Name      `xml:"customers"`
	Version   string        `xml:"version,attr,omitempty"`
	Customers []APICustomer `xml:"customer"`
}

type ExportInvoices

type ExportInvoices struct {
	XMLName  xml.Name     `xml:"invoices"`
	Version  string       `xml:"version,attr,omitempty"`
	Invoices []APIInvoice `xml:"invoice"`
}

type ExportLetterheadTemplates

type ExportLetterheadTemplates struct {
	XMLName   xml.Name                `xml:"letterhead_templates"`
	Version   string                  `xml:"version,attr,omitempty"`
	Templates []APILetterheadTemplate `xml:"template"`
}

Root-Element for XML export/import of letterhead templates

type ExportPersons

type ExportPersons struct {
	XMLName xml.Name    `xml:"persons"`
	Version string      `xml:"version,attr,omitempty"`
	Persons []APIPerson `xml:"person"`
}

Root-Element für persons.xml

type ExportSettings

type ExportSettings struct {
	XMLName xml.Name    `xml:"settings"`
	Version string      `xml:"version,attr,omitempty"`
	Setting APISettings `xml:"setting"`
}

type FileRow

type FileRow struct {
	Name      string
	Size      int64
	SizeHuman string
	ModTime   time.Time
	IsDir     bool
}

type Flash

type Flash struct {
	Kind    string // "success" | "error" | "warning" | "info"
	Message string
}

type FontFile

type FontFile struct {
	Filename string `json:"filename"` // basename only, e.g. "Roboto-Regular.ttf"
}

FontFile represents a single available font file within a user's asset directory.

type ImportedPosition

type ImportedPosition struct {
	Text     string   // required
	Quantity float64  // required
	NetPrice float64  // required
	TaxRate  *float64 // optional (nil => use company default)
	Unit     string   // optional ("" => "C62")
}

Public DTO used by all parsers

func ParsePositions

func ParsePositions(r io.Reader, ext string) ([]ImportedPosition, error)

Convenience: one entry point that auto-detects by file extension or content. - ext can be "", ".csv", ".xml" (case-insensitive). If empty, content sniffing is used.

type LetterheadOption

type LetterheadOption struct {
	Name      string // filename only, e.g. "briefbogen.pdf"
	RelPath   string // path relative to the user assets dir, e.g. "branding/briefbogen.pdf"
	ModTime   time.Time
	SizeHuman string
}

LetterheadOption is used to render selectable PDFs in the form.

type ProfilePageData

type ProfilePageData struct {
	CSRFToken string
	User      *model.User
	Tokens    []model.APIToken
	NewToken  string // set only when a new plaintext token was just created
}

controller/views.go ProfilePageData is the template view model for the profile page.

type SessionWriter

type SessionWriter struct {
	// contains filtered or unexported fields
}

SessionWriter is a thin wrapper around gorilla/sessions that ensures cookie options (MaxAge, Secure, Domain, SameSite) are applied consistently before saving. This avoids accidentally overwriting a persistent "remember me" cookie with a temporary one when saving flash messages or other values.

func LoadSession

func LoadSession(c echo.Context) (*SessionWriter, error)

LoadSession retrieves the session named "session" from the Echo context. It returns a SessionWriter that you should use to read/write values and Save().

func (*SessionWriter) AddFlash

func (sw *SessionWriter) AddFlash(v any)

AddFlash appends a flash message to the session. It does not save automatically; call sw.Save() afterwards.

func (*SessionWriter) Save

func (sw *SessionWriter) Save() error

Save persists the session back to the client. It automatically reapplies cookie options based on the "persist" flag stored in the session.

func (*SessionWriter) Values

func (sw *SessionWriter) Values() map[any]any

Values gives access to the session data map. Use it to set or read keys:

sw.Values()["uid"] = user.ID

type Template

type Template struct {
	// contains filtered or unexported fields
}

Template implements Echo's renderer interface.

func (*Template) Render

func (t *Template) Render(w io.Writer, name string, data any, _ echo.Context) error

Render satisfies Echo's renderer interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL