package repository import ( "errors" "time" ) var ( ErrUpdateFailed = errors.New("update failed") ErrDeleteFailed = errors.New("delete failed") ErrNotFound = errors.New("record not found") ErrHasChildren = errors.New("cannot delete: has dependent records that must be removed first") ) // Repository is the interface which must be satisfied in order to // connect to a database. type Repository interface { Migrate() error InsertCompany(c Company) (*Company, error) AllCompanies() ([]Company, error) GetCompanyByID(id int64) (*Company, error) UpdateCompany(id int64, updated Company) error DeleteCompany(id int64) error InsertAssignment(a Assignment) (*Assignment, error) AssignmentsByCompany(companyID int64) ([]Assignment, error) AllActiveAssignments() ([]Assignment, error) GetAssignmentByID(id int64) (*Assignment, error) UpdateAssignment(id int64, updated Assignment) error DeleteAssignment(id int64) error InsertTask(t Task) (*Task, error) TasksByAssignment(assignmentID int64) ([]Task, error) GetTaskByID(id int64) (*Task, error) UpdateTask(id int64, name string) error DeleteTask(id int64) error TotalMinutesForTask(taskID int64) (float64, error) InsertWorkSession(s WorkSession) (*WorkSession, error) InsertManualWorkSession(s WorkSession) (*WorkSession, error) StopWorkSession(id int64) error UpdateWorkSession(id int64, updated WorkSession) error DeleteWorkSession(id int64) error WorkSessionsByAssignment(assignmentID int64, limit int) ([]WorkSession, error) TotalHoursForAssignment(assignmentID int64) (float64, error) NextInvoiceNumber(date time.Time) (string, error) InsertInvoice(inv Invoice) (*Invoice, error) } type Company struct { ID int64 `json:"id"` Name string `json:"name"` Address string `json:"address"` ContactEmail string `json:"contact_email"` ContactPhone string `json:"contact_phone"` HourlyRate float64 `json:"hourly_rate"` CreatedAt time.Time `json:"created_at"` } type Assignment struct { ID int64 `json:"id"` CompanyID int64 `json:"company_id"` CompanyName string `json:"company_name"` Name string `json:"name"` Description string `json:"description"` HourlyRate float64 `json:"hourly_rate"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` } // Task is a reusable task within an assignment. Each task gets an // incremental number scoped to its assignment (1, 2, 3...). // Time spent on sessions with this task stacks up. type Task struct { ID int64 `json:"id"` AssignmentID int64 `json:"assignment_id"` Number int `json:"number"` Name string `json:"name"` TotalMinutes float64 `json:"total_minutes"` } // WorkSession is a single timed block of work on a task. type WorkSession struct { ID int64 `json:"id"` AssignmentID int64 `json:"assignment_id"` TaskID int64 `json:"task_id"` TaskDescription string `json:"task_description"` StartTime time.Time `json:"start_time"` EndTime *time.Time `json:"end_time"` DurationMinutes float64 `json:"duration_minutes"` } // Invoice is a generated invoice record, used for tracking invoice numbers. type Invoice struct { ID int64 `json:"id"` AssignmentID int64 `json:"assignment_id"` InvoiceNumber string `json:"invoice_number"` TotalAmount float64 `json:"total_amount"` GeneratedAt time.Time `json:"generated_at"` }