Documentation
¶
Index ¶
- Variables
- type AutomatedReminderResult
- type AutomatedReminderService
- func (s *AutomatedReminderService) CreateRule(ctx context.Context, tenantID, schemaName string, ...) (*ReminderRule, error)
- func (s *AutomatedReminderService) DeleteRule(ctx context.Context, tenantID, schemaName, ruleID string) error
- func (s *AutomatedReminderService) GetRule(ctx context.Context, tenantID, schemaName, ruleID string) (*ReminderRule, error)
- func (s *AutomatedReminderService) ListRules(ctx context.Context, tenantID, schemaName string) ([]ReminderRule, error)
- func (s *AutomatedReminderService) ProcessRemindersForTenant(ctx context.Context, tenantID, schemaName, companyName string) ([]AutomatedReminderResult, error)
- func (s *AutomatedReminderService) UpdateRule(ctx context.Context, tenantID, schemaName, ruleID string, ...) (*ReminderRule, error)
- type BulkReminderResult
- type CreateInvoiceLineRequest
- type CreateInvoiceRequest
- type CreateReminderRuleRequest
- type GORMRepository
- func (r *GORMRepository) ApplyPayment(ctx context.Context, schemaName, tenantID, invoiceID string, ...) error
- func (r *GORMRepository) Create(ctx context.Context, schemaName string, invoice *Invoice) error
- func (r *GORMRepository) GenerateNumber(ctx context.Context, schemaName, tenantID string, invoiceType InvoiceType) (string, error)
- func (r *GORMRepository) GetByID(ctx context.Context, schemaName, tenantID, invoiceID string) (*Invoice, error)
- func (r *GORMRepository) List(ctx context.Context, schemaName, tenantID string, filter *InvoiceFilter) ([]Invoice, error)
- func (r *GORMRepository) UpdateOverdueStatus(ctx context.Context, schemaName, tenantID string) (int, error)
- func (r *GORMRepository) UpdatePayment(ctx context.Context, schemaName, tenantID, invoiceID string, ...) error
- func (r *GORMRepository) UpdateStatus(ctx context.Context, schemaName, tenantID, invoiceID string, ...) error
- func (r *GORMRepository) VoidInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) error
- type ImportEInvoiceRequest
- type ImportInvoicesRequest
- type ImportInvoicesResult
- type ImportInvoicesRowError
- type InterestCalculationResult
- type InterestGORMRepository
- func (r *InterestGORMRepository) CreateInterest(ctx context.Context, schemaName string, interest *InvoiceInterest) error
- func (r *InterestGORMRepository) GetInvoiceForInterest(ctx context.Context, schemaName, tenantID, invoiceID string) (*interestInvoice, error)
- func (r *InterestGORMRepository) GetLatestInterest(ctx context.Context, schemaName, invoiceID string) (*InvoiceInterest, error)
- func (r *InterestGORMRepository) ListInterestHistory(ctx context.Context, schemaName, invoiceID string) ([]InvoiceInterest, error)
- func (r *InterestGORMRepository) ListOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]interestInvoice, error)
- type InterestRepository
- type InterestService
- func (s *InterestService) CalculateInterest(ctx context.Context, schemaName, tenantID, invoiceID string, ...) (*InterestCalculationResult, error)
- func (s *InterestService) CalculateInterestForOverdueInvoices(ctx context.Context, schemaName, tenantID string, interestRate float64) ([]InterestCalculationResult, error)
- func (s *InterestService) GetLatestInterest(ctx context.Context, schemaName, invoiceID string) (*InvoiceInterest, error)
- func (s *InterestService) ListInterestHistory(ctx context.Context, schemaName, invoiceID string) ([]InvoiceInterest, error)
- func (s *InterestService) SaveInterestCalculation(ctx context.Context, schemaName string, result *InterestCalculationResult) (*InvoiceInterest, error)
- type InterestSettings
- type Invoice
- type InvoiceFilter
- type InvoiceForReminder
- type InvoiceInterest
- type InvoiceLine
- type InvoiceStatus
- type InvoiceType
- type MockReminderRepository
- func (m *MockReminderRepository) AddMockOverdueInvoice(id, invoiceNumber, contactID, contactName, contactEmail, currency string, ...)
- func (m *MockReminderRepository) CreateReminder(ctx context.Context, schemaName string, reminder *PaymentReminder) error
- func (m *MockReminderRepository) GetOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]OverdueInvoice, error)
- func (m *MockReminderRepository) GetReminderCount(ctx context.Context, schemaName, tenantID, invoiceID string) (int, *time.Time, error)
- func (m *MockReminderRepository) GetRemindersByInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) ([]PaymentReminder, error)
- func (m *MockReminderRepository) UpdateReminderStatus(ctx context.Context, schemaName, reminderID string, status ReminderStatus, ...) error
- type NotFoundError
- type OverdueInvoice
- type OverdueInvoicesSummary
- type PaymentReminder
- type ReminderGORMRepository
- func (r *ReminderGORMRepository) CreateReminder(ctx context.Context, schemaName string, reminder *PaymentReminder) error
- func (r *ReminderGORMRepository) GetOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]OverdueInvoice, error)
- func (r *ReminderGORMRepository) GetReminderCount(ctx context.Context, schemaName, tenantID, invoiceID string) (int, *time.Time, error)
- func (r *ReminderGORMRepository) GetRemindersByInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) ([]PaymentReminder, error)
- func (r *ReminderGORMRepository) UpdateReminderStatus(ctx context.Context, schemaName, reminderID string, status ReminderStatus, ...) error
- type ReminderRepository
- type ReminderResult
- type ReminderRule
- type ReminderRuleGORMRepository
- func (r *ReminderRuleGORMRepository) CreateRule(ctx context.Context, schemaName string, rule *ReminderRule) error
- func (r *ReminderRuleGORMRepository) DeleteRule(ctx context.Context, schemaName, tenantID, ruleID string) error
- func (r *ReminderRuleGORMRepository) GetInvoicesForRule(ctx context.Context, schemaName, tenantID string, rule *ReminderRule, ...) ([]InvoiceForReminder, error)
- func (r *ReminderRuleGORMRepository) GetRule(ctx context.Context, schemaName, tenantID, ruleID string) (*ReminderRule, error)
- func (r *ReminderRuleGORMRepository) HasReminderBeenSent(ctx context.Context, schemaName, tenantID, invoiceID, ruleID string) (bool, error)
- func (r *ReminderRuleGORMRepository) ListActiveRules(ctx context.Context, schemaName, tenantID string) ([]ReminderRule, error)
- func (r *ReminderRuleGORMRepository) ListRules(ctx context.Context, schemaName, tenantID string) ([]ReminderRule, error)
- func (r *ReminderRuleGORMRepository) RecordReminderSent(ctx context.Context, schemaName string, reminder *PaymentReminder) error
- func (r *ReminderRuleGORMRepository) UpdateRule(ctx context.Context, schemaName string, rule *ReminderRule) error
- type ReminderRuleRepository
- type ReminderService
- func (s *ReminderService) GetOverdueInvoicesSummary(ctx context.Context, tenantID, schemaName string) (*OverdueInvoicesSummary, error)
- func (s *ReminderService) GetReminderHistory(ctx context.Context, tenantID, schemaName, invoiceID string) ([]PaymentReminder, error)
- func (s *ReminderService) SendBulkReminders(ctx context.Context, tenantID, schemaName string, ...) (*BulkReminderResult, error)
- func (s *ReminderService) SendReminder(ctx context.Context, tenantID, schemaName string, req *SendReminderRequest, ...) (*ReminderResult, error)
- type ReminderStatus
- type Repository
- type SendBulkRemindersRequest
- type SendReminderRequest
- type Service
- func (s *Service) Create(ctx context.Context, tenantID, schemaName string, req *CreateInvoiceRequest) (*Invoice, error)
- func (s *Service) GetByID(ctx context.Context, tenantID, schemaName, invoiceID string) (*Invoice, error)
- func (s *Service) ImportCSV(ctx context.Context, tenantID, schemaName string, ...) (*ImportInvoicesResult, error)
- func (s *Service) ImportEInvoiceXML(ctx context.Context, tenantID, schemaName string, ...) (*ImportInvoicesResult, error)
- func (s *Service) List(ctx context.Context, tenantID, schemaName string, filter *InvoiceFilter) ([]Invoice, error)
- func (s *Service) RecordPayment(ctx context.Context, tenantID, schemaName, invoiceID string, ...) error
- func (s *Service) ResolveInvoiceIDByNumber(ctx context.Context, tenantID, schemaName, invoiceNumber string) (string, error)
- func (s *Service) Send(ctx context.Context, tenantID, schemaName, invoiceID string) error
- func (s *Service) UpdateOverdueStatus(ctx context.Context, tenantID, schemaName string) (int, error)
- func (s *Service) Void(ctx context.Context, tenantID, schemaName, invoiceID string) error
- func (s *Service) WithRepository(repo Repository) *Service
- type TriggerType
- type UpdateInterestSettingsRequest
- type UpdateReminderRuleRequest
- type VATTreatment
- type ValidationError
Constants ¶
This section is empty.
Variables ¶
var ( ErrRuleNameRequired = &ValidationError{Field: "name", Message: "rule name is required"} ErrTriggerTypeRequired = &ValidationError{Field: "trigger_type", Message: "trigger type is required"} ErrInvalidTriggerType = &ValidationError{Field: "trigger_type", Message: "invalid trigger type"} ErrInvalidDaysOffset = &ValidationError{Field: "days_offset", Message: "days offset cannot be negative"} ErrRuleNotFound = &NotFoundError{Entity: "reminder rule"} )
Errors
var ErrInvoiceNotFound = fmt.Errorf("invoice not found")
ErrInvoiceNotFound is returned when an invoice is not found
Functions ¶
This section is empty.
Types ¶
type AutomatedReminderResult ¶
type AutomatedReminderResult struct {
TenantID string `json:"tenant_id"`
RuleID string `json:"rule_id"`
RuleName string `json:"rule_name"`
InvoicesFound int `json:"invoices_found"`
RemindersSent int `json:"reminders_sent"`
Skipped int `json:"skipped"`
Failed int `json:"failed"`
Errors []string `json:"errors,omitempty"`
RunAt time.Time `json:"run_at"`
}
AutomatedReminderResult represents the result of an automated reminder run
type AutomatedReminderService ¶
type AutomatedReminderService struct {
// contains filtered or unexported fields
}
AutomatedReminderService handles scheduled reminder processing
func NewAutomatedReminderService ¶
func NewAutomatedReminderService(db *pgxpool.Pool, emailService *email.Service) *AutomatedReminderService
NewAutomatedReminderService creates a new automated reminder service
func NewAutomatedReminderServiceWithRepository ¶
func NewAutomatedReminderServiceWithRepository(ruleRepo ReminderRuleRepository, emailService *email.Service) *AutomatedReminderService
NewAutomatedReminderServiceWithRepository creates a service with custom repository (for testing)
func (*AutomatedReminderService) CreateRule ¶
func (s *AutomatedReminderService) CreateRule(ctx context.Context, tenantID, schemaName string, req *CreateReminderRuleRequest) (*ReminderRule, error)
CreateRule creates a new reminder rule
func (*AutomatedReminderService) DeleteRule ¶
func (s *AutomatedReminderService) DeleteRule(ctx context.Context, tenantID, schemaName, ruleID string) error
DeleteRule deletes a rule
func (*AutomatedReminderService) GetRule ¶
func (s *AutomatedReminderService) GetRule(ctx context.Context, tenantID, schemaName, ruleID string) (*ReminderRule, error)
GetRule returns a single rule
func (*AutomatedReminderService) ListRules ¶
func (s *AutomatedReminderService) ListRules(ctx context.Context, tenantID, schemaName string) ([]ReminderRule, error)
ListRules returns all reminder rules for a tenant
func (*AutomatedReminderService) ProcessRemindersForTenant ¶
func (s *AutomatedReminderService) ProcessRemindersForTenant(ctx context.Context, tenantID, schemaName, companyName string) ([]AutomatedReminderResult, error)
ProcessRemindersForTenant processes all reminder rules for a tenant
func (*AutomatedReminderService) UpdateRule ¶
func (s *AutomatedReminderService) UpdateRule(ctx context.Context, tenantID, schemaName, ruleID string, req *UpdateReminderRuleRequest) (*ReminderRule, error)
UpdateRule updates an existing rule
type BulkReminderResult ¶
type BulkReminderResult struct {
TotalRequested int `json:"total_requested"`
Successful int `json:"successful"`
Failed int `json:"failed"`
Results []ReminderResult `json:"results"`
}
BulkReminderResult represents the results of sending multiple reminders
type CreateInvoiceLineRequest ¶
type CreateInvoiceLineRequest struct {
Description string `json:"description"`
Quantity decimal.Decimal `json:"quantity"`
Unit string `json:"unit,omitempty"`
UnitPrice decimal.Decimal `json:"unit_price"`
DiscountPercent decimal.Decimal `json:"discount_percent,omitempty"`
VATRate decimal.Decimal `json:"vat_rate"`
VATTreatment VATTreatment `json:"vat_treatment,omitempty"`
AccountID *string `json:"account_id,omitempty"`
ProductID *string `json:"product_id,omitempty"`
}
CreateInvoiceLineRequest is a line in the create invoice request
type CreateInvoiceRequest ¶
type CreateInvoiceRequest struct {
InvoiceType InvoiceType `json:"invoice_type"`
ContactID string `json:"contact_id"`
IssueDate time.Time `json:"issue_date"`
DueDate time.Time `json:"due_date"`
Currency string `json:"currency,omitempty"`
ExchangeRate decimal.Decimal `json:"exchange_rate,omitempty"`
Reference string `json:"reference,omitempty"`
Notes string `json:"notes,omitempty"`
Lines []CreateInvoiceLineRequest `json:"lines"`
UserID string `json:"-"`
}
CreateInvoiceRequest is the request to create an invoice
type CreateReminderRuleRequest ¶
type CreateReminderRuleRequest struct {
Name string `json:"name"`
TriggerType TriggerType `json:"trigger_type"`
DaysOffset int `json:"days_offset"`
EmailTemplateType string `json:"email_template_type,omitempty"`
IsActive bool `json:"is_active"`
}
CreateReminderRuleRequest is the request to create a reminder rule
func (*CreateReminderRuleRequest) Validate ¶
func (r *CreateReminderRuleRequest) Validate() error
Validate validates the create rule request
type GORMRepository ¶
type GORMRepository struct {
// contains filtered or unexported fields
}
GORMRepository implements Repository using GORM
func NewGORMRepository ¶
func NewGORMRepository(db *gorm.DB) *GORMRepository
NewGORMRepository creates a new GORM invoicing repository
func (*GORMRepository) ApplyPayment ¶
func (r *GORMRepository) ApplyPayment(ctx context.Context, schemaName, tenantID, invoiceID string, amount decimal.Decimal) error
ApplyPayment atomically applies a payment delta while holding the invoice row lock. This prevents concurrent allocations or reversals from losing a previously recorded payment amount.
func (*GORMRepository) GenerateNumber ¶
func (r *GORMRepository) GenerateNumber(ctx context.Context, schemaName, tenantID string, invoiceType InvoiceType) (string, error)
GenerateNumber generates a new invoice number
func (*GORMRepository) GetByID ¶
func (r *GORMRepository) GetByID(ctx context.Context, schemaName, tenantID, invoiceID string) (*Invoice, error)
GetByID retrieves an invoice by ID with its lines
func (*GORMRepository) List ¶
func (r *GORMRepository) List(ctx context.Context, schemaName, tenantID string, filter *InvoiceFilter) ([]Invoice, error)
List retrieves invoices with optional filtering
func (*GORMRepository) UpdateOverdueStatus ¶
func (r *GORMRepository) UpdateOverdueStatus(ctx context.Context, schemaName, tenantID string) (int, error)
UpdateOverdueStatus updates the status of overdue invoices
func (*GORMRepository) UpdatePayment ¶
func (r *GORMRepository) UpdatePayment(ctx context.Context, schemaName, tenantID, invoiceID string, amountPaid decimal.Decimal, status InvoiceStatus) error
UpdatePayment updates the amount paid and status of an invoice
func (*GORMRepository) UpdateStatus ¶
func (r *GORMRepository) UpdateStatus(ctx context.Context, schemaName, tenantID, invoiceID string, status InvoiceStatus) error
UpdateStatus updates the status of an invoice
func (*GORMRepository) VoidInvoice ¶
func (r *GORMRepository) VoidInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) error
VoidInvoice atomically voids an unpaid invoice. The payment and status predicates are part of the update so a concurrent payment cannot be followed by a stale void operation.
type ImportEInvoiceRequest ¶
type ImportEInvoiceRequest struct {
XMLContent string `json:"xml_content"`
FileName string `json:"file_name,omitempty"`
InvoiceType InvoiceType `json:"invoice_type,omitempty"`
UserID string `json:"-"`
}
ImportEInvoiceRequest contains Estonian e-invoice XML for manual invoice import.
type ImportInvoicesRequest ¶
type ImportInvoicesRequest struct {
CSVContent string `json:"csv_content"`
FileName string `json:"file_name,omitempty"`
UserID string `json:"-"`
}
ImportInvoicesRequest contains CSV payload for bulk invoice import.
type ImportInvoicesResult ¶
type ImportInvoicesResult struct {
FileName string `json:"file_name,omitempty"`
RowsProcessed int `json:"rows_processed"`
InvoicesCreated int `json:"invoices_created"`
LinesImported int `json:"lines_imported"`
RowsSkipped int `json:"rows_skipped"`
Errors []ImportInvoicesRowError `json:"errors,omitempty"`
}
ImportInvoicesResult summarizes a bulk invoice import.
type ImportInvoicesRowError ¶
type ImportInvoicesRowError struct {
Row int `json:"row"`
InvoiceNumber string `json:"invoice_number,omitempty"`
Message string `json:"message"`
}
ImportInvoicesRowError describes a row-level import failure.
type InterestCalculationResult ¶
type InterestCalculationResult struct {
InvoiceID string `json:"invoice_id"`
InvoiceNumber string `json:"invoice_number"`
DueDate time.Time `json:"due_date"`
DaysOverdue int `json:"days_overdue"`
OutstandingAmount decimal.Decimal `json:"outstanding_amount"`
InterestRate decimal.Decimal `json:"interest_rate"`
DailyInterest decimal.Decimal `json:"daily_interest"`
TotalInterest decimal.Decimal `json:"total_interest"`
TotalWithInterest decimal.Decimal `json:"total_with_interest"`
CalculatedAt time.Time `json:"calculated_at"`
Currency string `json:"currency"`
}
InterestCalculationResult represents the result of an interest calculation
type InterestGORMRepository ¶
type InterestGORMRepository struct {
// contains filtered or unexported fields
}
InterestGORMRepository stores interest data through the shared ORM layer.
func NewInterestGORMRepository ¶
func NewInterestGORMRepository(db *gorm.DB) *InterestGORMRepository
func NewInterestRepository ¶
func NewInterestRepository(db *pgxpool.Pool) *InterestGORMRepository
func (*InterestGORMRepository) CreateInterest ¶
func (r *InterestGORMRepository) CreateInterest(ctx context.Context, schemaName string, interest *InvoiceInterest) error
func (*InterestGORMRepository) GetInvoiceForInterest ¶
func (r *InterestGORMRepository) GetInvoiceForInterest(ctx context.Context, schemaName, tenantID, invoiceID string) (*interestInvoice, error)
func (*InterestGORMRepository) GetLatestInterest ¶
func (r *InterestGORMRepository) GetLatestInterest(ctx context.Context, schemaName, invoiceID string) (*InvoiceInterest, error)
func (*InterestGORMRepository) ListInterestHistory ¶
func (r *InterestGORMRepository) ListInterestHistory(ctx context.Context, schemaName, invoiceID string) ([]InvoiceInterest, error)
func (*InterestGORMRepository) ListOverdueInvoices ¶
type InterestRepository ¶
type InterestRepository interface {
GetInvoiceForInterest(ctx context.Context, schemaName, tenantID, invoiceID string) (*interestInvoice, error)
CreateInterest(ctx context.Context, schemaName string, interest *InvoiceInterest) error
GetLatestInterest(ctx context.Context, schemaName, invoiceID string) (*InvoiceInterest, error)
ListInterestHistory(ctx context.Context, schemaName, invoiceID string) ([]InvoiceInterest, error)
ListOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]interestInvoice, error)
}
type InterestService ¶
type InterestService struct {
// contains filtered or unexported fields
}
InterestService handles interest calculations for overdue invoices.
func NewInterestService ¶
func NewInterestService(db *pgxpool.Pool) *InterestService
NewInterestService creates a new interest service.
func NewInterestServiceWithRepository ¶
func NewInterestServiceWithRepository(repo InterestRepository) *InterestService
func (*InterestService) CalculateInterest ¶
func (s *InterestService) CalculateInterest(ctx context.Context, schemaName, tenantID, invoiceID string, interestRate float64, asOfDate time.Time) (*InterestCalculationResult, error)
CalculateInterest calculates current interest for an invoice.
func (*InterestService) CalculateInterestForOverdueInvoices ¶
func (s *InterestService) CalculateInterestForOverdueInvoices(ctx context.Context, schemaName, tenantID string, interestRate float64) ([]InterestCalculationResult, error)
CalculateInterestForOverdueInvoices calculates interest for all overdue invoices of a tenant.
func (*InterestService) GetLatestInterest ¶
func (s *InterestService) GetLatestInterest(ctx context.Context, schemaName, invoiceID string) (*InvoiceInterest, error)
GetLatestInterest gets the most recent interest calculation for an invoice.
func (*InterestService) ListInterestHistory ¶
func (s *InterestService) ListInterestHistory(ctx context.Context, schemaName, invoiceID string) ([]InvoiceInterest, error)
ListInterestHistory gets all interest calculations for an invoice.
func (*InterestService) SaveInterestCalculation ¶
func (s *InterestService) SaveInterestCalculation(ctx context.Context, schemaName string, result *InterestCalculationResult) (*InvoiceInterest, error)
SaveInterestCalculation saves an interest calculation record.
type InterestSettings ¶
type InterestSettings struct {
Rate float64 `json:"rate"` // Daily interest rate (e.g., 0.0005 = 0.05%)
AnnualRate float64 `json:"annual_rate"` // Annualized rate for display (rate * 365)
Description string `json:"description"` // Human-readable description
IsEnabled bool `json:"is_enabled"` // Whether interest calculation is enabled
}
InterestSettings represents the interest configuration for a tenant
type Invoice ¶
type Invoice struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
InvoiceNumber string `json:"invoice_number"`
InvoiceType InvoiceType `json:"invoice_type"`
ContactID string `json:"contact_id"`
Contact *contacts.Contact `json:"contact,omitempty"`
IssueDate time.Time `json:"issue_date"`
DueDate time.Time `json:"due_date"`
Currency string `json:"currency"`
ExchangeRate decimal.Decimal `json:"exchange_rate"`
Subtotal decimal.Decimal `json:"subtotal"`
VATAmount decimal.Decimal `json:"vat_amount"`
Total decimal.Decimal `json:"total"`
BaseSubtotal decimal.Decimal `json:"base_subtotal"`
BaseVATAmount decimal.Decimal `json:"base_vat_amount"`
BaseTotal decimal.Decimal `json:"base_total"`
AmountPaid decimal.Decimal `json:"amount_paid"`
Status InvoiceStatus `json:"status"`
Reference string `json:"reference,omitempty"`
Notes string `json:"notes,omitempty"`
Lines []InvoiceLine `json:"lines"`
JournalEntryID *string `json:"journal_entry_id,omitempty"`
EInvoiceSentAt *time.Time `json:"einvoice_sent_at,omitempty"`
EInvoiceID *string `json:"einvoice_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
CreatedBy string `json:"created_by"`
UpdatedAt time.Time `json:"updated_at"`
}
Invoice represents a sales or purchase invoice
func (*Invoice) Calculate ¶
func (inv *Invoice) Calculate()
Calculate computes the invoice totals from lines
type InvoiceFilter ¶
type InvoiceFilter struct {
InvoiceType InvoiceType
Status InvoiceStatus
ContactID string
FromDate *time.Time
ToDate *time.Time
Search string
}
InvoiceFilter provides filtering options
type InvoiceForReminder ¶
type InvoiceForReminder struct {
ID string `json:"id"`
InvoiceNumber string `json:"invoice_number"`
ContactID string `json:"contact_id"`
ContactName string `json:"contact_name"`
ContactEmail string `json:"contact_email,omitempty"`
IssueDate string `json:"issue_date"`
DueDate string `json:"due_date"`
Total string `json:"total"`
AmountPaid string `json:"amount_paid"`
OutstandingAmount string `json:"outstanding_amount"`
Currency string `json:"currency"`
DaysUntilDue int `json:"days_until_due"` // Negative if overdue
DaysOverdue int `json:"days_overdue"` // 0 if not overdue
}
InvoiceForReminder represents an invoice that may need a reminder
type InvoiceInterest ¶
type InvoiceInterest struct {
ID string `json:"id"`
InvoiceID string `json:"invoice_id"`
CalculatedAt time.Time `json:"calculated_at"`
DaysOverdue int `json:"days_overdue"`
PrincipalAmount decimal.Decimal `json:"principal_amount"`
InterestRate decimal.Decimal `json:"interest_rate"`
InterestAmount decimal.Decimal `json:"interest_amount"`
TotalWithInterest decimal.Decimal `json:"total_with_interest"`
CreatedAt time.Time `json:"created_at"`
}
InvoiceInterest represents a calculated interest record for an invoice
type InvoiceLine ¶
type InvoiceLine struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
InvoiceID string `json:"invoice_id"`
LineNumber int `json:"line_number"`
Description string `json:"description"`
Quantity decimal.Decimal `json:"quantity"`
Unit string `json:"unit,omitempty"`
UnitPrice decimal.Decimal `json:"unit_price"`
DiscountPercent decimal.Decimal `json:"discount_percent"`
VATRate decimal.Decimal `json:"vat_rate"`
VATTreatment VATTreatment `json:"vat_treatment"`
LineSubtotal decimal.Decimal `json:"line_subtotal"`
LineVAT decimal.Decimal `json:"line_vat"`
LineTotal decimal.Decimal `json:"line_total"`
AccountID *string `json:"account_id,omitempty"`
ProductID *string `json:"product_id,omitempty"`
}
InvoiceLine represents a line item on an invoice
func (*InvoiceLine) Calculate ¶
func (l *InvoiceLine) Calculate()
Calculate computes the line totals
func (InvoiceLine) ReverseChargeVAT ¶
func (l InvoiceLine) ReverseChargeVAT() decimal.Decimal
ReverseChargeVAT calculates the self-assessed VAT amount for reverse-charge reporting.
type InvoiceStatus ¶
type InvoiceStatus string
InvoiceStatus represents the status of an invoice
const ( StatusDraft InvoiceStatus = "DRAFT" StatusSent InvoiceStatus = "SENT" StatusPartiallyPaid InvoiceStatus = "PARTIALLY_PAID" StatusPaid InvoiceStatus = "PAID" StatusOverdue InvoiceStatus = "OVERDUE" StatusVoided InvoiceStatus = "VOIDED" )
type InvoiceType ¶
type InvoiceType string
InvoiceType represents the type of invoice
const ( InvoiceTypeSales InvoiceType = "SALES" InvoiceTypePurchase InvoiceType = "PURCHASE" InvoiceTypeCreditNote InvoiceType = "CREDIT_NOTE" )
type MockReminderRepository ¶
type MockReminderRepository struct {
OverdueInvoices []OverdueInvoice
Reminders map[string][]PaymentReminder
GetOverdueErr error
}
MockReminderRepository for testing.
func NewMockReminderRepository ¶
func NewMockReminderRepository() *MockReminderRepository
NewMockReminderRepository creates a new mock reminder repository.
func (*MockReminderRepository) AddMockOverdueInvoice ¶
func (m *MockReminderRepository) AddMockOverdueInvoice(id, invoiceNumber, contactID, contactName, contactEmail, currency string, total, amountPaid decimal.Decimal, daysOverdue int)
AddMockOverdueInvoice adds a mock overdue invoice for testing.
func (*MockReminderRepository) CreateReminder ¶
func (m *MockReminderRepository) CreateReminder(ctx context.Context, schemaName string, reminder *PaymentReminder) error
CreateReminder creates a mock reminder.
func (*MockReminderRepository) GetOverdueInvoices ¶
func (m *MockReminderRepository) GetOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]OverdueInvoice, error)
GetOverdueInvoices returns mock overdue invoices.
func (*MockReminderRepository) GetReminderCount ¶
func (m *MockReminderRepository) GetReminderCount(ctx context.Context, schemaName, tenantID, invoiceID string) (int, *time.Time, error)
GetReminderCount returns mock reminder count.
func (*MockReminderRepository) GetRemindersByInvoice ¶
func (m *MockReminderRepository) GetRemindersByInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) ([]PaymentReminder, error)
GetRemindersByInvoice returns mock reminders for an invoice.
func (*MockReminderRepository) UpdateReminderStatus ¶
func (m *MockReminderRepository) UpdateReminderStatus(ctx context.Context, schemaName, reminderID string, status ReminderStatus, sentAt *time.Time, errorMsg string) error
UpdateReminderStatus updates mock reminder status.
type NotFoundError ¶
type NotFoundError struct {
Entity string
}
NotFoundError represents a not found error
func (*NotFoundError) Error ¶
func (e *NotFoundError) Error() string
type OverdueInvoice ¶
type OverdueInvoice struct {
ID string `json:"id"`
InvoiceNumber string `json:"invoice_number"`
ContactID string `json:"contact_id"`
ContactName string `json:"contact_name"`
ContactEmail string `json:"contact_email,omitempty"`
IssueDate string `json:"issue_date"`
DueDate string `json:"due_date"`
Total decimal.Decimal `json:"total"`
AmountPaid decimal.Decimal `json:"amount_paid"`
OutstandingAmount decimal.Decimal `json:"outstanding_amount"`
Currency string `json:"currency"`
DaysOverdue int `json:"days_overdue"`
ReminderCount int `json:"reminder_count"`
LastReminderAt *time.Time `json:"last_reminder_at,omitempty"`
}
OverdueInvoice represents an overdue invoice with reminder info
type OverdueInvoicesSummary ¶
type OverdueInvoicesSummary struct {
TotalOverdue decimal.Decimal `json:"total_overdue"`
InvoiceCount int `json:"invoice_count"`
ContactCount int `json:"contact_count"`
AverageDaysOverdue int `json:"average_days_overdue"`
Invoices []OverdueInvoice `json:"invoices"`
GeneratedAt time.Time `json:"generated_at"`
}
OverdueInvoicesSummary represents a summary of overdue invoices
type PaymentReminder ¶
type PaymentReminder struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
InvoiceID string `json:"invoice_id"`
InvoiceNumber string `json:"invoice_number"`
ContactID string `json:"contact_id"`
ContactName string `json:"contact_name"`
ContactEmail string `json:"contact_email"`
RuleID *string `json:"rule_id,omitempty"` // Link to reminder rule
TriggerType string `json:"trigger_type,omitempty"` // BEFORE_DUE, ON_DUE, AFTER_DUE
DaysOffset int `json:"days_offset,omitempty"` // Days from due date
ReminderNumber int `json:"reminder_number"` // 1st, 2nd, 3rd reminder etc.
Status ReminderStatus `json:"status"`
SentAt *time.Time `json:"sent_at,omitempty"`
ErrorMessage string `json:"error_message,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
PaymentReminder represents a payment reminder for an overdue invoice
type ReminderGORMRepository ¶
type ReminderGORMRepository struct {
// contains filtered or unexported fields
}
ReminderGORMRepository implements ReminderRepository with the shared ORM layer.
func NewReminderGORMRepository ¶
func NewReminderGORMRepository(db *gorm.DB) *ReminderGORMRepository
func NewReminderRepository ¶
func NewReminderRepository(db *pgxpool.Pool) *ReminderGORMRepository
func (*ReminderGORMRepository) CreateReminder ¶
func (r *ReminderGORMRepository) CreateReminder(ctx context.Context, schemaName string, reminder *PaymentReminder) error
CreateReminder creates a new payment reminder record.
func (*ReminderGORMRepository) GetOverdueInvoices ¶
func (r *ReminderGORMRepository) GetOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]OverdueInvoice, error)
GetOverdueInvoices retrieves all overdue sales invoices.
func (*ReminderGORMRepository) GetReminderCount ¶
func (r *ReminderGORMRepository) GetReminderCount(ctx context.Context, schemaName, tenantID, invoiceID string) (int, *time.Time, error)
GetReminderCount gets the number of reminders sent for an invoice.
func (*ReminderGORMRepository) GetRemindersByInvoice ¶
func (r *ReminderGORMRepository) GetRemindersByInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) ([]PaymentReminder, error)
GetRemindersByInvoice gets all reminders for an invoice.
func (*ReminderGORMRepository) UpdateReminderStatus ¶
func (r *ReminderGORMRepository) UpdateReminderStatus(ctx context.Context, schemaName, reminderID string, status ReminderStatus, sentAt *time.Time, errorMsg string) error
UpdateReminderStatus updates the status of a reminder.
type ReminderRepository ¶
type ReminderRepository interface {
// GetOverdueInvoices retrieves all overdue sales invoices
GetOverdueInvoices(ctx context.Context, schemaName, tenantID string, asOfDate time.Time) ([]OverdueInvoice, error)
// GetReminderCount gets the number of reminders sent for an invoice
GetReminderCount(ctx context.Context, schemaName, tenantID, invoiceID string) (int, *time.Time, error)
// CreateReminder creates a new payment reminder record
CreateReminder(ctx context.Context, schemaName string, reminder *PaymentReminder) error
// UpdateReminderStatus updates the status of a reminder
UpdateReminderStatus(ctx context.Context, schemaName, reminderID string, status ReminderStatus, sentAt *time.Time, errorMsg string) error
// GetRemindersByInvoice gets all reminders for an invoice
GetRemindersByInvoice(ctx context.Context, schemaName, tenantID, invoiceID string) ([]PaymentReminder, error)
}
ReminderRepository defines the interface for payment reminder data access
type ReminderResult ¶
type ReminderResult struct {
InvoiceID string `json:"invoice_id"`
InvoiceNumber string `json:"invoice_number"`
Success bool `json:"success"`
Message string `json:"message"`
ReminderID string `json:"reminder_id,omitempty"`
}
ReminderResult represents the result of sending a reminder
type ReminderRule ¶
type ReminderRule struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
Name string `json:"name"`
TriggerType TriggerType `json:"trigger_type"`
DaysOffset int `json:"days_offset"`
EmailTemplateType string `json:"email_template_type"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ReminderRule defines when automated reminders should be sent
type ReminderRuleGORMRepository ¶
type ReminderRuleGORMRepository struct {
// contains filtered or unexported fields
}
ReminderRuleGORMRepository implements ReminderRuleRepository with the shared ORM layer.
func NewReminderRuleGORMRepository ¶
func NewReminderRuleGORMRepository(db *gorm.DB) *ReminderRuleGORMRepository
func NewReminderRuleRepository ¶
func NewReminderRuleRepository(db *pgxpool.Pool) *ReminderRuleGORMRepository
func (*ReminderRuleGORMRepository) CreateRule ¶
func (r *ReminderRuleGORMRepository) CreateRule(ctx context.Context, schemaName string, rule *ReminderRule) error
func (*ReminderRuleGORMRepository) DeleteRule ¶
func (r *ReminderRuleGORMRepository) DeleteRule(ctx context.Context, schemaName, tenantID, ruleID string) error
func (*ReminderRuleGORMRepository) GetInvoicesForRule ¶
func (r *ReminderRuleGORMRepository) GetInvoicesForRule(ctx context.Context, schemaName, tenantID string, rule *ReminderRule, asOfDate time.Time) ([]InvoiceForReminder, error)
func (*ReminderRuleGORMRepository) GetRule ¶
func (r *ReminderRuleGORMRepository) GetRule(ctx context.Context, schemaName, tenantID, ruleID string) (*ReminderRule, error)
func (*ReminderRuleGORMRepository) HasReminderBeenSent ¶
func (*ReminderRuleGORMRepository) ListActiveRules ¶
func (r *ReminderRuleGORMRepository) ListActiveRules(ctx context.Context, schemaName, tenantID string) ([]ReminderRule, error)
func (*ReminderRuleGORMRepository) ListRules ¶
func (r *ReminderRuleGORMRepository) ListRules(ctx context.Context, schemaName, tenantID string) ([]ReminderRule, error)
func (*ReminderRuleGORMRepository) RecordReminderSent ¶
func (r *ReminderRuleGORMRepository) RecordReminderSent(ctx context.Context, schemaName string, reminder *PaymentReminder) error
func (*ReminderRuleGORMRepository) UpdateRule ¶
func (r *ReminderRuleGORMRepository) UpdateRule(ctx context.Context, schemaName string, rule *ReminderRule) error
type ReminderRuleRepository ¶
type ReminderRuleRepository interface {
ListRules(ctx context.Context, schemaName, tenantID string) ([]ReminderRule, error)
ListActiveRules(ctx context.Context, schemaName, tenantID string) ([]ReminderRule, error)
GetRule(ctx context.Context, schemaName, tenantID, ruleID string) (*ReminderRule, error)
CreateRule(ctx context.Context, schemaName string, rule *ReminderRule) error
UpdateRule(ctx context.Context, schemaName string, rule *ReminderRule) error
DeleteRule(ctx context.Context, schemaName, tenantID, ruleID string) error
GetInvoicesForRule(ctx context.Context, schemaName, tenantID string, rule *ReminderRule, asOfDate time.Time) ([]InvoiceForReminder, error)
HasReminderBeenSent(ctx context.Context, schemaName, tenantID, invoiceID, ruleID string) (bool, error)
RecordReminderSent(ctx context.Context, schemaName string, reminder *PaymentReminder) error
}
ReminderRuleRepository defines the interface for reminder rule data access.
type ReminderService ¶
type ReminderService struct {
// contains filtered or unexported fields
}
ReminderService provides payment reminder operations
func NewReminderService ¶
func NewReminderService(db *pgxpool.Pool, emailService *email.Service) *ReminderService
NewReminderService creates a new reminder service
func NewReminderServiceWithRepository ¶
func NewReminderServiceWithRepository(repo ReminderRepository, emailService *email.Service) *ReminderService
NewReminderServiceWithRepository creates a reminder service with custom repository
func (*ReminderService) GetOverdueInvoicesSummary ¶
func (s *ReminderService) GetOverdueInvoicesSummary(ctx context.Context, tenantID, schemaName string) (*OverdueInvoicesSummary, error)
GetOverdueInvoicesSummary retrieves a summary of all overdue invoices
func (*ReminderService) GetReminderHistory ¶
func (s *ReminderService) GetReminderHistory(ctx context.Context, tenantID, schemaName, invoiceID string) ([]PaymentReminder, error)
GetReminderHistory gets the reminder history for an invoice
func (*ReminderService) SendBulkReminders ¶
func (s *ReminderService) SendBulkReminders(ctx context.Context, tenantID, schemaName string, req *SendBulkRemindersRequest, companyName string) (*BulkReminderResult, error)
SendBulkReminders sends payment reminders for multiple invoices
func (*ReminderService) SendReminder ¶
func (s *ReminderService) SendReminder(ctx context.Context, tenantID, schemaName string, req *SendReminderRequest, companyName string) (*ReminderResult, error)
SendReminder sends a payment reminder for a specific invoice
type ReminderStatus ¶
type ReminderStatus string
ReminderStatus represents the status of a payment reminder
const ( ReminderStatusPending ReminderStatus = "PENDING" ReminderStatusSent ReminderStatus = "SENT" ReminderStatusFailed ReminderStatus = "FAILED" ReminderStatusCanceled ReminderStatus = "CANCELED" )
type Repository ¶
type Repository interface {
Create(ctx context.Context, schemaName string, invoice *Invoice) error
GetByID(ctx context.Context, schemaName, tenantID, invoiceID string) (*Invoice, error)
List(ctx context.Context, schemaName, tenantID string, filter *InvoiceFilter) ([]Invoice, error)
UpdateStatus(ctx context.Context, schemaName, tenantID, invoiceID string, status InvoiceStatus) error
UpdatePayment(ctx context.Context, schemaName, tenantID, invoiceID string, amountPaid decimal.Decimal, status InvoiceStatus) error
GenerateNumber(ctx context.Context, schemaName, tenantID string, invoiceType InvoiceType) (string, error)
UpdateOverdueStatus(ctx context.Context, schemaName, tenantID string) (int, error)
}
Repository defines the contract for invoice data access
type SendBulkRemindersRequest ¶
type SendBulkRemindersRequest struct {
InvoiceIDs []string `json:"invoice_ids"`
Message string `json:"message,omitempty"`
}
SendBulkRemindersRequest represents a request to send multiple reminders
type SendReminderRequest ¶
type SendReminderRequest struct {
InvoiceID string `json:"invoice_id"`
Message string `json:"message,omitempty"` // Optional custom message
}
SendReminderRequest represents a request to send a payment reminder
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service provides invoicing operations
func NewService ¶
func NewService(db *pgxpool.Pool, accountingService *accounting.Service) *Service
NewService creates a new invoicing service with an ORM-backed repository.
func NewServiceWithRepository ¶
func NewServiceWithRepository(repo Repository, accountingService *accounting.Service) *Service
NewServiceWithRepository creates a new invoicing service with a custom repository
func (*Service) Create ¶
func (s *Service) Create(ctx context.Context, tenantID, schemaName string, req *CreateInvoiceRequest) (*Invoice, error)
Create creates a new invoice
func (*Service) GetByID ¶
func (s *Service) GetByID(ctx context.Context, tenantID, schemaName, invoiceID string) (*Invoice, error)
GetByID retrieves an invoice by ID
func (*Service) ImportCSV ¶
func (s *Service) ImportCSV( ctx context.Context, tenantID, schemaName string, existingContacts []contacts.Contact, existingProducts []inventory.Product, req *ImportInvoicesRequest, validateDate func(time.Time) error, ) (*ImportInvoicesResult, error)
ImportCSV imports invoices from grouped CSV rows. Each row represents one invoice line.
func (*Service) ImportEInvoiceXML ¶
func (s *Service) ImportEInvoiceXML( ctx context.Context, tenantID, schemaName string, existingContacts []contacts.Contact, req *ImportEInvoiceRequest, validateDate func(time.Time) error, ) (*ImportInvoicesResult, error)
ImportEInvoiceXML imports invoices from Estonian e-invoice XML.
func (*Service) List ¶
func (s *Service) List(ctx context.Context, tenantID, schemaName string, filter *InvoiceFilter) ([]Invoice, error)
List retrieves invoices with optional filtering
func (*Service) RecordPayment ¶
func (s *Service) RecordPayment(ctx context.Context, tenantID, schemaName, invoiceID string, amount decimal.Decimal) error
RecordPayment records a payment against an invoice
func (*Service) ResolveInvoiceIDByNumber ¶
func (s *Service) ResolveInvoiceIDByNumber(ctx context.Context, tenantID, schemaName, invoiceNumber string) (string, error)
ResolveInvoiceIDByNumber returns the unique invoice ID for an invoice number.
func (*Service) UpdateOverdueStatus ¶
func (s *Service) UpdateOverdueStatus(ctx context.Context, tenantID, schemaName string) (int, error)
UpdateOverdueStatus updates status of overdue invoices
func (*Service) WithRepository ¶
func (s *Service) WithRepository(repo Repository) *Service
WithRepository returns a service that keeps this service's domain dependencies while using a repository bound to another transaction.
type TriggerType ¶
type TriggerType string
TriggerType represents when a reminder should be triggered
const ( TriggerBeforeDue TriggerType = "BEFORE_DUE" TriggerOnDue TriggerType = "ON_DUE" TriggerAfterDue TriggerType = "AFTER_DUE" )
type UpdateInterestSettingsRequest ¶
type UpdateInterestSettingsRequest struct {
Rate float64 `json:"rate"` // Daily interest rate
}
UpdateInterestSettingsRequest is the request to update interest settings
func (*UpdateInterestSettingsRequest) Validate ¶
func (r *UpdateInterestSettingsRequest) Validate() error
Validate validates the interest settings update request
type UpdateReminderRuleRequest ¶
type UpdateReminderRuleRequest struct {
Name *string `json:"name,omitempty"`
EmailTemplateType *string `json:"email_template_type,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}
UpdateReminderRuleRequest is the request to update a reminder rule
type VATTreatment ¶
type VATTreatment string
VATTreatment controls whether VAT is charged on the invoice line or reported separately.
const ( VATTreatmentStandard VATTreatment = "STANDARD" VATTreatmentReverseCharge VATTreatment = "REVERSE_CHARGE" )
func NormalizeVATTreatment ¶
func NormalizeVATTreatment(value string) (VATTreatment, error)
NormalizeVATTreatment validates and normalizes VAT treatment values.
type ValidationError ¶
ValidationError represents a validation error
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string