repo

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const TimestampLayout = "2006-01-02T15:04:05.000000000Z07:00"

TimestampLayout is a fixed-width variant of time.RFC3339Nano, used whenever this package persists a time.Time to a SQLite TEXT column.

time.RFC3339Nano trims trailing zero digits from the fractional-second component (e.g. ".5" instead of ".500000000"). That breaks plain lexicographic string comparison in SQL (<=, >=, ORDER BY): a timestamp ending in zeros can sort as "greater than" a slightly later timestamp whose un-trimmed digits happen to start lower, because the trimmed string's terminator ('Z' or '+') compares greater than any digit character. Always emitting all 9 fractional digits keeps every stored timestamp the same length, so string order always matches chronological order.

Parsing is unaffected — time.Parse(time.RFC3339Nano, ...) accepts both this fixed-width format and the old trimmed one, so existing rows written before this fix remain readable.

Variables

This section is empty.

Functions

func DefaultStorageDir

func DefaultStorageDir() (string, error)

DefaultStorageDir returns the OS-appropriate default base directory for local file storage, used when config.StorageLocalPath isn't set.

func NewAccountingRepo

func NewAccountingRepo(database *sql.DB, q *db.Queries) data.AccountingRepoer

NewAccountingRepo returns an AccountingRepoer backed by SQLite.

func NewBranchRepo

func NewBranchRepo(database *sql.DB, q *db.Queries) data.BranchRepoer

func NewCompanyRepo

func NewCompanyRepo(database *sql.DB, q *db.Queries) data.CompanyRepoer

func NewCustomerRepo

func NewCustomerRepo(database *sql.DB, q *db.Queries) data.CustomerRepoer

func NewDiscountRepo

func NewDiscountRepo(database *sql.DB, q *db.Queries) data.DiscountRepoer

NewDiscountRepo returns a DiscountRepoer backed by SQLite.

func NewExpenseRepo

func NewExpenseRepo(database *sql.DB, q *db.Queries) data.ExpenseRepoer

func NewFileRepo

func NewFileRepo(database *sql.DB, q *db.Queries) data.FileRepoer

NewFileRepo returns a FileRepoer backed by SQLite.

func NewOrderRepo

func NewOrderRepo(database *sql.DB, q *db.Queries) data.OrderRepoer

NewOrderRepo constructs an OrderRepo.

func NewPOSStationRepo

func NewPOSStationRepo(database *sql.DB, q *db.Queries) data.POSStationRepoer

func NewProductRepo

func NewProductRepo(database *sql.DB, q *db.Queries) data.ProductRepoer

func NewReportsRepo

func NewReportsRepo(database *sql.DB) data.ReportsQuerier

NewReportsRepo returns a ReportsQuerier backed by SQLite.

func NewSQLiteDB

func NewSQLiteDB(path string) (*sql.DB, error)

NewSQLiteDB opens a SQLite database at path and configures recommended pragmas. Use ":memory:" for an in-process test database.

func NewSessionRepo

func NewSessionRepo(database *sql.DB, q *db.Queries) data.SessionRepoer

NewSessionRepo constructs a SessionRepo.

func NewSupplierPaymentRepo

func NewSupplierPaymentRepo(database *sql.DB, q *db.Queries) data.SupplierPaymentRepoer

func NewSupplierRepo

func NewSupplierRepo(database *sql.DB, q *db.Queries) data.SupplierRepoer

func NewUserRepo

func NewUserRepo(database *sql.DB, q *db.Queries) data.UserRepoer

NewUserRepo creates a new UserRepo backed by the given database and queries. Pass a tx-scoped *db.Queries (via testhelpers.WithTxRollback) for test isolation.

Types

type AccountingRepo

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

AccountingRepo persists COA accounts and double-entry journal entries.

func (*AccountingRepo) BalanceByAccount

func (r *AccountingRepo) BalanceByAccount(
	ctx context.Context,
	companyID uuid.UUID,
) ([]model.AccountBalance, error)

BalanceByAccount returns running debit/credit totals per COA account for the company. It executes a raw SQL query because sqlc cannot express the LEFT JOIN / GROUP BY pattern cleanly with a per-company filter on the joined table.

func (*AccountingRepo) CreateJournalEntry

func (r *AccountingRepo) CreateJournalEntry(
	ctx context.Context,
	entry *model.JournalEntry,
) error

CreateJournalEntry persists the entry header and all its lines atomically. It sets entry.ID, entry.CreatedAt, and each line's ID and EntryID.

func (*AccountingRepo) GetAccountByCode

func (r *AccountingRepo) GetAccountByCode(
	ctx context.Context,
	code string,
) (*model.Account, error)

func (*AccountingRepo) ListAccounts

func (r *AccountingRepo) ListAccounts(ctx context.Context) ([]model.Account, error)

func (*AccountingRepo) ListJournalEntriesByCompany

func (r *AccountingRepo) ListJournalEntriesByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.JournalEntry], error)

type BranchRepo

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

func (*BranchRepo) Create

func (r *BranchRepo) Create(ctx context.Context, entity *model.Branch) error

func (*BranchRepo) Delete

func (r *BranchRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*BranchRepo) GetByID

func (r *BranchRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Branch, error)

func (*BranchRepo) ListByCompany

func (r *BranchRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Branch], error)

func (*BranchRepo) Update

func (r *BranchRepo) Update(ctx context.Context, entity *model.Branch) error

func (*BranchRepo) WithTx

func (r *BranchRepo) WithTx(ctx context.Context, fn func(data.BranchRepoer) error) error

type CompanyRepo

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

func (*CompanyRepo) Create

func (r *CompanyRepo) Create(ctx context.Context, entity *model.Company) error

func (*CompanyRepo) Delete

func (r *CompanyRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*CompanyRepo) GetByHandle

func (r *CompanyRepo) GetByHandle(ctx context.Context, handle string) (*model.Company, error)

func (*CompanyRepo) GetByID

func (r *CompanyRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Company, error)

func (*CompanyRepo) ListByOwner

func (*CompanyRepo) Update

func (r *CompanyRepo) Update(ctx context.Context, entity *model.Company) error

func (*CompanyRepo) WithTx

func (r *CompanyRepo) WithTx(ctx context.Context, fn func(data.CompanyRepoer) error) error

type CustomerRepo

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

func (*CustomerRepo) Create

func (r *CustomerRepo) Create(ctx context.Context, entity *model.Customer) error

func (*CustomerRepo) Delete

func (r *CustomerRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*CustomerRepo) GetByCompanyAndEmail added in v0.1.2

func (r *CustomerRepo) GetByCompanyAndEmail(
	ctx context.Context,
	companyID uuid.UUID,
	email string,
) (*model.Customer, error)

func (*CustomerRepo) GetByCompanyAndPhone added in v0.1.2

func (r *CustomerRepo) GetByCompanyAndPhone(
	ctx context.Context,
	companyID uuid.UUID,
	phone string,
) (*model.Customer, error)

func (*CustomerRepo) GetByID

func (r *CustomerRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Customer, error)

func (*CustomerRepo) ListByCompany

func (r *CustomerRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Customer], error)

func (*CustomerRepo) Update

func (r *CustomerRepo) Update(ctx context.Context, entity *model.Customer) error

func (*CustomerRepo) WithTx

func (r *CustomerRepo) WithTx(ctx context.Context, fn func(data.CustomerRepoer) error) error

type DiscountRepo

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

DiscountRepo persists named discount rules.

func (*DiscountRepo) CountRedemptions added in v0.1.4

func (r *DiscountRepo) CountRedemptions(ctx context.Context, discountID uuid.UUID) (int, error)

CountRedemptions returns how many orders have redeemed a discount.

func (*DiscountRepo) Create

func (r *DiscountRepo) Create(ctx context.Context, entity *model.Discount) error

Create persists a new discount. Sets ID and CreatedAt.

func (*DiscountRepo) CreateRedemption added in v0.1.4

func (r *DiscountRepo) CreateRedemption(
	ctx context.Context,
	entity *model.DiscountRedemption,
) error

CreateRedemption records an order's redemption of a discount. Sets ID.

func (*DiscountRepo) Delete

func (r *DiscountRepo) Delete(ctx context.Context, id uuid.UUID) error

Delete removes a discount by ID.

func (*DiscountRepo) DeleteRedemptionByOrder added in v0.1.4

func (r *DiscountRepo) DeleteRedemptionByOrder(ctx context.Context, orderID uuid.UUID) error

DeleteRedemptionByOrder clears any redemption tied to an order — a no-op if none exists.

func (*DiscountRepo) GetByCode added in v0.1.4

func (r *DiscountRepo) GetByCode(
	ctx context.Context, companyID uuid.UUID, code string,
) (*model.Discount, error)

GetByCode retrieves a discount by its company-scoped coupon code.

func (*DiscountRepo) GetByID

func (r *DiscountRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Discount, error)

GetByID retrieves a discount by its ID.

func (*DiscountRepo) ListByCompany

func (r *DiscountRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Discount], error)

ListByCompany returns paginated discounts for a company, optionally filtered by a name search keyword.

func (*DiscountRepo) ListSelectable added in v0.1.4

func (r *DiscountRepo) ListSelectable(
	ctx context.Context, companyID uuid.UUID, at time.Time,
) ([]model.Discount, error)

ListSelectable returns active, uncoded, currently-in-window discounts for a company — what the POS dropdown may offer.

func (*DiscountRepo) Update

func (r *DiscountRepo) Update(ctx context.Context, entity *model.Discount) error

Update persists mutable discount fields.

type ExpenseRepo

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

func (*ExpenseRepo) Create

func (r *ExpenseRepo) Create(ctx context.Context, entity *model.Expense) error

func (*ExpenseRepo) GetByID

func (r *ExpenseRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Expense, error)

func (*ExpenseRepo) ListByCompany

func (r *ExpenseRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Expense], error)

type FileRepo

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

FileRepo persists uploaded file metadata.

func (*FileRepo) Create

func (r *FileRepo) Create(ctx context.Context, entity *model.File) error

Create persists a new file record. Sets ID and CreatedAt.

func (*FileRepo) Delete

func (r *FileRepo) Delete(ctx context.Context, id, companyID uuid.UUID) error

Delete removes a file record by ID, scoped to the owning company.

func (*FileRepo) GetByID

func (r *FileRepo) GetByID(ctx context.Context, id, companyID uuid.UUID) (*model.File, error)

GetByID retrieves a file by ID, scoped to the owning company.

type GoqiteEnqueuer

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

GoqiteEnqueuer implements data.Enqueuer using a goqite SQLite-backed queue. All jobs share the single "okpos" queue; the job name routes to the correct handler.

func NewGoqiteEnqueuer

func NewGoqiteEnqueuer(database *sql.DB) *GoqiteEnqueuer

NewGoqiteEnqueuer creates an enqueuer backed by the given *sql.DB. The database must already contain the goqite schema (migration 000023).

func (*GoqiteEnqueuer) Enqueue added in v0.2.0

func (e *GoqiteEnqueuer) Enqueue(ctx context.Context, job data.BackgroundJob) error

Enqueue enqueues a job non-transactionally.

func (*GoqiteEnqueuer) Queue

func (e *GoqiteEnqueuer) Queue() *goqite.Queue

Queue returns the underlying goqite.Queue, used by worker.NewRunner.

type InventoryRepo

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

func NewInventoryRepo

func NewInventoryRepo(database *sql.DB, q *db.Queries) *InventoryRepo

func (*InventoryRepo) CurrentStock

func (r *InventoryRepo) CurrentStock(ctx context.Context, productID uuid.UUID) (float64, error)

func (*InventoryRepo) GetByID

func (r *InventoryRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.StockMovement, error)

func (*InventoryRepo) HasMovements

func (r *InventoryRepo) HasMovements(ctx context.Context, productID uuid.UUID) (bool, error)

func (*InventoryRepo) IsReversed added in v0.1.2

func (r *InventoryRepo) IsReversed(ctx context.Context, movementID uuid.UUID) (bool, error)

IsReversed reports whether a correction movement already reverses movementID.

func (*InventoryRepo) LPP

func (r *InventoryRepo) LPP(ctx context.Context, productID uuid.UUID) (int64, error)

func (*InventoryRepo) ListByCompany

func (*InventoryRepo) ListByProduct

func (r *InventoryRepo) ListByProduct(
	ctx context.Context,
	productID, companyID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.StockMovement], error)

func (*InventoryRepo) Record

func (r *InventoryRepo) Record(ctx context.Context, entity *model.StockMovement) error

func (*InventoryRepo) StockAt

func (r *InventoryRepo) StockAt(
	ctx context.Context,
	productID uuid.UUID,
	at time.Time,
) (float64, error)

func (*InventoryRepo) WithTx

func (r *InventoryRepo) WithTx(ctx context.Context, fn func(data.InventoryRepoer) error) error

type LocalFSStorage

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

LocalFSStorage stores file bytes on the local filesystem, rooted at baseDir. It does not implement data.URLPresigner — a private local directory has no native presign mechanism, so read access is instead brokered through a short-lived file-access JWT (see service.FileService).

func NewLocalFSStorage

func NewLocalFSStorage(baseDir string) (*LocalFSStorage, error)

NewLocalFSStorage returns a FileStorage backed by baseDir, creating it (privately, mode 0700) if it doesn't already exist.

func (*LocalFSStorage) Delete

func (s *LocalFSStorage) Delete(_ context.Context, key string) error

Delete removes baseDir/key. Deleting an already-absent key is a no-op, matching typical object-storage delete semantics.

func (*LocalFSStorage) Get

Get opens baseDir/key for reading. Returns data.ErrNotFound if it doesn't exist.

func (*LocalFSStorage) Put

func (s *LocalFSStorage) Put(_ context.Context, key string, r io.Reader, _ int64) error

Put writes r to baseDir/key, creating parent directories as needed.

type OrderRepo

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

OrderRepo implements data.OrderRepoer using SQLite.

func (*OrderRepo) CountOrdersByCompanyAndDate

func (r *OrderRepo) CountOrdersByCompanyAndDate(
	ctx context.Context,
	companyID uuid.UUID,
	date string,
) (int64, error)

CountOrdersByCompanyAndDate returns the number of orders created by the company on the given date (format "YYYY-MM-DD"). Used for receipt sequence generation.

func (*OrderRepo) CreateOrder

func (r *OrderRepo) CreateOrder(ctx context.Context, entity *model.Order) error

CreateOrder persists a new open order. Sets ID, CreatedAt, UpdatedAt.

func (*OrderRepo) CreateOrderItem

func (r *OrderRepo) CreateOrderItem(ctx context.Context, entity *model.OrderItem) error

CreateOrderItem persists a new order item. Sets ID.

func (*OrderRepo) CreateOrderReturn

func (r *OrderRepo) CreateOrderReturn(ctx context.Context, entity *model.OrderReturn) error

CreateOrderReturn persists a return record. Sets ID.

func (*OrderRepo) CreateOrderReturnItem

func (r *OrderRepo) CreateOrderReturnItem(
	ctx context.Context,
	entity *model.OrderReturnItem,
) error

CreateOrderReturnItem persists a return item line. Sets ID.

func (*OrderRepo) CreatePayment

func (r *OrderRepo) CreatePayment(ctx context.Context, entity *model.Payment) error

CreatePayment persists a payment leg. Sets ID.

func (*OrderRepo) DeleteOrder

func (r *OrderRepo) DeleteOrder(ctx context.Context, id uuid.UUID) error

DeleteOrder removes an order record entirely.

func (*OrderRepo) DeleteOrderItem

func (r *OrderRepo) DeleteOrderItem(ctx context.Context, id uuid.UUID) error

DeleteOrderItem removes an order item.

func (*OrderRepo) GetOrderByID

func (r *OrderRepo) GetOrderByID(ctx context.Context, id uuid.UUID) (*model.Order, error)

GetOrderByID retrieves an order by its ID.

func (*OrderRepo) GetOrderItemByID

func (r *OrderRepo) GetOrderItemByID(ctx context.Context, id uuid.UUID) (*model.OrderItem, error)

GetOrderItemByID retrieves an order item by its ID.

func (*OrderRepo) GetOrderReturnByID

func (r *OrderRepo) GetOrderReturnByID(
	ctx context.Context,
	id uuid.UUID,
) (*model.OrderReturn, error)

GetOrderReturnByID retrieves a return by its ID.

func (*OrderRepo) ListOrderItemsByOrder

func (r *OrderRepo) ListOrderItemsByOrder(
	ctx context.Context,
	orderID uuid.UUID,
) ([]model.OrderItem, error)

ListOrderItemsByOrder returns all items for an order.

func (*OrderRepo) ListOrderReturnItemsByReturn

func (r *OrderRepo) ListOrderReturnItemsByReturn(
	ctx context.Context,
	returnID uuid.UUID,
) ([]model.OrderReturnItem, error)

ListOrderReturnItemsByReturn returns all item lines for a return.

func (*OrderRepo) ListOrderReturnsByOrder

func (r *OrderRepo) ListOrderReturnsByOrder(
	ctx context.Context,
	orderID uuid.UUID,
) ([]model.OrderReturn, error)

ListOrderReturnsByOrder returns all return records for an order.

func (*OrderRepo) ListOrdersByCompany

func (r *OrderRepo) ListOrdersByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Order], error)

ListOrdersByCompany returns paginated orders for a company.

func (*OrderRepo) ListOrdersByCompanyFiltered

func (r *OrderRepo) ListOrdersByCompanyFiltered(
	ctx context.Context,
	companyID uuid.UUID,
	filter *data.OrderFilter,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Order], error)

ListOrdersByCompanyFiltered returns paginated orders for a company, narrowed by filter. Built as hand-rolled dynamic SQL (bypassing sqlc, same approach as ReportsRepo's multi-filter queries) since sqlc's static query generation doesn't cleanly express several independently-optional, mixed-type conditions in one query.

func (*OrderRepo) ListOrdersBySession

func (r *OrderRepo) ListOrdersBySession(
	ctx context.Context,
	sessionID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Order], error)

ListOrdersBySession returns paginated orders for a session.

func (*OrderRepo) ListPaymentsByOrder

func (r *OrderRepo) ListPaymentsByOrder(
	ctx context.Context,
	orderID uuid.UUID,
) ([]model.Payment, error)

ListPaymentsByOrder returns all payment legs for an order.

func (*OrderRepo) SumPaymentsByOrder

func (r *OrderRepo) SumPaymentsByOrder(ctx context.Context, orderID uuid.UUID) (int64, error)

SumPaymentsByOrder returns the total of completed payments for an order.

func (*OrderRepo) UpdateOrder

func (r *OrderRepo) UpdateOrder(ctx context.Context, entity *model.Order) error

UpdateOrder persists mutable order fields.

func (*OrderRepo) UpdateOrderItem

func (r *OrderRepo) UpdateOrderItem(ctx context.Context, entity *model.OrderItem) error

UpdateOrderItem updates the quantity and subtotal of an existing order item.

func (*OrderRepo) WithTx

func (r *OrderRepo) WithTx(
	ctx context.Context,
	fn func(orders data.OrderRepoer, inv data.InventoryRepoer) error,
) error

WithTx runs fn inside a single database transaction with transactional views of both the order repo and the inventory repo.

type POSStationRepo

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

func (*POSStationRepo) Create

func (r *POSStationRepo) Create(ctx context.Context, entity *model.POSStation) error

func (*POSStationRepo) Delete

func (r *POSStationRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*POSStationRepo) GetByID

func (r *POSStationRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.POSStation, error)

func (*POSStationRepo) ListByCompany

func (*POSStationRepo) Update

func (r *POSStationRepo) Update(ctx context.Context, entity *model.POSStation) error

func (*POSStationRepo) WithTx

func (r *POSStationRepo) WithTx(ctx context.Context, fn func(data.POSStationRepoer) error) error

type ProductRepo

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

func (*ProductRepo) Create

func (r *ProductRepo) Create(ctx context.Context, entity *model.Product) error

Create persists a new product. Sets CreatedAt/UpdatedAt, and generates an ID only if entity.ID is not already set — ProductService.Create pre-generates it when it needs to default SKU to the product's own ID, so the row can be inserted once with its final SKU rather than requiring a separate backfill update (which would race against the SKU uniqueness constraint under concurrent creates).

func (*ProductRepo) Delete

func (r *ProductRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*ProductRepo) GetByID

func (r *ProductRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Product, error)

func (*ProductRepo) GetBySKU

func (r *ProductRepo) GetBySKU(
	ctx context.Context,
	companyID uuid.UUID,
	sku string,
) (*model.Product, error)

GetBySKU retrieves a product by its SKU, scoped to companyID. Used by the POS barcode-scan-to-cart flow.

func (*ProductRepo) GetOrCreateCategories added in v0.1.7

func (r *ProductRepo) GetOrCreateCategories(
	ctx context.Context,
	companyID uuid.UUID,
	names []string,
) ([]model.Category, error)

GetOrCreateCategories resolves each name to a company-scoped category via an atomic upsert (see UpsertCategory), so concurrent creates of the same normalized name can't race into duplicate rows. Blank names are skipped.

func (*ProductRepo) GetProductCategories added in v0.1.7

func (r *ProductRepo) GetProductCategories(
	ctx context.Context,
	productID uuid.UUID,
) ([]model.Category, error)

func (*ProductRepo) GetRecipeComponents

func (r *ProductRepo) GetRecipeComponents(
	ctx context.Context,
	recipeID uuid.UUID,
) ([]model.RecipeComponent, error)

func (*ProductRepo) GetRecipeOverheads

func (r *ProductRepo) GetRecipeOverheads(
	ctx context.Context,
	recipeID uuid.UUID,
) ([]model.RecipeOverhead, error)

func (*ProductRepo) ListByCompany

func (r *ProductRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Product], error)

func (*ProductRepo) ListByCompanyAndCategory added in v0.1.7

func (r *ProductRepo) ListByCompanyAndCategory(
	ctx context.Context,
	companyID, categoryID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Product], error)

func (*ProductRepo) ListByCompanyAndType

func (r *ProductRepo) ListByCompanyAndType(
	ctx context.Context,
	companyID uuid.UUID,
	t model.ProductType,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Product], error)

func (*ProductRepo) ListByCompanyTypeAndCategory added in v0.1.7

func (r *ProductRepo) ListByCompanyTypeAndCategory(
	ctx context.Context,
	companyID uuid.UUID,
	t model.ProductType,
	categoryID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Product], error)

func (*ProductRepo) ListCategoriesByCompany added in v0.1.7

func (r *ProductRepo) ListCategoriesByCompany(
	ctx context.Context,
	companyID uuid.UUID,
) ([]model.Category, error)

func (*ProductRepo) ListSellableByCompany

func (r *ProductRepo) ListSellableByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Product], error)

ListSellableByCompany returns paginated Simple+Recipe products for the POS product grid, as one correctly-ordered and counted set.

func (*ProductRepo) SetProductCategories added in v0.1.7

func (r *ProductRepo) SetProductCategories(
	ctx context.Context,
	productID uuid.UUID,
	categoryIDs []uuid.UUID,
) error

func (*ProductRepo) SetRecipeComponents

func (r *ProductRepo) SetRecipeComponents(
	ctx context.Context,
	recipeID uuid.UUID,
	components []model.RecipeComponent,
) error

func (*ProductRepo) SetRecipeOverheads

func (r *ProductRepo) SetRecipeOverheads(
	ctx context.Context,
	recipeID uuid.UUID,
	overheads []model.RecipeOverhead,
) error

func (*ProductRepo) Update

func (r *ProductRepo) Update(ctx context.Context, entity *model.Product) error

func (*ProductRepo) WithTx

func (r *ProductRepo) WithTx(
	ctx context.Context,
	fn func(products data.ProductRepoer, inv data.InventoryRepoer) error,
) error

WithTx runs fn inside a single database transaction with transactional views of both the product repo and the inventory repo — mirrors OrderRepo.WithTx, so a product write and a stock movement (e.g. initial stock at creation) can commit atomically.

type ReportsRepo

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

ReportsRepo provides aggregate report queries using raw SQL. It does not use sqlc; all queries are executed via database.QueryContext.

func (*ReportsRepo) InventorySnapshot

func (r *ReportsRepo) InventorySnapshot(
	ctx context.Context,
	companyID uuid.UUID,
) ([]model.InventoryLine, error)

InventorySnapshot returns current stock and last-purchase-price per product.

func (*ReportsRepo) InventorySnapshotPaged

func (r *ReportsRepo) InventorySnapshotPaged(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	productType string,
	categoryID *uuid.UUID,
	stockStatus string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.InventoryLine], error)

InventorySnapshotPaged is the paginated, searchable counterpart to InventorySnapshot, used by the web Inventory list page.

The stock-status filter ("low"/"out"/"ok") applies to the aggregated current_stock (a SUM over stock_movements), so it must be a HAVING clause evaluated after GROUP BY — it can't be a plain WHERE. That in turn means the count query can't stay a flat `count(*) FROM products`; it wraps the same grouped/filtered query as a subquery instead.

Every filter arg is a numbered parameter (?1, ?2, ...) even where the same value is referenced multiple times in the SQL text (e.g. companyID), so each value is only passed once in the Go args slice.

func (*ReportsRepo) PLByPeriod

func (r *ReportsRepo) PLByPeriod(
	ctx context.Context,
	companyID uuid.UUID,
	from, to string,
) (model.PLSummary, error)

PLByPeriod returns revenue and expense totals from double-entry journal entries.

func (*ReportsRepo) RevenueByPaymentMethod

func (r *ReportsRepo) RevenueByPaymentMethod(
	ctx context.Context,
	companyID uuid.UUID,
	from, to string,
) ([]model.PaymentMethodRevenue, error)

RevenueByPaymentMethod returns completed payment totals grouped by method.

func (*ReportsRepo) SalesByPeriod

func (r *ReportsRepo) SalesByPeriod(
	ctx context.Context,
	companyID uuid.UUID,
	from, to, groupBy string,
) ([]model.SalesPeriod, error)

SalesByPeriod returns revenue grouped by day, week, or month.

func (*ReportsRepo) SalesTotals

func (r *ReportsRepo) SalesTotals(
	ctx context.Context,
	companyID uuid.UUID,
	from, to string,
) (model.SalesSummary, error)

SalesTotals returns aggregate sales figures for the given date range.

func (*ReportsRepo) TopProductsByRevenue

func (r *ReportsRepo) TopProductsByRevenue(
	ctx context.Context,
	companyID uuid.UUID,
	from, to string,
	topN int,
) ([]model.TopProduct, error)

TopProductsByRevenue returns the top N products by order-item subtotal.

type S3Config

type S3Config struct {
	Endpoint  string
	Region    string
	AccessKey string
	SecretKey string
	Bucket    string
	UseSSL    bool
}

S3Config configures an S3-compatible storage backend (AWS S3, MinIO, Cloudflare R2, DigitalOcean Spaces, etc.).

type S3Storage

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

S3Storage stores file bytes in an S3-compatible bucket via minio-go, and caches presigned GET URLs in-memory (keyed by storage key) so repeated reads of the same file within one URL's lifetime don't re-hit the presign endpoint on every request.

func NewS3Storage

func NewS3Storage(ctx context.Context, cfg *S3Config) (*S3Storage, error)

NewS3Storage connects to the configured S3-compatible endpoint and ensures the target bucket exists, creating it if necessary.

func (*S3Storage) Delete

func (s *S3Storage) Delete(ctx context.Context, key string) error

Delete removes the object at key. Deleting an already-absent key is a no-op, matching S3's own delete semantics.

func (*S3Storage) Get

func (s *S3Storage) Get(ctx context.Context, key string) (io.ReadCloser, error)

Get opens the object at key for reading. Returns data.ErrNotFound if it doesn't exist.

func (*S3Storage) PresignGET

func (s *S3Storage) PresignGET(ctx context.Context, key string, ttl time.Duration) (string, error)

PresignGET returns a presigned GET URL for key, valid for ttl. Cached in-memory (TTL-bound to ttl) so repeated calls for the same key within one token's lifetime don't re-hit the S3 presign endpoint.

func (*S3Storage) Put

func (s *S3Storage) Put(ctx context.Context, key string, r io.Reader, size int64) error

Put uploads r to the bucket under key.

type SessionRepo

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

SessionRepo implements data.SessionRepoer using SQLite.

func (*SessionRepo) Close

func (r *SessionRepo) Close(ctx context.Context, sessionID uuid.UUID, closedAt time.Time) error

Close marks a session as closed at the given time.

func (*SessionRepo) Create

func (r *SessionRepo) Create(ctx context.Context, entity *model.POSSession) error

Create persists a new open POS session. Sets ID and OpenedAt.

func (*SessionRepo) CreateReconciliation

func (r *SessionRepo) CreateReconciliation(
	ctx context.Context,
	entity *model.SessionReconciliation,
) error

CreateReconciliation persists a SessionReconciliation. Sets ReconciledAt.

func (*SessionRepo) DeleteOpenOrders

func (r *SessionRepo) DeleteOpenOrders(ctx context.Context, sessionID uuid.UUID) (int64, error)

DeleteOpenOrders hard-deletes every open order for the session (cascading to their items via FK) and returns the number deleted.

func (*SessionRepo) GetByID

func (r *SessionRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.POSSession, error)

GetByID retrieves a session by its ID.

func (*SessionRepo) GetOpenByStation

func (r *SessionRepo) GetOpenByStation(
	ctx context.Context,
	stationID uuid.UUID,
) (*model.POSSession, error)

GetOpenByStation retrieves the open session for a station, if any. Returns ErrNotFound if no open session exists for the station.

func (*SessionRepo) GetOpenByUser

func (r *SessionRepo) GetOpenByUser(
	ctx context.Context,
	companyID, userID uuid.UUID,
) (*model.POSSession, error)

GetOpenByUser retrieves the open session opened by userID within companyID, if any. Returns ErrNotFound if no open session exists.

func (*SessionRepo) GetReconciliationBySession

func (r *SessionRepo) GetReconciliationBySession(
	ctx context.Context,
	sessionID uuid.UUID,
) (*model.SessionReconciliation, error)

GetReconciliationBySession retrieves the reconciliation for a given session.

func (*SessionRepo) HasOpenOrders

func (r *SessionRepo) HasOpenOrders(ctx context.Context, sessionID uuid.UUID) (bool, error)

HasOpenOrders returns true if the session has any orders in open status.

func (*SessionRepo) ListByCompany

func (r *SessionRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.POSSession], error)

ListByCompany returns paginated sessions for a company, ordered by opened_at DESC.

func (*SessionRepo) ListOpenByCompanyFiltered

func (r *SessionRepo) ListOpenByCompanyFiltered(
	ctx context.Context,
	companyID uuid.UUID,
	filter *data.SessionFilter,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.POSSession], error)

ListOpenByCompanyFiltered returns paginated open sessions for a company, optionally narrowed by filter.BranchID. Built as hand-rolled dynamic SQL (bypassing sqlc), same approach as OrderRepo.ListOrdersByCompanyFiltered.

func (*SessionRepo) SumCashPayments

func (r *SessionRepo) SumCashPayments(ctx context.Context, sessionID uuid.UUID) (int64, error)

SumCashPayments returns the total cash-method payments taken in a session.

type SupplierPaymentRepo

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

func (*SupplierPaymentRepo) Create

func (*SupplierPaymentRepo) GetByID

func (*SupplierPaymentRepo) ListByCompany

func (*SupplierPaymentRepo) ListBySupplier

type SupplierRepo

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

func (*SupplierRepo) Create

func (r *SupplierRepo) Create(ctx context.Context, entity *model.Supplier) error

func (*SupplierRepo) Delete

func (r *SupplierRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*SupplierRepo) GetByID

func (r *SupplierRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.Supplier, error)

func (*SupplierRepo) ListByCompany

func (r *SupplierRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	search string,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.Supplier], error)

func (*SupplierRepo) Update

func (r *SupplierRepo) Update(ctx context.Context, entity *model.Supplier) error

func (*SupplierRepo) WithTx

func (r *SupplierRepo) WithTx(ctx context.Context, fn func(data.SupplierRepoer) error) error

type UserRepo

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

UserRepo is the SQLite implementation of data.UserRepoer.

func (*UserRepo) CountByCompany

func (r *UserRepo) CountByCompany(ctx context.Context, companyID uuid.UUID) (int64, error)

func (*UserRepo) CountByRole added in v0.1.7

func (r *UserRepo) CountByRole(ctx context.Context, role auth.UserRole) (int64, error)

func (*UserRepo) Create

func (r *UserRepo) Create(ctx context.Context, entity *model.User) error

func (*UserRepo) Delete

func (r *UserRepo) Delete(ctx context.Context, id uuid.UUID) error

func (*UserRepo) GetByEmail

func (r *UserRepo) GetByEmail(ctx context.Context, email string) (*model.User, error)

func (*UserRepo) GetByID

func (r *UserRepo) GetByID(ctx context.Context, id uuid.UUID) (*model.User, error)

func (*UserRepo) InvalidateTokens

func (r *UserRepo) InvalidateTokens(ctx context.Context, userID uuid.UUID) error

InvalidateTokens sets token_valid_after to now, so any JWT already issued to this user (its iat predates this call) is rejected by handler.JWTParserMiddleware and AuthService.RefreshTokens going forward.

func (*UserRepo) ListByCompany

func (r *UserRepo) ListByCompany(
	ctx context.Context,
	companyID uuid.UUID,
	q data.SupportsPagination,
) (*dto.PaginationResults[model.User], error)

func (*UserRepo) Paginate

func (*UserRepo) Update

func (r *UserRepo) Update(ctx context.Context, entity *model.User) error

func (*UserRepo) WithTx

func (r *UserRepo) WithTx(ctx context.Context, fn func(data.UserRepoer) error) error

Jump to

Keyboard shortcuts

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