Help us shape the future of Go! Take the 2026 Go Developer Survey

investor

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 46 Imported by: 0

README

Arandu

Arandu Investor

Angel-investor revenue sharing for an Arandu application: the investors and their contracts, the application's money in and out, the costs of running it, and a monthly closing per contract that pays each investor their share of the net into an arandu-wallet wallet they withdraw from by PIX.

It is one install per application. Every investor's contract says what share of the net they hold and which products' revenue counts; the costs the admin declares are spread over the revenue of each period, so every line of an investor's statement carries its part of them.

How a period closes

A contract closes on its billing day (1–28), once a month. Closing the period [start, end):

  1. Gross is every entry of the contract's products dated in the period: sales, renewals, refunds (negative) and adjustments.
  2. Fees are what was taken on the way: the gateway, the invoice issuer, taxes, expenses typed by hand.
  3. Costs are the declared costs that ran in the period — monthly, yearly (a twelfth a month) or once, prorated by the days of the billing month — each one shared out over the products it applies to by their revenue.
  4. Net is gross − fees − costs. The cost ratio (costs over gross, in parts per million) is what every statement line carries as its part of the costs.
  5. The investor's amount is the contract's share of the net, rounded to the centavo. It is deposited into their investor wallet in arandu-wallet, idempotently, and becomes an invoice.

A period whose net is zero or negative closes with nothing due, and the loss is not carried into the next one. An invoice is never summed with the next: it is withdrawn whole, with no minimum, and becomes overdue once a later period closes while it is still unpaid. An entry that arrives late — dated in a period already closed — is counted in the next closing, never twice.

Money is int64 centavos, shares are basis points (1500 = 15%), and no income tax is withheld.

Install

It needs arandu-wallet v0.13.0 or newer, which brings the withdrawal requests an investor is paid through and takes them only through this package:

go get github.com/hyz-is/arandu-wallet@v0.13.0
go get github.com/hyz-is/arandu-investor

Wire it

An Arandu application registers a module explicitly. There is no service provider, no container and no discovery, so these are the lines to paste into bootstrap/app.go and there are no others.

import (
	investor "github.com/hyz-is/arandu-investor"
	wallet "github.com/hyz-is/arandu-wallet"
)

In Build, after the session store, the Disk and the wallet module exist and before k.Register:

	investorModule, err := investor.New(investor.Config{
		Files:  contractsDisk,         // the application's filesystem.Disk, local or S3
		Wallet: walletModule.Service(), // the one arandu-wallet instance
		Payer:  investor.Payer{Name: "Empresa Ltda", Document: "00.000.000/0001-00"},
	}, db, sessions)
	if err != nil {
		return App{}, err
	}

And the registration, inside the k.Register(...) call already there:

		investorModule,

Then, once, before the application serves:

aru migrate

The package owns eight tables, which is why arandu.mod.toml says migrations = true. arandu-wallet's own migrations run in the same step.

Give people access

The policy is in policy.go, and roles reach it through the Subject, which arandu-permission fills:

role or action what it opens
role investor.admin, or action investor.admin (AdminAction) the registry, contracts, entries, costs, closings, every investor's invoices and reports
role wallet.operator arandu-wallet's operator actions; the admin who pays withdrawals and closes periods needs it too

The action is what an arandu-permission group carries: mount its Roles() in Config.Middleware (or AdminMiddleware), so the actions are resolved on each request, and the people of that group are the admin.

An investor needs no role. A signed-in user whose user_id is on an investor's registration reads that investor's panel, contracts, statements, projection, invoices and reports, and nobody else's. Anybody else is refused. The tenant of every statement is the Grant's, never a value from the request.

Record the application's money

The application's own code — the place its payments are confirmed — records each movement through the service. Sending the same ExternalRef twice records it once:

	_, err := investorModule.Service().RecordEntry(ctx, actor, investor.EntryRequest{
		ExternalRef: "mp:" + payment.ID,
		Kind:        investor.KindSale, // or KindRenewal, KindRefund, ...
		ProductID:   "placaflow",
		OccurredAt:  payment.ApprovedAt,
		Gross:       19900, // centavos
		Fee:         798,   // what the gateway took
		FeeDetail:   "gateway",
	})

An entry is never edited; a wrong one is undone by a reversal. The admin types what did not come through the application on the books screen.

Close the periods

The admin closes one contract by hand, or every contract due on a day with "close the contracts due today". An application that wants it unattended runs the same call from its scheduler once a day:

	closed, failed, err := investorModule.Service().CloseDue(ctx, operator, investor.DayOf(time.Now(), loc))

A contract that fails to close does not stop the others: it is reported in failed and closed on the next run.

Withdrawals

The investor declares a PIX key or a bank account on their panel — always in the name and document of their registration — and asks for an invoice ("Solicitar saque"). arandu-wallet holds the amount. The wallet is opened with PayoutVia: "investor", so a request that does not come through this package — the wallet's own route — is refused, and no part of an invoice leaves around these rules. The admin, on the withdrawals screen, takes the request, makes the PIX outside the system, and records the end-to-end identifier with the receipt attached; or rejects it with a reason, and the invoice can be asked for again. The investor downloads the receipt from their panel ("Ver comprovante"). With Config.Activity, every one of these acts is in arandu-activitylog.

Reports

Each investor has a monthly report and a yearly income report (informe de rendimentos), both .xlsx, written with the standard library.

Screens

Eight screens, in pt-BR and English, built on Kyse components with components.DataTable: the investor's panel, a contract's statement and projection, and the admin's registry, investor, books, costs and withdrawals. Every GET route answers the screen to a browser and JSON to a client that asks for it; every form posts to the same routes the JSON API uses.

Publish the views

Look at what would be written, then write it:

aru vendor:publish --tag=view
aru vendor:publish --tag=view --apply

The files land under resources/views/modules/investor/, and from that point they are yours. Compile them:

aru view:build

and import the two directories it wrote into, with the other imports:

	_ "your/module/path/storage/framework/views/modules/investor"
	_ "your/module/path/storage/framework/views/modules/investor/admin"

Without them the views are not in the binary, and the module refuses to boot rather than answering the first request that reaches one with a 500. The refusal names the view, the command and the import.

The sentences come from resources/lang/<locale>/investor.json, shipped in English and Brazilian Portuguese: the screens, the data tables (columns, search, pager), the validation messages, the reports and the activity descriptions. To change one, put the key in the application's own catalogue and pass it as Config.Translator; it is asked first, key by key.

The language is Config.Locale when the application fixes one, else the one translation.Middleware or translation.InLocale put on the request, else English. A product that speaks only Brazilian Portuguese sets it once:

investor.Config{
	Locale:         "pt-BR", // screens, messages, reports, activity log
	TitleSeparator: " — ",   // "Saques dos investidores — <APP_NAME>"
	// ...
}

Validation messages are written in English where they are produced -- by this package, the framework's helpers and arandu-wallet -- so a JSON client reads them as it always did, and each route draws them again in the request's language before the router puts them in the flash or in a 422. Labels.Message, Labels.Errors and Labels.Summary do the same for an application that calls the service directly. The error banner names each field by its label ("Chave PIX: Preencha este campo.").

Configuration

field required meaning
Files yes the Disk the signed contracts are kept on, under the tenant's prefix.
Wallet yes arandu-wallet's service. The package keeps no balance of its own.
Prefix no where the routes are mounted. Defaults to /investor.
PageSize no rows per page. Defaults to 25, refused above 200.
Location no the timezone days are counted in. Defaults to America/Sao_Paulo.
Payer no the paying company, printed on the income report.
Translator no the application's catalogue, asked before the shipped one.
Locale no the language of every screen, message, report and activity description ("pt-BR"). Empty follows the request, then English.
TitleSeparator no joins a screen's title to the application's APP_NAME in the document title (" — " gives "Saques dos investidores — Alpr.sh"). Empty titles a screen with its own title.
Paths no the segments of every route. Empty fields keep DefaultPaths; PortuguesePaths is the set in pt-BR (/contratos, /faturas/{id}/saque, /faturas/{id}/comprovante, /conta-de-recebimento, /investidores, /saques).
AdminPrefix no where the admin's routes are mounted. Defaults to Prefix + Paths.Admin.
Middleware, AdminMiddleware no run after RequireAuth, on every route and on the admin's only.
Chrome no what the application's layout draws around a screen (its sidebar, its menu), carried on the page as Screen.Chrome().
Activity no arandu-activitylog's logger; every act that changes something is recorded in the log investor.

An application that keeps the investor's screens in its customer panel and the admin's in its operator console mounts the two halves itself:

investorModule.InvestorRoutes(panel)   // under Prefix, with the panel's guards
investorModule.AdminRoutes(console)    // under AdminPrefix, with the console's

The pages embed hesape's view.Page and answer HasErrors and ErrorSummary too, so they fit the layout of an application on Arandu Framework v0.62 and of an older one. Module.URLs() builds every address, for an application that links to the screens from its own pages.

New returns an error rather than starting half-wired.

Routes

Every route sits behind RequireAuth: a visitor with no session is sent to /auth/login, and a handler reads who is asking with ctx.User(). The paths below are the defaults; Config.Paths and Config.AdminPrefix move them, and the route names never change. The policy then decides; a refusal is 403, a record that is not there 404, a rejected input goes back with the messages in the flash (422 with the messages keyed by field to a JSON client).

method path what
GET /investor/me the investor's panel
GET /investor/me/contracts, /me/invoices the investor's contracts and invoices
POST /investor/me/payout-accounts declare a PIX key, or a bank account with kind=bank
GET /investor/me/reports/{year}[/{month}] income report, monthly report
GET /investor/contracts/{id}/statement, /projection, /file a contract's statement, open period, signed copy
GET /investor/costs the declared costs
POST /investor/invoices/{id}/withdrawal ask for an invoice to be paid
GET /investor/invoices/{id}/receipt the receipt of a paid withdrawal
GET, POST /investor/admin/investors the registry, register an investor
GET, PUT /investor/admin/investors/{id} one investor
POST, DELETE /investor/admin/investors/{id}/suspension suspend, reactivate
GET, POST /investor/admin/investors/{id}/contracts contracts, register one (multipart, with the PDF)
POST /investor/admin/contracts/{id}/amendments register an amendment
POST /investor/admin/contracts/{id}/closings close one contract's period
POST /investor/admin/closings/due close every contract due on a day
GET, POST /investor/admin/entries the books, a typed entry
POST /investor/admin/entries/{id}/reversal reverse an entry
GET, POST /investor/admin/costs the costs, declare one
POST /investor/admin/costs/{id}/end end a cost
GET /investor/admin/investors/{id}/invoices, /reports/{year}[/{month}] one investor's invoices and reports
GET /investor/admin/withdrawals the withdrawal queue
POST /investor/admin/withdrawals/{id}/processing, /payment, /rejection take, pay (multipart, with the receipt), reject

The data path

Each entity embeds model.Model and declares its table beside it. aru model:build generates the queries — InvestorQuery.go with Investors(db), and one per entity — which are committed and never edited by hand; aru model:build --check fails when one is out of date.

InvestorService owns *data.DB and follows validate -> security.Authorize -> Grant -> Model terminal in every exported method, which the unit suite audits. Handlers never hold the database or start a query. Every query starts at Investors(s.db) or its sibling and reads the tenant from the Grant through data.Tenant(g).

Example

go run -tags example ./example

It opens SQLite in a temporary directory, migrates arandu-wallet and this package, and runs one investor through a whole period: the contract with its PDF, a sale and a renewal with the gateway's fee, a monthly cost, the closing on the billing day, and the withdrawal of the invoice by PIX with the receipt. It leaves nothing behind. The build tag is there so that installing this package never compiles it.

Tests

GOWORK=off go test ./... -race

The unit suite audits the data path, holds the policy, checks the calculation, and builds every published view with the view compiler an application uses — then renders each screen with sample data. The feature suite runs the closings, statements, withdrawals and routes against SQLite with arandu-wallet installed beside it.

Licence

MIT. See LICENSE.md.

Documentation

Overview

Package investor is an Arandu module: one entity with its generated query, one policy that decides about it, one service that orchestrates each use case, and the routes that reach them.

The files are laid out by role rather than by layer, so the whole package reads top to bottom:

module.go      -> registration, routes, handlers and migrations
config.go      -> what the application passes in
model.go       -> the entity, and what it may answer with
policy.go      -> who may do what
service.go     -> the use cases, and Model access after authorization
views.go       -> the files the application takes ownership of

An application registers it explicitly. There is no service provider, no container and no discovery: the wiring is three lines somebody wrote, and reading them is how they learn what the application is made of.

Index

Constants

View Source
const (
	EventInvestorCreated     = "investor.created"
	EventInvestorUpdated     = "investor.updated"
	EventInvestorSuspended   = "investor.suspended"
	EventInvestorReactivated = "investor.reactivated"
	EventContractCreated     = "contract.created"
	EventContractAmended     = "contract.amended"
	EventEntryRecorded       = "entry.recorded"
	EventEntryReversed       = "entry.reversed"
	EventCostCreated         = "cost.created"
	EventCostEnded           = "cost.ended"
	EventPeriodClosed        = "period.closed"
	EventPayoutAccountAdded  = "payout_account.added"
	EventWithdrawalRequested = "withdrawal.requested"
	EventWithdrawalTaken     = "withdrawal.processing"
	EventWithdrawalPaid      = "withdrawal.paid"
	EventWithdrawalRejected  = "withdrawal.rejected"
)

The events this package records, one per act that changes something. The subject of each entry is the record the act was on, by kind and key.

View Source
const (
	// DefaultPrefix is where the routes are mounted when Config leaves Prefix
	// empty.
	DefaultPrefix = "/investor"
	// DefaultPageSize is how many records one page answers with when Config
	// leaves PageSize at zero.
	DefaultPageSize = 25
	// MaxPageSize is the ceiling PageSize is refused above. A page nobody
	// bounded is a page that reads the whole table on the day the table is
	// large.
	MaxPageSize = 200
)

The defaults for the optional settings. They are constants rather than literals inside Config.withDefaults, so the value a reader finds here is the value the package uses.

View Source
const (
	// InvestorsManage is registering, changing and suspending investors, and
	// keeping their contracts.
	InvestorsManage security.Action = "investor.investors.manage"
	// EntriesManage is recording entries by hand, reversing them and closing a
	// contract's period.
	EntriesManage security.Action = "investor.entries.manage"
	// CostsManage is declaring the costs of the system.
	CostsManage security.Action = "investor.costs.manage"
	// DashboardView is reading an investor's statement, costs and projection.
	DashboardView security.Action = "investor.dashboard.view"
	// ContractView is reading and downloading an investor's own contract.
	ContractView security.Action = "investor.contract.view"
	// ReportsView is reading an investor's invoices and income reports.
	ReportsView security.Action = "investor.reports.view"
	// AdminAction is being this package's admin, held as an action: what an
	// application whose permissions arandu-permission administers puts in a
	// group, so the people of that group are the admin without a role
	// written on their accounts. It opens what AdminRole opens, and nothing
	// more.
	AdminAction security.Action = "investor.admin"
)

The actions of this package. Constants rather than strings at the call site: a typo in an action name would silently authorize nothing, or worse, everything.

They carry the package in the name because an application registers many packages, and the name of an action shows up in logs and in audit trails where "view" on its own says nothing about what was viewed.

View Source
const (
	PayoutPix  = "pix"
	PayoutBank = "bank"
)

The kinds of payout account an investor declares, as arandu-wallet keeps them.

View Source
const (
	// TranslationGroup is the file every key of this package lives in, and the
	// prefix of every key: "investor.screen.dashboard_title".
	TranslationGroup = "investor"
	// FallbackLocale answers a request that negotiated no locale, when
	// Config.Locale names none either, and every line a locale does not have.
	// It is English, as in the other hyz-is modules; an application that
	// speaks one language sets Config.Locale.
	FallbackLocale = "en"
)
View Source
const (
	ViewDashboard       = "modules.investor.dashboard"
	ViewStatement       = "modules.investor.statement"
	ViewProjection      = "modules.investor.projection"
	ViewAdminInvestors  = "modules.investor.admin.investors"
	ViewAdminInvestor   = "modules.investor.admin.investor"
	ViewAdminCosts      = "modules.investor.admin.costs"
	ViewAdminEntries    = "modules.investor.admin.entries"
	ViewAdminWithdrawal = "modules.investor.admin.withdrawals"
)

The screens this package renders, by the name their path gives them.

View Source
const ActivityLogName = "investor"

ActivityLogName is the log every entry of this package is recorded in.

View Source
const AdminRole = "investor.admin"

AdminRole is the role an application grants to the people who run the investors' money: finance, whoever registers investors, closes periods and declares costs.

One role and not several. The rules below need exactly one distinction -- the investor, and somebody acting across the tenant on the investors' behalf. Which people hold it is the application's to decide, through arandu-permission; this package only reads it off the subject.

View Source
const DayLayout = "2006-01-02"

DayLayout is the format a Day is written in.

View Source
const DefaultLocation = "America/Sao_Paulo"

DefaultLocation is the timezone days are counted in when Config leaves Location nil. The package is Brazilian first; an application elsewhere sets its own.

View Source
const MaxContractBytes = 20 << 20

MaxContractBytes is the largest signed file accepted. A scanned contract of a few pages is far below it; a file above it is a mistake, or worse.

View Source
const PayoutVia = "investor"

PayoutVia is the name this package asks for its investors' withdrawals under, and the one their wallets are opened with: arandu-wallet refuses a request for those wallets that does not carry it.

View Source
const PublishCommand = "aru vendor:publish --apply"

PublishCommand is what an application runs to take ownership of the views this package offers.

It is spelled out as a constant so that whatever says it -- the refusal below, or a message an application writes for its own operators -- says one thing. A person who is told two different commands for one job tries both.

The command reads the modules the application registered and writes what each one declares, which is why it is the application's command and not this package's: nothing outside the application knows which modules it holds.

View Source
const WalletSlug = "investor"

WalletSlug is the slug of the investor's wallet in arandu-wallet: one per investor, held by their login user, in reais. Every invoice is deposited there and every withdrawal of one is paid out of it.

Variables

View Source
var BankAccountTypes = []string{"checking", "savings"}

BankAccountTypes are the kinds of bank account an investor can be paid into: checking and savings.

View Source
var DefaultPaths = Paths{
	Me: "/me", Contracts: "/contracts", Invoices: "/invoices", Reports: "/reports", PayoutAccounts: "/payout-accounts",
	File: "/file", Statement: "/statement", Projection: "/projection", Costs: "/costs",
	Withdrawal: "/withdrawal", Receipt: "/receipt",
	Admin: "/admin", Investors: "/investors", Suspension: "/suspension", Amendments: "/amendments",
	Closings: "/closings", Due: "/due", Entries: "/entries", Reversal: "/reversal", End: "/end",
	Withdrawals: "/withdrawals", Processing: "/processing", Payment: "/payment", Rejection: "/rejection",
}

DefaultPaths are the English segments, the addresses of earlier releases.

View Source
var ErrNotFound = fmt.Errorf("investor: record not found: %w", model.ErrModelNotFound)

ErrNotFound is returned when no row matches, including when the row exists in another tenant. The two cases are deliberately indistinguishable.

It wraps model.ErrModelNotFound, so the router answers it with 404 and a caller can still ask for it by name with errors.Is.

View Source
var ErrNotWithdrawable = errors.New("investor: this invoice cannot be withdrawn now")

ErrNotWithdrawable is an invoice that cannot be asked for: nothing due, already paid out, or a request for it still waiting.

View Source
var PixKeyTypes = []string{"cpf", "cnpj", "email", "phone", "random"}

PixKeyTypes are the kinds of PIX key an investor can be paid into.

View Source
var PortuguesePaths = Paths{
	Me: "/", Contracts: "/contratos", Invoices: "/faturas", Reports: "/relatorios", PayoutAccounts: "/conta-de-recebimento",
	File: "/arquivo", Statement: "/extrato", Projection: "/projecao", Costs: "/custos",
	Withdrawal: "/saque", Receipt: "/comprovante",
	Admin: "/admin", Investors: "/investidores", Suspension: "/suspensao", Amendments: "/aditivos",
	Closings: "/fechamentos", Due: "/vencidos", Entries: "/lancamentos", Reversal: "/estorno", End: "/encerramento",
	Withdrawals: "/saques", Processing: "/em-pagamento", Payment: "/pagamento", Rejection: "/recusa",
}

PortuguesePaths are the segments in Brazilian Portuguese, for an application whose addresses are written in it: the investor's panel at Prefix itself, /contratos, /faturas/{id}/saque, /faturas/{id}/comprovante, /conta-de-recebimento, and the admin's /investidores and /saques.

Functions

func AllocateCosts

func AllocateCosts(costs []ScopedCost, revenue map[string]int64, contract Scope) int64

AllocateCosts is the part of the costs a contract bears.

revenue is the gross of the window by product, over the whole application -- not only the contract's products, because a cost of the whole application is shared over all of its revenue. A cost whose products earned nothing in the window is borne whole by a contract that covers all of them, and by nobody else: it has no revenue to be shared over.

func CompleteFilters added in v0.5.0

func CompleteFilters(rows []components.TableRow, filters ...components.DataTableFilter) []components.DataTableFilter

CompleteFilters are the faceted filters of a list that holds all its rows, which the browser narrows by what each row says in TableRow.Facets. A filter that names no Options offers the values the rows carry, in the order they first appear; one that does name them keeps only those some row carries, so a value nobody has is not offered. The count beside a value is how many rows carry it. A filter that would offer fewer than two values narrows nothing and is left out.

func CostInWindow

func CostInWindow(item CostItem, start, end Day, billingDay int) int64

CostInWindow is how much of one cost falls in the window [start, end), for a contract that closes on billingDay.

func IsAdmin added in v0.2.0

func IsAdmin(s security.Subject) bool

IsAdmin says whether the subject is this package's admin: they carry AdminRole, or AdminAction among the actions arandu-permission resolved for them. The policy decides with it; an application asks it to decide what to offer, never to authorize.

func Lines added in v0.3.0

func Lines(locale string) translation.Lines

Lines are the sentences this package ships for one locale, keyed the way a translator asks for them ("investor.validation.required"), and nil for a locale it does not ship. An application reads them to see what there is to override, or to check a catalogue of its own against them.

func Locales

func Locales() []string

Locales are the languages the package ships.

func NextOnly added in v0.5.0

func NextOnly(next string) components.Paginator

NextOnly is the page of a list the package reads by cursor and tells nothing else about: the address of the page after this one, not the number of the page, not the total, not the way back. A data table given it as its Paginator draws the one step.

func PublishedPaths

func PublishedPaths() []string

PublishedPaths are the files in the archive, each relative to the root of the application, sorted.

func ViewNames

func ViewNames() []string

ViewNames are the names the published views are rendered by, sorted.

The name is the path under the view root with its separators turned into dots, which is what the view compiler writes into the registration call. It is derived from the same archive the publication carries, so a view that was renamed cannot keep an old name here.

func ViewPackages

func ViewPackages() []string

ViewPackages are the directories the compiled views land in, each relative to the root of the application, sorted and without repeats.

Importing one is what puts its views in the binary: a compiled view calls the registry from init(), and a package nothing imports is not linked at all. The import is named rather than written into bootstrap/app.go, because one line somebody reads beats a file that changed while they were not looking.

Types

type AccountOption

type AccountOption struct{ ID, Label, Kind string }

AccountOption is one payout account a withdrawal can be paid into: its label, and its kind, PayoutPix or PayoutBank.

type AdminCostsPageData

type AdminCostsPageData struct {
	Screen
	Rows            []CostRow
	StoreURL, Today string
}

AdminCostsPageData is the declared costs, for the admin.

type AdminEntriesPageData

type AdminEntriesPageData struct {
	Screen
	Rows                              []EntryRow
	Query, Kind, Sort, Dir            string
	CurrentPage, Pages, Total         int
	URL, StoreURL, CloseDueURL, Today string
	// PageSize is how many rows one page holds, the size the server reads
	// the books with; the table's footer and its pager count by it.
	PageSize int
	// Hide are the keys of the columns the reader switched off, as the
	// address carried them (hide=source&hide=ref), limited to the columns
	// that can be hidden. The table draws its state from them.
	Hide []string
}

AdminEntriesPageData is the admin's books, a page at a time.

type AdminInvestorPageData

type AdminInvestorPageData struct {
	Screen
	Investor                       InvestorRow
	LegalName, LegalRepresentative string
	Contracts                      []ContractRow
	Invoices                       []InvoiceRow
	ContractStoreURL               string
	UpdateURL, SuspensionURL       string
	ReportsURL                     string
	Year, Month                    int
	Today                          string
}

AdminInvestorPageData is one investor, for the admin.

type AdminInvestorsPageData

type AdminInvestorsPageData struct {
	Screen
	Rows          []InvestorRow
	StoreURL      string
	Next, NextURL string
}

AdminInvestorsPageData is the admin's registry.

type AdminWithdrawalsPageData

type AdminWithdrawalsPageData struct {
	Screen
	Rows   []WithdrawalRow
	Status string
	URL    string
}

AdminWithdrawalsPageData is the queue of investors' withdrawals.

type BankAccountRequest added in v0.2.0

type BankAccountRequest struct {
	// Bank is the bank's code or name: "341", "Itaú".
	Bank string
	// Branch is the agency, with its digit when it has one.
	Branch string
	// Number is the account number, with its digit.
	Number string
	// Type is one of BankAccountTypes.
	Type string
}

BankAccountRequest is a bank account an investor declares to be paid into. The holder is not here: an investor is paid into an account in the name and the document of their registration, whatever a form says.

func (BankAccountRequest) Validate added in v0.2.0

func (r BankAccountRequest) Validate() validation.Errors

Validate reports the errors per field.

type CellInput

type CellInput struct {
	Name, Type, Placeholder, Value, Label string
	Required                              bool
}

CellInput is one field of a form drawn inside a table cell.

type ChromeRequest added in v0.2.0

type ChromeRequest struct {
	// Title is the screen's title, already in the request's language, without
	// the application's name Config.TitleSeparator adds to Page.Title: what a
	// heading or a breadcrumb draws.
	Title string
	// Admin says the screen is one of the admin's, mounted under AdminPrefix.
	Admin bool
	// Subject is who is asking, as RequireAuth and Config.Middleware left it.
	Subject security.Subject
	// Page is the page hesape's view.New built for the request.
	Page hview.Page
}

ChromeRequest is what Config.Chrome is asked about one screen.

type Collection

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

Collection is a page of records as one response.

func NewCollection

func NewCollection(records []Investor, cursor string) Collection

NewCollection wraps a page of records for the response. The cursor is what the next request passes back, and is empty when there is no next page.

func (Collection) ToArray

func (c Collection) ToArray() map[string]any

ToArray returns the page under a single key, so that the shape of the response does not change when a second key is added beside it.

func (Collection) With

func (c Collection) With() map[string]any

With returns the cursor of the next page, and nothing when there is none.

type Config

type Config struct {
	// Prefix is the path the routes are mounted under. Empty means
	// DefaultPrefix.
	Prefix string

	// PageSize is how many records one page answers with. Zero means
	// DefaultPageSize, and anything above MaxPageSize is refused rather than
	// clamped: a number somebody wrote and did not get is worse than a number
	// somebody wrote and was told about.
	PageSize int

	// Files is the Disk the signed contracts are kept on: the application's,
	// local or S3, reached with the Grant so every key carries the tenant's
	// prefix. Required: a contract without its signed copy is the one thing
	// this package exists to keep.
	Files *filesystem.Disk

	// Location is the timezone an instant becomes a calendar day in, which is
	// what a period counts by: a sale at 22:00 in Sao Paulo on the 19th is a
	// sale of the 19th, though it is already the 20th in UTC. Nil means
	// DefaultLocation.
	Location *time.Location

	// Wallet is arandu-wallet's service, the application's one instance
	// (walletModule.Service()). Required: an invoice is deposited in the
	// investor's wallet and withdrawn from it, and this package keeps no
	// balance of its own.
	Wallet *wallet.WalletService

	// Payer is the company that pays the investors, printed on the yearly
	// income report. Optional: left empty, the report prints a dash.
	Payer Payer

	// Translator is the application's own catalogue, asked before the one this
	// package ships, key by key: "investor.screen.dashboard_title". Optional.
	Translator *translation.Translator

	// Locale is the language every screen, validation message, report and
	// activity description of this package is written in, whatever the
	// request negotiated: "pt-BR" for an application that speaks Brazilian
	// Portuguese and nothing else. Empty means the locale translation.Middleware
	// or translation.InLocale put on the request, and FallbackLocale (English)
	// when there is none. The package ships the locales Locales() lists; any
	// other reads the application's Translator first and English after it.
	Locale string

	// TitleSeparator joins a screen's title to the application's name in the
	// document title: with " — ", the admin's queue is titled
	// "Saques dos investidores — Alpr.sh". The name is the APP_NAME hesape's
	// view.New read from the request, the one the layout draws as its brand,
	// so nothing here repeats it. Empty, or a request that carries no
	// application name, titles a screen with its own title alone, as earlier
	// releases did.
	TitleSeparator string

	// Paths are the segments every route is built from, under Prefix and
	// AdminPrefix. A field left empty keeps its DefaultPaths value, so the zero
	// value answers at the addresses earlier releases did; PortuguesePaths is
	// the whole set in Brazilian Portuguese.
	Paths Paths

	// AdminPrefix is where the admin's routes are mounted. Empty means Prefix
	// followed by Paths.Admin, which is where earlier releases put them. An
	// application whose team works on another side of the site -- an operator
	// console at /admin -- mounts them there.
	AdminPrefix string

	// Middleware runs on every route of this package after RequireAuth, in
	// order, and AdminMiddleware after it on the admin's routes only. An
	// application whose permissions arandu-permission administers mounts its
	// Roles() in Middleware: RequireAuth puts the subject as the session
	// resolved it, without the actions arandu-permission resolves on each
	// request. A guard of the application's own side -- the operator console's
	// -- goes in AdminMiddleware. Nil runs nothing more. A guard answers "is
	// this request on the right side" and stops; the policy still decides.
	Middleware      []func(http.Handler) http.Handler
	AdminMiddleware []func(http.Handler) http.Handler

	// Chrome is what the application's layout draws around a screen of this
	// package: its sidebar, its navigation, the account menu. It is called once
	// per screen, after RequireAuth and before the page is rendered, and what it
	// answers is carried on the page as Screen.Chrome, where a layout asserts
	// the interface it draws from. An error is returned as the handler's. Nil
	// draws the screens with the page hesape's view.New builds and nothing
	// more.
	Chrome func(ctx *fhttp.Context, req ChromeRequest) (any, error)

	// Activity is arandu-activitylog's logger, the application's one instance
	// (activityModule.Logger()). Every act that changes something -- an
	// investor, a contract, an entry, a cost, a closing, a payout account, a
	// withdrawal asked for, taken, paid or rejected -- is recorded under the
	// Grant it was authorized with, in the log named ActivityLogName. Nil
	// records nothing.
	Activity *activitylog.Logger
}

Config is what the application passes when it wires this package.

A typed struct rather than a map: a misspelled key in a map is a setting that silently keeps its default, and the failure shows up as behaviour nobody asked for rather than as an error. Here a field that does not exist does not compile.

It names no tenant, and that is deliberate. Every route sits behind RequireAuth, so the tenant of every statement is the one the Grant carries, from the session of whoever is asking; a tenant written here would be a second place for one to come from. The zero value is a valid configuration.

func (Config) Validate

func (c Config) Validate() error

Validate reports what the configuration cannot be used with.

It is called by New, so an application with a setting that cannot work fails where it is wired rather than on the first request that needed it.

type Contract

type Contract struct {
	model.Model

	ID       string `db:"id"`
	TenantID string `db:"tenant_id"`

	// InvestorID is whose contract this is.
	InvestorID string `db:"investor_id"`

	// Number is how the contract is called on paper.
	Number string `db:"number"`

	// Version is 1 for the original and grows by one with each amendment.
	Version int `db:"version"`

	// RootID is the original contract every version belongs to: the
	// original's own id on the original, and the same id on each amendment.
	RootID string `db:"root_id"`

	// SignedOn, StartsOn and EndsOn are calendar days. EndsOn is empty while
	// the contract has no end.
	SignedOn Day `db:"signed_on"`
	StartsOn Day `db:"starts_on"`
	EndsOn   Day `db:"ends_on"`

	// ShareBps is the investor's share of the net, in basis points: 1500 is 15%.
	ShareBps int64 `db:"share_bps"`

	// BillingDay is the day of the month the contract's period closes, 1 to 28.
	BillingDay int `db:"billing_day"`

	// AllProducts is a contract over the whole application. When it is false,
	// only the products listed for it count.
	AllProducts Flag `db:"all_products"`

	// Status is whether this version is the one in force.
	Status ContractStatus `db:"status"`

	// The signed file, kept on the Disk the application passed in. FileKey is
	// the key on that Disk; the tenant prefix is the Disk's, from the Grant.
	FileKey    string `db:"file_key"`
	FileName   string `db:"file_name"`
	FileType   string `db:"file_type"`
	FileSize   int64  `db:"file_size"`
	FileSHA256 string `db:"file_sha256"`

	// CreatedBy is the subject who registered this version.
	CreatedBy string    `db:"created_by"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

Contract is what an investor signed: the share of the net they earn, the day the period closes, the products whose revenue counts, and the signed file.

An amendment is a new Contract with the same RootID as the original and the next Version. Nothing is overwritten: the old version stays readable, superseded, and the closings already made against it keep pointing at it.

func (*Contract) Fresh

func (row *Contract) Fresh(ctx context.Context, g auth.Grant, with ...string) (*Contract, error)

Fresh reads the row again, as a new Contract; it shadows the untyped one the embedded model promotes.

func (Contract) InForce

func (c Contract) InForce(day Day) bool

InForce reports whether the contract covers the day.

func (*Contract) Replicate

func (row *Contract) Replicate(except ...string) (*Contract, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

func (*Contract) Supersede

func (c *Contract) Supersede() error

Supersede marks this version as replaced by an amendment.

type ContractCollection

type ContractCollection []*Contract

ContractCollection is rows of Contract, as a query returns them.

func ContractCollectionOf

func ContractCollectionOf(rows model.Rows) ContractCollection

ContractCollectionOf converts rows of the table of Contract. A nil input is a nil collection.

func (ContractCollection) Contains

func (c ContractCollection) Contains(key any) bool

func (ContractCollection) Except

func (c ContractCollection) Except(keys ...any) ContractCollection

func (ContractCollection) Find

func (c ContractCollection) Find(key any) *Contract

func (ContractCollection) FindOrFail

func (c ContractCollection) FindOrFail(key any) (*Contract, error)

func (ContractCollection) Fresh

func (ContractCollection) Load

func (c ContractCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (ContractCollection) LoadCount

func (c ContractCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (ContractCollection) LoadMissing

func (c ContractCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (ContractCollection) ModelKeys

func (c ContractCollection) ModelKeys() []any

func (ContractCollection) Only

func (c ContractCollection) Only(keys ...any) ContractCollection

func (ContractCollection) Pluck

func (c ContractCollection) Pluck(column string) []any

func (ContractCollection) Rows

func (c ContractCollection) Rows() model.Rows

Rows converts the collection back to the core's rows.

func (ContractCollection) ToArray

func (c ContractCollection) ToArray() []map[string]any

func (ContractCollection) Unique

type ContractList

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

ContractList is a list of contracts as one response.

func (ContractList) ToArray

func (c ContractList) ToArray() map[string]any

ToArray returns the list under a single key.

func (ContractList) With

func (c ContractList) With() map[string]any

With returns nothing beside the list.

type ContractProduct

type ContractProduct struct {
	model.Model

	ID         string `db:"id"`
	TenantID   string `db:"tenant_id"`
	ContractID string `db:"contract_id"`
	// ProductID is the application's identifier of the product. This package
	// never resolves it: what a product is belongs to the application.
	ProductID string    `db:"product_id"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

ContractProduct is one product whose revenue counts for a contract that does not cover the whole application.

func (*ContractProduct) Fresh

func (row *ContractProduct) Fresh(ctx context.Context, g auth.Grant, with ...string) (*ContractProduct, error)

Fresh reads the row again, as a new ContractProduct; it shadows the untyped one the embedded model promotes.

func (*ContractProduct) Replicate

func (row *ContractProduct) Replicate(except ...string) (*ContractProduct, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

type ContractProductCollection

type ContractProductCollection []*ContractProduct

ContractProductCollection is rows of ContractProduct, as a query returns them.

func ContractProductCollectionOf

func ContractProductCollectionOf(rows model.Rows) ContractProductCollection

ContractProductCollectionOf converts rows of the table of ContractProduct. A nil input is a nil collection.

func (ContractProductCollection) Contains

func (c ContractProductCollection) Contains(key any) bool

func (ContractProductCollection) Except

func (ContractProductCollection) Find

func (ContractProductCollection) FindOrFail

func (c ContractProductCollection) FindOrFail(key any) (*ContractProduct, error)

func (ContractProductCollection) Fresh

func (ContractProductCollection) Load

func (c ContractProductCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (ContractProductCollection) LoadCount

func (c ContractProductCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (ContractProductCollection) LoadMissing

func (c ContractProductCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (ContractProductCollection) ModelKeys

func (c ContractProductCollection) ModelKeys() []any

func (ContractProductCollection) Only

func (ContractProductCollection) Pluck

func (c ContractProductCollection) Pluck(column string) []any

func (ContractProductCollection) Rows

Rows converts the collection back to the core's rows.

func (ContractProductCollection) ToArray

func (c ContractProductCollection) ToArray() []map[string]any

func (ContractProductCollection) Unique

type ContractProductQuery

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

ContractProductQuery is a query on the table of ContractProduct.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return ContractProduct rows or a value; there is no way to run one without a Grant.

func ContractProducts

func ContractProducts(db model.DB) *ContractProductQuery

ContractProducts starts a query on the table of ContractProduct, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*ContractProductQuery) AddSelect

func (q *ContractProductQuery) AddSelect(columns ...any) *ContractProductQuery

func (*ContractProductQuery) Avg

func (q *ContractProductQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractProductQuery) Base

func (q *ContractProductQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of contract.go -- and for the factory, which builds rows through it.

func (*ContractProductQuery) Chunk

func (q *ContractProductQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(ContractProductCollection, int) (bool, error)) error

func (*ContractProductQuery) Clone

Clone returns an independent copy of the query.

func (*ContractProductQuery) Count

func (q *ContractProductQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*ContractProductQuery) Create

func (q *ContractProductQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*ContractProduct, error)

func (*ContractProductQuery) Cursor

func (*ContractProductQuery) CursorPaginate

func (q *ContractProductQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (ContractProductCollection, *pagination.CursorPage, error)

func (*ContractProductQuery) Decrement

func (q *ContractProductQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*ContractProductQuery) Delete

func (q *ContractProductQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*ContractProductQuery) DoesntExist

func (q *ContractProductQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*ContractProductQuery) DoesntHave

func (q *ContractProductQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) Each

func (q *ContractProductQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*ContractProduct, int) (bool, error)) error

func (*ContractProductQuery) Exists

func (q *ContractProductQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*ContractProductQuery) Find

func (q *ContractProductQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*ContractProduct, error)

func (*ContractProductQuery) FindMany

func (q *ContractProductQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (ContractProductCollection, error)

func (*ContractProductQuery) FindOrFail

func (q *ContractProductQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*ContractProduct, error)

func (*ContractProductQuery) FindOrNew

func (q *ContractProductQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*ContractProduct, error)

func (*ContractProductQuery) First

func (q *ContractProductQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*ContractProduct, error)

First returns the first row, or nil and no error when there is none.

func (*ContractProductQuery) FirstOrCreate

func (q *ContractProductQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*ContractProduct, error)

func (*ContractProductQuery) FirstOrFail

func (q *ContractProductQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*ContractProduct, error)

func (*ContractProductQuery) FirstOrNew

func (q *ContractProductQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*ContractProduct, error)

func (*ContractProductQuery) FirstWhere

func (q *ContractProductQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*ContractProduct, error)

func (*ContractProductQuery) ForPage

func (q *ContractProductQuery) ForPage(page, perPage int) *ContractProductQuery

func (*ContractProductQuery) ForceCreate

func (q *ContractProductQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*ContractProduct, error)

func (*ContractProductQuery) Get

Get runs the query and returns the rows.

func (*ContractProductQuery) GroupBy

func (q *ContractProductQuery) GroupBy(groups ...any) *ContractProductQuery

func (*ContractProductQuery) Has

func (q *ContractProductQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) Increment

func (q *ContractProductQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*ContractProductQuery) Insert

func (q *ContractProductQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*ContractProductQuery) InsertOrIgnore

func (q *ContractProductQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*ContractProductQuery) Join

func (q *ContractProductQuery) Join(table any, first any, args ...any) *ContractProductQuery

func (*ContractProductQuery) Latest

func (q *ContractProductQuery) Latest(column ...string) *ContractProductQuery

func (*ContractProductQuery) Limit

func (*ContractProductQuery) Max

func (q *ContractProductQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractProductQuery) Min

func (q *ContractProductQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractProductQuery) New

New returns an empty ContractProduct on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*ContractProductQuery) Offset

func (q *ContractProductQuery) Offset(value int) *ContractProductQuery

func (*ContractProductQuery) Oldest

func (q *ContractProductQuery) Oldest(column ...string) *ContractProductQuery

func (*ContractProductQuery) OrDoesntHave

func (q *ContractProductQuery) OrDoesntHave(relation string) *ContractProductQuery

func (*ContractProductQuery) OrHas

func (q *ContractProductQuery) OrHas(relation, operator string, count int) *ContractProductQuery

func (*ContractProductQuery) OrWhere

func (q *ContractProductQuery) OrWhere(column any, args ...any) *ContractProductQuery

OrWhere adds an or-where clause; a func(*ContractProductQuery) in place of the column adds a group.

func (*ContractProductQuery) OrWhereDoesntHave

func (q *ContractProductQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) OrWhereHas

func (q *ContractProductQuery) OrWhereHas(relation string, callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) OrWhereNot

func (q *ContractProductQuery) OrWhereNot(column any, args ...any) *ContractProductQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*ContractProductQuery) OrWhereRelation

func (q *ContractProductQuery) OrWhereRelation(relation string, column any, args ...any) *ContractProductQuery

func (*ContractProductQuery) OrderBy

func (q *ContractProductQuery) OrderBy(column any, direction ...string) *ContractProductQuery

func (*ContractProductQuery) OrderByDesc

func (q *ContractProductQuery) OrderByDesc(column any) *ContractProductQuery

func (*ContractProductQuery) Paginate

func (*ContractProductQuery) Pluck

func (q *ContractProductQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*ContractProductQuery) Select

func (q *ContractProductQuery) Select(columns ...any) *ContractProductQuery

func (*ContractProductQuery) SelectRaw

func (q *ContractProductQuery) SelectRaw(expression string, bindings ...any) *ContractProductQuery

func (*ContractProductQuery) SimplePaginate

func (q *ContractProductQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (ContractProductCollection, *pagination.Page, error)

func (*ContractProductQuery) Sole

func (q *ContractProductQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*ContractProduct, error)

func (*ContractProductQuery) SoleValue

func (q *ContractProductQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*ContractProductQuery) Sum

func (q *ContractProductQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractProductQuery) Touch

func (q *ContractProductQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*ContractProductQuery) Update

func (q *ContractProductQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*ContractProductQuery) UpdateOrCreate

func (q *ContractProductQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*ContractProduct, error)

func (*ContractProductQuery) Upsert

func (q *ContractProductQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*ContractProductQuery) Value

func (q *ContractProductQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*ContractProductQuery) ValueOrFail

func (q *ContractProductQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*ContractProductQuery) Where

func (q *ContractProductQuery) Where(column any, args ...any) *ContractProductQuery

Where adds a where clause; a func(*ContractProductQuery) in place of the column adds a group.

func (*ContractProductQuery) WhereBelongsTo

func (q *ContractProductQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *ContractProductQuery

func (*ContractProductQuery) WhereBetween

func (q *ContractProductQuery) WhereBetween(column any, from, to any) *ContractProductQuery

func (*ContractProductQuery) WhereColumn

func (q *ContractProductQuery) WhereColumn(first any, args ...any) *ContractProductQuery

func (*ContractProductQuery) WhereDoesntHave

func (q *ContractProductQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) WhereExists

func (q *ContractProductQuery) WhereExists(callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) WhereHas

func (q *ContractProductQuery) WhereHas(relation string, callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) WhereHasCount

func (q *ContractProductQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *ContractProductQuery

func (*ContractProductQuery) WhereIn

func (q *ContractProductQuery) WhereIn(column any, values []any) *ContractProductQuery

func (*ContractProductQuery) WhereKey

func (*ContractProductQuery) WhereNot

func (q *ContractProductQuery) WhereNot(column any, args ...any) *ContractProductQuery

WhereNot adds a negated where clause, or a negated group.

func (*ContractProductQuery) WhereNotExists

func (q *ContractProductQuery) WhereNotExists(callback func(*query.Builder)) *ContractProductQuery

func (*ContractProductQuery) WhereNotIn

func (q *ContractProductQuery) WhereNotIn(column any, values []any) *ContractProductQuery

func (*ContractProductQuery) WhereNotNull

func (q *ContractProductQuery) WhereNotNull(columns ...any) *ContractProductQuery

func (*ContractProductQuery) WhereNull

func (q *ContractProductQuery) WhereNull(columns ...any) *ContractProductQuery

func (*ContractProductQuery) WhereRelation

func (q *ContractProductQuery) WhereRelation(relation string, column any, args ...any) *ContractProductQuery

func (*ContractProductQuery) With

func (q *ContractProductQuery) With(relations ...string) *ContractProductQuery

func (*ContractProductQuery) WithAvg

func (q *ContractProductQuery) WithAvg(relation, column string) *ContractProductQuery

func (*ContractProductQuery) WithCount

func (q *ContractProductQuery) WithCount(relations ...string) *ContractProductQuery

func (*ContractProductQuery) WithExists

func (q *ContractProductQuery) WithExists(relation string) *ContractProductQuery

func (*ContractProductQuery) WithMax

func (q *ContractProductQuery) WithMax(relation, column string) *ContractProductQuery

func (*ContractProductQuery) WithMin

func (q *ContractProductQuery) WithMin(relation, column string) *ContractProductQuery

func (*ContractProductQuery) WithSum

func (q *ContractProductQuery) WithSum(relation, column string) *ContractProductQuery

func (*ContractProductQuery) Without

func (q *ContractProductQuery) Without(relations ...string) *ContractProductQuery

func (*ContractProductQuery) WithoutGlobalScope

func (q *ContractProductQuery) WithoutGlobalScope(identifier string) *ContractProductQuery

func (*ContractProductQuery) WithoutGlobalScopes

func (q *ContractProductQuery) WithoutGlobalScopes(identifiers ...string) *ContractProductQuery

type ContractQuery

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

ContractQuery is a query on the table of Contract.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Contract rows or a value; there is no way to run one without a Grant.

func Contracts

func Contracts(db model.DB) *ContractQuery

Contracts starts a query on the table of Contract, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*ContractQuery) AddSelect

func (q *ContractQuery) AddSelect(columns ...any) *ContractQuery

func (*ContractQuery) Avg

func (q *ContractQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractQuery) Base

func (q *ContractQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of contract.go -- and for the factory, which builds rows through it.

func (*ContractQuery) Chunk

func (q *ContractQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(ContractCollection, int) (bool, error)) error

func (*ContractQuery) Clone

func (q *ContractQuery) Clone() *ContractQuery

Clone returns an independent copy of the query.

func (*ContractQuery) Count

func (q *ContractQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*ContractQuery) Create

func (q *ContractQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Contract, error)

func (*ContractQuery) Cursor

func (q *ContractQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Contract, error]

func (*ContractQuery) CursorPaginate

func (q *ContractQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (ContractCollection, *pagination.CursorPage, error)

func (*ContractQuery) Decrement

func (q *ContractQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*ContractQuery) Delete

func (q *ContractQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*ContractQuery) DoesntExist

func (q *ContractQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*ContractQuery) DoesntHave

func (q *ContractQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) Each

func (q *ContractQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*Contract, int) (bool, error)) error

func (*ContractQuery) Exists

func (q *ContractQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*ContractQuery) Find

func (q *ContractQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Contract, error)

func (*ContractQuery) FindMany

func (q *ContractQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (ContractCollection, error)

func (*ContractQuery) FindOrFail

func (q *ContractQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Contract, error)

func (*ContractQuery) FindOrNew

func (q *ContractQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Contract, error)

func (*ContractQuery) First

func (q *ContractQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Contract, error)

First returns the first row, or nil and no error when there is none.

func (*ContractQuery) FirstOrCreate

func (q *ContractQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Contract, error)

func (*ContractQuery) FirstOrFail

func (q *ContractQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Contract, error)

func (*ContractQuery) FirstOrNew

func (q *ContractQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Contract, error)

func (*ContractQuery) FirstWhere

func (q *ContractQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Contract, error)

func (*ContractQuery) ForPage

func (q *ContractQuery) ForPage(page, perPage int) *ContractQuery

func (*ContractQuery) ForceCreate

func (q *ContractQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Contract, error)

func (*ContractQuery) Get

func (q *ContractQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (ContractCollection, error)

Get runs the query and returns the rows.

func (*ContractQuery) GroupBy

func (q *ContractQuery) GroupBy(groups ...any) *ContractQuery

func (*ContractQuery) Has

func (q *ContractQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) Increment

func (q *ContractQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*ContractQuery) Insert

func (q *ContractQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*ContractQuery) InsertOrIgnore

func (q *ContractQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*ContractQuery) Join

func (q *ContractQuery) Join(table any, first any, args ...any) *ContractQuery

func (*ContractQuery) Latest

func (q *ContractQuery) Latest(column ...string) *ContractQuery

func (*ContractQuery) Limit

func (q *ContractQuery) Limit(value int) *ContractQuery

func (*ContractQuery) Max

func (q *ContractQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractQuery) Min

func (q *ContractQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractQuery) New

func (q *ContractQuery) New() (*Contract, error)

New returns an empty Contract on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*ContractQuery) Offset

func (q *ContractQuery) Offset(value int) *ContractQuery

func (*ContractQuery) Oldest

func (q *ContractQuery) Oldest(column ...string) *ContractQuery

func (*ContractQuery) OrDoesntHave

func (q *ContractQuery) OrDoesntHave(relation string) *ContractQuery

func (*ContractQuery) OrHas

func (q *ContractQuery) OrHas(relation, operator string, count int) *ContractQuery

func (*ContractQuery) OrWhere

func (q *ContractQuery) OrWhere(column any, args ...any) *ContractQuery

OrWhere adds an or-where clause; a func(*ContractQuery) in place of the column adds a group.

func (*ContractQuery) OrWhereDoesntHave

func (q *ContractQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) OrWhereHas

func (q *ContractQuery) OrWhereHas(relation string, callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) OrWhereNot

func (q *ContractQuery) OrWhereNot(column any, args ...any) *ContractQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*ContractQuery) OrWhereRelation

func (q *ContractQuery) OrWhereRelation(relation string, column any, args ...any) *ContractQuery

func (*ContractQuery) OrderBy

func (q *ContractQuery) OrderBy(column any, direction ...string) *ContractQuery

func (*ContractQuery) OrderByDesc

func (q *ContractQuery) OrderByDesc(column any) *ContractQuery

func (*ContractQuery) Paginate

func (q *ContractQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (ContractCollection, *pagination.LengthAwarePage, error)

func (*ContractQuery) Pluck

func (q *ContractQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*ContractQuery) Select

func (q *ContractQuery) Select(columns ...any) *ContractQuery

func (*ContractQuery) SelectRaw

func (q *ContractQuery) SelectRaw(expression string, bindings ...any) *ContractQuery

func (*ContractQuery) SimplePaginate

func (q *ContractQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (ContractCollection, *pagination.Page, error)

func (*ContractQuery) Sole

func (q *ContractQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Contract, error)

func (*ContractQuery) SoleValue

func (q *ContractQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*ContractQuery) Sum

func (q *ContractQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*ContractQuery) Touch

func (q *ContractQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*ContractQuery) Update

func (q *ContractQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*ContractQuery) UpdateOrCreate

func (q *ContractQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Contract, error)

func (*ContractQuery) Upsert

func (q *ContractQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*ContractQuery) Value

func (q *ContractQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*ContractQuery) ValueOrFail

func (q *ContractQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*ContractQuery) Where

func (q *ContractQuery) Where(column any, args ...any) *ContractQuery

Where adds a where clause; a func(*ContractQuery) in place of the column adds a group.

func (*ContractQuery) WhereBelongsTo

func (q *ContractQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *ContractQuery

func (*ContractQuery) WhereBetween

func (q *ContractQuery) WhereBetween(column any, from, to any) *ContractQuery

func (*ContractQuery) WhereColumn

func (q *ContractQuery) WhereColumn(first any, args ...any) *ContractQuery

func (*ContractQuery) WhereDoesntHave

func (q *ContractQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) WhereExists

func (q *ContractQuery) WhereExists(callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) WhereHas

func (q *ContractQuery) WhereHas(relation string, callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) WhereHasCount

func (q *ContractQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *ContractQuery

func (*ContractQuery) WhereIn

func (q *ContractQuery) WhereIn(column any, values []any) *ContractQuery

func (*ContractQuery) WhereKey

func (q *ContractQuery) WhereKey(id any) *ContractQuery

func (*ContractQuery) WhereNot

func (q *ContractQuery) WhereNot(column any, args ...any) *ContractQuery

WhereNot adds a negated where clause, or a negated group.

func (*ContractQuery) WhereNotExists

func (q *ContractQuery) WhereNotExists(callback func(*query.Builder)) *ContractQuery

func (*ContractQuery) WhereNotIn

func (q *ContractQuery) WhereNotIn(column any, values []any) *ContractQuery

func (*ContractQuery) WhereNotNull

func (q *ContractQuery) WhereNotNull(columns ...any) *ContractQuery

func (*ContractQuery) WhereNull

func (q *ContractQuery) WhereNull(columns ...any) *ContractQuery

func (*ContractQuery) WhereRelation

func (q *ContractQuery) WhereRelation(relation string, column any, args ...any) *ContractQuery

func (*ContractQuery) With

func (q *ContractQuery) With(relations ...string) *ContractQuery

func (*ContractQuery) WithAvg

func (q *ContractQuery) WithAvg(relation, column string) *ContractQuery

func (*ContractQuery) WithCount

func (q *ContractQuery) WithCount(relations ...string) *ContractQuery

func (*ContractQuery) WithExists

func (q *ContractQuery) WithExists(relation string) *ContractQuery

func (*ContractQuery) WithMax

func (q *ContractQuery) WithMax(relation, column string) *ContractQuery

func (*ContractQuery) WithMin

func (q *ContractQuery) WithMin(relation, column string) *ContractQuery

func (*ContractQuery) WithSum

func (q *ContractQuery) WithSum(relation, column string) *ContractQuery

func (*ContractQuery) Without

func (q *ContractQuery) Without(relations ...string) *ContractQuery

func (*ContractQuery) WithoutGlobalScope

func (q *ContractQuery) WithoutGlobalScope(identifier string) *ContractQuery

func (*ContractQuery) WithoutGlobalScopes

func (q *ContractQuery) WithoutGlobalScopes(identifiers ...string) *ContractQuery

type ContractRequest

type ContractRequest struct {
	Number      string
	SignedOn    string
	StartsOn    string
	EndsOn      string
	ShareBps    int64
	BillingDay  int
	AllProducts bool
	Products    []string
	FileName    string
	FileType    string
}

ContractRequest is the input contract for registering a contract or an amendment. The file comes beside it, as a reader, so the bytes never pass through a struct a log might print.

func (ContractRequest) Validate

func (r ContractRequest) Validate() validation.Errors

Validate reports the errors per field.

type ContractResource

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

ContractResource is the list of fields one Contract answers with.

func NewContractResource

func NewContractResource(c Contract, products []string) ContractResource

NewContractResource snapshots one contract and its products for a response.

func (ContractResource) Contract

func (r ContractResource) Contract() Contract

Contract is the version the resource describes.

func (ContractResource) Products

func (r ContractResource) Products() []string

Products are the products the version's revenue counts, empty when it counts the whole application's.

func (ContractResource) ToArray

func (r ContractResource) ToArray() map[string]any

ToArray returns the fields that may leave, by name. The file is described, never linked: it is read through the package's own download route, which asks the policy first.

func (ContractResource) With

func (r ContractResource) With() map[string]any

With returns nothing beside the fields.

type ContractRow

type ContractRow struct {
	// Ends is the last day, or "em aberto" for a contract with none; Period
	// is the two together, as a column draws them.
	ID, Number, Share, Products, Status, Starts, Ends, Period string
	Version, BillingDay                                       int
	Active                                                    bool
	StatementURL, ProjectionURL, FileURL                      string
	CloseURL, AmendURL                                        string
}

ContractRow is one contract as a screen shows it.

type ContractStatus

type ContractStatus string

ContractStatus is whether a contract version is the one in force.

const (
	// ContractActive is the version in force.
	ContractActive ContractStatus = "active"
	// ContractSuperseded was replaced by an amendment.
	ContractSuperseded ContractStatus = "superseded"
)

type CostItem

type CostItem struct {
	model.Model

	ID       string `db:"id"`
	TenantID string `db:"tenant_id"`

	Name     string `db:"name"`
	Category string `db:"category"`

	// Amount is centavos per Recurrence: per month, per year, or once.
	Amount     int64      `db:"amount"`
	Recurrence Recurrence `db:"recurrence"`

	// StartsOn is the first day the cost runs, and the day a one-off cost
	// happens. EndsOn is the last day it runs, empty while it has no end.
	StartsOn Day `db:"starts_on"`
	EndsOn   Day `db:"ends_on"`

	// AllProducts is a cost of the whole application. When it is false, only
	// the products listed for it bear it.
	AllProducts Flag `db:"all_products"`

	CreatedBy string    `db:"created_by"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

CostItem is one cost of running the application that is shared out over the revenue: a server, a cluster, a tool, the invoice issuer.

func (*CostItem) Fresh

func (row *CostItem) Fresh(ctx context.Context, g auth.Grant, with ...string) (*CostItem, error)

Fresh reads the row again, as a new CostItem; it shadows the untyped one the embedded model promotes.

func (*CostItem) Replicate

func (row *CostItem) Replicate(except ...string) (*CostItem, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

type CostItemCollection

type CostItemCollection []*CostItem

CostItemCollection is rows of CostItem, as a query returns them.

func CostItemCollectionOf

func CostItemCollectionOf(rows model.Rows) CostItemCollection

CostItemCollectionOf converts rows of the table of CostItem. A nil input is a nil collection.

func (CostItemCollection) Contains

func (c CostItemCollection) Contains(key any) bool

func (CostItemCollection) Except

func (c CostItemCollection) Except(keys ...any) CostItemCollection

func (CostItemCollection) Find

func (c CostItemCollection) Find(key any) *CostItem

func (CostItemCollection) FindOrFail

func (c CostItemCollection) FindOrFail(key any) (*CostItem, error)

func (CostItemCollection) Fresh

func (CostItemCollection) Load

func (c CostItemCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (CostItemCollection) LoadCount

func (c CostItemCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (CostItemCollection) LoadMissing

func (c CostItemCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (CostItemCollection) ModelKeys

func (c CostItemCollection) ModelKeys() []any

func (CostItemCollection) Only

func (c CostItemCollection) Only(keys ...any) CostItemCollection

func (CostItemCollection) Pluck

func (c CostItemCollection) Pluck(column string) []any

func (CostItemCollection) Rows

func (c CostItemCollection) Rows() model.Rows

Rows converts the collection back to the core's rows.

func (CostItemCollection) ToArray

func (c CostItemCollection) ToArray() []map[string]any

func (CostItemCollection) Unique

type CostItemProduct

type CostItemProduct struct {
	model.Model

	ID         string    `db:"id"`
	TenantID   string    `db:"tenant_id"`
	CostItemID string    `db:"cost_item_id"`
	ProductID  string    `db:"product_id"`
	CreatedAt  time.Time `db:"created_at"`
	UpdatedAt  time.Time `db:"updated_at"`
}

CostItemProduct is one product that bears a cost that is not the whole application's.

func (*CostItemProduct) Fresh

func (row *CostItemProduct) Fresh(ctx context.Context, g auth.Grant, with ...string) (*CostItemProduct, error)

Fresh reads the row again, as a new CostItemProduct; it shadows the untyped one the embedded model promotes.

func (*CostItemProduct) Replicate

func (row *CostItemProduct) Replicate(except ...string) (*CostItemProduct, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

type CostItemProductCollection

type CostItemProductCollection []*CostItemProduct

CostItemProductCollection is rows of CostItemProduct, as a query returns them.

func CostItemProductCollectionOf

func CostItemProductCollectionOf(rows model.Rows) CostItemProductCollection

CostItemProductCollectionOf converts rows of the table of CostItemProduct. A nil input is a nil collection.

func (CostItemProductCollection) Contains

func (c CostItemProductCollection) Contains(key any) bool

func (CostItemProductCollection) Except

func (CostItemProductCollection) Find

func (CostItemProductCollection) FindOrFail

func (c CostItemProductCollection) FindOrFail(key any) (*CostItemProduct, error)

func (CostItemProductCollection) Fresh

func (CostItemProductCollection) Load

func (c CostItemProductCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (CostItemProductCollection) LoadCount

func (c CostItemProductCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (CostItemProductCollection) LoadMissing

func (c CostItemProductCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (CostItemProductCollection) ModelKeys

func (c CostItemProductCollection) ModelKeys() []any

func (CostItemProductCollection) Only

func (CostItemProductCollection) Pluck

func (c CostItemProductCollection) Pluck(column string) []any

func (CostItemProductCollection) Rows

Rows converts the collection back to the core's rows.

func (CostItemProductCollection) ToArray

func (c CostItemProductCollection) ToArray() []map[string]any

func (CostItemProductCollection) Unique

type CostItemProductQuery

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

CostItemProductQuery is a query on the table of CostItemProduct.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return CostItemProduct rows or a value; there is no way to run one without a Grant.

func CostItemProducts

func CostItemProducts(db model.DB) *CostItemProductQuery

CostItemProducts starts a query on the table of CostItemProduct, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*CostItemProductQuery) AddSelect

func (q *CostItemProductQuery) AddSelect(columns ...any) *CostItemProductQuery

func (*CostItemProductQuery) Avg

func (q *CostItemProductQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemProductQuery) Base

func (q *CostItemProductQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of ledger.go -- and for the factory, which builds rows through it.

func (*CostItemProductQuery) Chunk

func (q *CostItemProductQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(CostItemProductCollection, int) (bool, error)) error

func (*CostItemProductQuery) Clone

Clone returns an independent copy of the query.

func (*CostItemProductQuery) Count

func (q *CostItemProductQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*CostItemProductQuery) Create

func (q *CostItemProductQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*CostItemProduct, error)

func (*CostItemProductQuery) Cursor

func (*CostItemProductQuery) CursorPaginate

func (q *CostItemProductQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (CostItemProductCollection, *pagination.CursorPage, error)

func (*CostItemProductQuery) Decrement

func (q *CostItemProductQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*CostItemProductQuery) Delete

func (q *CostItemProductQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*CostItemProductQuery) DoesntExist

func (q *CostItemProductQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*CostItemProductQuery) DoesntHave

func (q *CostItemProductQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) Each

func (q *CostItemProductQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*CostItemProduct, int) (bool, error)) error

func (*CostItemProductQuery) Exists

func (q *CostItemProductQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*CostItemProductQuery) Find

func (q *CostItemProductQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*CostItemProduct, error)

func (*CostItemProductQuery) FindMany

func (q *CostItemProductQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (CostItemProductCollection, error)

func (*CostItemProductQuery) FindOrFail

func (q *CostItemProductQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*CostItemProduct, error)

func (*CostItemProductQuery) FindOrNew

func (q *CostItemProductQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*CostItemProduct, error)

func (*CostItemProductQuery) First

func (q *CostItemProductQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*CostItemProduct, error)

First returns the first row, or nil and no error when there is none.

func (*CostItemProductQuery) FirstOrCreate

func (q *CostItemProductQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*CostItemProduct, error)

func (*CostItemProductQuery) FirstOrFail

func (q *CostItemProductQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*CostItemProduct, error)

func (*CostItemProductQuery) FirstOrNew

func (q *CostItemProductQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*CostItemProduct, error)

func (*CostItemProductQuery) FirstWhere

func (q *CostItemProductQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*CostItemProduct, error)

func (*CostItemProductQuery) ForPage

func (q *CostItemProductQuery) ForPage(page, perPage int) *CostItemProductQuery

func (*CostItemProductQuery) ForceCreate

func (q *CostItemProductQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*CostItemProduct, error)

func (*CostItemProductQuery) Get

Get runs the query and returns the rows.

func (*CostItemProductQuery) GroupBy

func (q *CostItemProductQuery) GroupBy(groups ...any) *CostItemProductQuery

func (*CostItemProductQuery) Has

func (q *CostItemProductQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) Increment

func (q *CostItemProductQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*CostItemProductQuery) Insert

func (q *CostItemProductQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*CostItemProductQuery) InsertOrIgnore

func (q *CostItemProductQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*CostItemProductQuery) Join

func (q *CostItemProductQuery) Join(table any, first any, args ...any) *CostItemProductQuery

func (*CostItemProductQuery) Latest

func (q *CostItemProductQuery) Latest(column ...string) *CostItemProductQuery

func (*CostItemProductQuery) Limit

func (*CostItemProductQuery) Max

func (q *CostItemProductQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemProductQuery) Min

func (q *CostItemProductQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemProductQuery) New

New returns an empty CostItemProduct on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*CostItemProductQuery) Offset

func (q *CostItemProductQuery) Offset(value int) *CostItemProductQuery

func (*CostItemProductQuery) Oldest

func (q *CostItemProductQuery) Oldest(column ...string) *CostItemProductQuery

func (*CostItemProductQuery) OrDoesntHave

func (q *CostItemProductQuery) OrDoesntHave(relation string) *CostItemProductQuery

func (*CostItemProductQuery) OrHas

func (q *CostItemProductQuery) OrHas(relation, operator string, count int) *CostItemProductQuery

func (*CostItemProductQuery) OrWhere

func (q *CostItemProductQuery) OrWhere(column any, args ...any) *CostItemProductQuery

OrWhere adds an or-where clause; a func(*CostItemProductQuery) in place of the column adds a group.

func (*CostItemProductQuery) OrWhereDoesntHave

func (q *CostItemProductQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) OrWhereHas

func (q *CostItemProductQuery) OrWhereHas(relation string, callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) OrWhereNot

func (q *CostItemProductQuery) OrWhereNot(column any, args ...any) *CostItemProductQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*CostItemProductQuery) OrWhereRelation

func (q *CostItemProductQuery) OrWhereRelation(relation string, column any, args ...any) *CostItemProductQuery

func (*CostItemProductQuery) OrderBy

func (q *CostItemProductQuery) OrderBy(column any, direction ...string) *CostItemProductQuery

func (*CostItemProductQuery) OrderByDesc

func (q *CostItemProductQuery) OrderByDesc(column any) *CostItemProductQuery

func (*CostItemProductQuery) Paginate

func (*CostItemProductQuery) Pluck

func (q *CostItemProductQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*CostItemProductQuery) Select

func (q *CostItemProductQuery) Select(columns ...any) *CostItemProductQuery

func (*CostItemProductQuery) SelectRaw

func (q *CostItemProductQuery) SelectRaw(expression string, bindings ...any) *CostItemProductQuery

func (*CostItemProductQuery) SimplePaginate

func (q *CostItemProductQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (CostItemProductCollection, *pagination.Page, error)

func (*CostItemProductQuery) Sole

func (q *CostItemProductQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*CostItemProduct, error)

func (*CostItemProductQuery) SoleValue

func (q *CostItemProductQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*CostItemProductQuery) Sum

func (q *CostItemProductQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemProductQuery) Touch

func (q *CostItemProductQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*CostItemProductQuery) Update

func (q *CostItemProductQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*CostItemProductQuery) UpdateOrCreate

func (q *CostItemProductQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*CostItemProduct, error)

func (*CostItemProductQuery) Upsert

func (q *CostItemProductQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*CostItemProductQuery) Value

func (q *CostItemProductQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*CostItemProductQuery) ValueOrFail

func (q *CostItemProductQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*CostItemProductQuery) Where

func (q *CostItemProductQuery) Where(column any, args ...any) *CostItemProductQuery

Where adds a where clause; a func(*CostItemProductQuery) in place of the column adds a group.

func (*CostItemProductQuery) WhereBelongsTo

func (q *CostItemProductQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *CostItemProductQuery

func (*CostItemProductQuery) WhereBetween

func (q *CostItemProductQuery) WhereBetween(column any, from, to any) *CostItemProductQuery

func (*CostItemProductQuery) WhereColumn

func (q *CostItemProductQuery) WhereColumn(first any, args ...any) *CostItemProductQuery

func (*CostItemProductQuery) WhereDoesntHave

func (q *CostItemProductQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) WhereExists

func (q *CostItemProductQuery) WhereExists(callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) WhereHas

func (q *CostItemProductQuery) WhereHas(relation string, callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) WhereHasCount

func (q *CostItemProductQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *CostItemProductQuery

func (*CostItemProductQuery) WhereIn

func (q *CostItemProductQuery) WhereIn(column any, values []any) *CostItemProductQuery

func (*CostItemProductQuery) WhereKey

func (*CostItemProductQuery) WhereNot

func (q *CostItemProductQuery) WhereNot(column any, args ...any) *CostItemProductQuery

WhereNot adds a negated where clause, or a negated group.

func (*CostItemProductQuery) WhereNotExists

func (q *CostItemProductQuery) WhereNotExists(callback func(*query.Builder)) *CostItemProductQuery

func (*CostItemProductQuery) WhereNotIn

func (q *CostItemProductQuery) WhereNotIn(column any, values []any) *CostItemProductQuery

func (*CostItemProductQuery) WhereNotNull

func (q *CostItemProductQuery) WhereNotNull(columns ...any) *CostItemProductQuery

func (*CostItemProductQuery) WhereNull

func (q *CostItemProductQuery) WhereNull(columns ...any) *CostItemProductQuery

func (*CostItemProductQuery) WhereRelation

func (q *CostItemProductQuery) WhereRelation(relation string, column any, args ...any) *CostItemProductQuery

func (*CostItemProductQuery) With

func (q *CostItemProductQuery) With(relations ...string) *CostItemProductQuery

func (*CostItemProductQuery) WithAvg

func (q *CostItemProductQuery) WithAvg(relation, column string) *CostItemProductQuery

func (*CostItemProductQuery) WithCount

func (q *CostItemProductQuery) WithCount(relations ...string) *CostItemProductQuery

func (*CostItemProductQuery) WithExists

func (q *CostItemProductQuery) WithExists(relation string) *CostItemProductQuery

func (*CostItemProductQuery) WithMax

func (q *CostItemProductQuery) WithMax(relation, column string) *CostItemProductQuery

func (*CostItemProductQuery) WithMin

func (q *CostItemProductQuery) WithMin(relation, column string) *CostItemProductQuery

func (*CostItemProductQuery) WithSum

func (q *CostItemProductQuery) WithSum(relation, column string) *CostItemProductQuery

func (*CostItemProductQuery) Without

func (q *CostItemProductQuery) Without(relations ...string) *CostItemProductQuery

func (*CostItemProductQuery) WithoutGlobalScope

func (q *CostItemProductQuery) WithoutGlobalScope(identifier string) *CostItemProductQuery

func (*CostItemProductQuery) WithoutGlobalScopes

func (q *CostItemProductQuery) WithoutGlobalScopes(identifiers ...string) *CostItemProductQuery

type CostItemQuery

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

CostItemQuery is a query on the table of CostItem.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return CostItem rows or a value; there is no way to run one without a Grant.

func CostItems

func CostItems(db model.DB) *CostItemQuery

CostItems starts a query on the table of CostItem, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*CostItemQuery) AddSelect

func (q *CostItemQuery) AddSelect(columns ...any) *CostItemQuery

func (*CostItemQuery) Avg

func (q *CostItemQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemQuery) Base

func (q *CostItemQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of ledger.go -- and for the factory, which builds rows through it.

func (*CostItemQuery) Chunk

func (q *CostItemQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(CostItemCollection, int) (bool, error)) error

func (*CostItemQuery) Clone

func (q *CostItemQuery) Clone() *CostItemQuery

Clone returns an independent copy of the query.

func (*CostItemQuery) Count

func (q *CostItemQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*CostItemQuery) Create

func (q *CostItemQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*CostItem, error)

func (*CostItemQuery) Cursor

func (q *CostItemQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*CostItem, error]

func (*CostItemQuery) CursorPaginate

func (q *CostItemQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (CostItemCollection, *pagination.CursorPage, error)

func (*CostItemQuery) Decrement

func (q *CostItemQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*CostItemQuery) Delete

func (q *CostItemQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*CostItemQuery) DoesntExist

func (q *CostItemQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*CostItemQuery) DoesntHave

func (q *CostItemQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) Each

func (q *CostItemQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*CostItem, int) (bool, error)) error

func (*CostItemQuery) Exists

func (q *CostItemQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*CostItemQuery) Find

func (q *CostItemQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*CostItem, error)

func (*CostItemQuery) FindMany

func (q *CostItemQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (CostItemCollection, error)

func (*CostItemQuery) FindOrFail

func (q *CostItemQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*CostItem, error)

func (*CostItemQuery) FindOrNew

func (q *CostItemQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*CostItem, error)

func (*CostItemQuery) First

func (q *CostItemQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*CostItem, error)

First returns the first row, or nil and no error when there is none.

func (*CostItemQuery) FirstOrCreate

func (q *CostItemQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*CostItem, error)

func (*CostItemQuery) FirstOrFail

func (q *CostItemQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*CostItem, error)

func (*CostItemQuery) FirstOrNew

func (q *CostItemQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*CostItem, error)

func (*CostItemQuery) FirstWhere

func (q *CostItemQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*CostItem, error)

func (*CostItemQuery) ForPage

func (q *CostItemQuery) ForPage(page, perPage int) *CostItemQuery

func (*CostItemQuery) ForceCreate

func (q *CostItemQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*CostItem, error)

func (*CostItemQuery) Get

func (q *CostItemQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (CostItemCollection, error)

Get runs the query and returns the rows.

func (*CostItemQuery) GroupBy

func (q *CostItemQuery) GroupBy(groups ...any) *CostItemQuery

func (*CostItemQuery) Has

func (q *CostItemQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) Increment

func (q *CostItemQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*CostItemQuery) Insert

func (q *CostItemQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*CostItemQuery) InsertOrIgnore

func (q *CostItemQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*CostItemQuery) Join

func (q *CostItemQuery) Join(table any, first any, args ...any) *CostItemQuery

func (*CostItemQuery) Latest

func (q *CostItemQuery) Latest(column ...string) *CostItemQuery

func (*CostItemQuery) Limit

func (q *CostItemQuery) Limit(value int) *CostItemQuery

func (*CostItemQuery) Max

func (q *CostItemQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemQuery) Min

func (q *CostItemQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemQuery) New

func (q *CostItemQuery) New() (*CostItem, error)

New returns an empty CostItem on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*CostItemQuery) Offset

func (q *CostItemQuery) Offset(value int) *CostItemQuery

func (*CostItemQuery) Oldest

func (q *CostItemQuery) Oldest(column ...string) *CostItemQuery

func (*CostItemQuery) OrDoesntHave

func (q *CostItemQuery) OrDoesntHave(relation string) *CostItemQuery

func (*CostItemQuery) OrHas

func (q *CostItemQuery) OrHas(relation, operator string, count int) *CostItemQuery

func (*CostItemQuery) OrWhere

func (q *CostItemQuery) OrWhere(column any, args ...any) *CostItemQuery

OrWhere adds an or-where clause; a func(*CostItemQuery) in place of the column adds a group.

func (*CostItemQuery) OrWhereDoesntHave

func (q *CostItemQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) OrWhereHas

func (q *CostItemQuery) OrWhereHas(relation string, callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) OrWhereNot

func (q *CostItemQuery) OrWhereNot(column any, args ...any) *CostItemQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*CostItemQuery) OrWhereRelation

func (q *CostItemQuery) OrWhereRelation(relation string, column any, args ...any) *CostItemQuery

func (*CostItemQuery) OrderBy

func (q *CostItemQuery) OrderBy(column any, direction ...string) *CostItemQuery

func (*CostItemQuery) OrderByDesc

func (q *CostItemQuery) OrderByDesc(column any) *CostItemQuery

func (*CostItemQuery) Paginate

func (q *CostItemQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (CostItemCollection, *pagination.LengthAwarePage, error)

func (*CostItemQuery) Pluck

func (q *CostItemQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*CostItemQuery) Select

func (q *CostItemQuery) Select(columns ...any) *CostItemQuery

func (*CostItemQuery) SelectRaw

func (q *CostItemQuery) SelectRaw(expression string, bindings ...any) *CostItemQuery

func (*CostItemQuery) SimplePaginate

func (q *CostItemQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (CostItemCollection, *pagination.Page, error)

func (*CostItemQuery) Sole

func (q *CostItemQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*CostItem, error)

func (*CostItemQuery) SoleValue

func (q *CostItemQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*CostItemQuery) Sum

func (q *CostItemQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*CostItemQuery) Touch

func (q *CostItemQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*CostItemQuery) Update

func (q *CostItemQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*CostItemQuery) UpdateOrCreate

func (q *CostItemQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*CostItem, error)

func (*CostItemQuery) Upsert

func (q *CostItemQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*CostItemQuery) Value

func (q *CostItemQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*CostItemQuery) ValueOrFail

func (q *CostItemQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*CostItemQuery) Where

func (q *CostItemQuery) Where(column any, args ...any) *CostItemQuery

Where adds a where clause; a func(*CostItemQuery) in place of the column adds a group.

func (*CostItemQuery) WhereBelongsTo

func (q *CostItemQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *CostItemQuery

func (*CostItemQuery) WhereBetween

func (q *CostItemQuery) WhereBetween(column any, from, to any) *CostItemQuery

func (*CostItemQuery) WhereColumn

func (q *CostItemQuery) WhereColumn(first any, args ...any) *CostItemQuery

func (*CostItemQuery) WhereDoesntHave

func (q *CostItemQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) WhereExists

func (q *CostItemQuery) WhereExists(callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) WhereHas

func (q *CostItemQuery) WhereHas(relation string, callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) WhereHasCount

func (q *CostItemQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *CostItemQuery

func (*CostItemQuery) WhereIn

func (q *CostItemQuery) WhereIn(column any, values []any) *CostItemQuery

func (*CostItemQuery) WhereKey

func (q *CostItemQuery) WhereKey(id any) *CostItemQuery

func (*CostItemQuery) WhereNot

func (q *CostItemQuery) WhereNot(column any, args ...any) *CostItemQuery

WhereNot adds a negated where clause, or a negated group.

func (*CostItemQuery) WhereNotExists

func (q *CostItemQuery) WhereNotExists(callback func(*query.Builder)) *CostItemQuery

func (*CostItemQuery) WhereNotIn

func (q *CostItemQuery) WhereNotIn(column any, values []any) *CostItemQuery

func (*CostItemQuery) WhereNotNull

func (q *CostItemQuery) WhereNotNull(columns ...any) *CostItemQuery

func (*CostItemQuery) WhereNull

func (q *CostItemQuery) WhereNull(columns ...any) *CostItemQuery

func (*CostItemQuery) WhereRelation

func (q *CostItemQuery) WhereRelation(relation string, column any, args ...any) *CostItemQuery

func (*CostItemQuery) With

func (q *CostItemQuery) With(relations ...string) *CostItemQuery

func (*CostItemQuery) WithAvg

func (q *CostItemQuery) WithAvg(relation, column string) *CostItemQuery

func (*CostItemQuery) WithCount

func (q *CostItemQuery) WithCount(relations ...string) *CostItemQuery

func (*CostItemQuery) WithExists

func (q *CostItemQuery) WithExists(relation string) *CostItemQuery

func (*CostItemQuery) WithMax

func (q *CostItemQuery) WithMax(relation, column string) *CostItemQuery

func (*CostItemQuery) WithMin

func (q *CostItemQuery) WithMin(relation, column string) *CostItemQuery

func (*CostItemQuery) WithSum

func (q *CostItemQuery) WithSum(relation, column string) *CostItemQuery

func (*CostItemQuery) Without

func (q *CostItemQuery) Without(relations ...string) *CostItemQuery

func (*CostItemQuery) WithoutGlobalScope

func (q *CostItemQuery) WithoutGlobalScope(identifier string) *CostItemQuery

func (*CostItemQuery) WithoutGlobalScopes

func (q *CostItemQuery) WithoutGlobalScopes(identifiers ...string) *CostItemQuery

type CostRequest

type CostRequest struct {
	Name        string
	Category    string
	Amount      int64
	Recurrence  Recurrence
	StartsOn    string
	EndsOn      string
	AllProducts bool
	Products    []string
}

CostRequest declares one cost of running the application.

func (CostRequest) Validate

func (r CostRequest) Validate() validation.Errors

Validate reports the errors per field.

type CostRow

type CostRow struct {
	ID, Name, Category, Amount, Recurrence, Starts, Ends, Scope, EndURL string
	Ended                                                               bool
}

CostRow is one declared cost.

type CostView

type CostView struct {
	Item     CostItem
	Products []string
}

CostView is one cost with the products that bear it.

type CreateRequest

type CreateRequest struct {
	// UserID is the login user who is this investor.
	UserID string
	// Kind is Person or Company.
	Kind PersonKind
	// Document is the CPF or the CNPJ, formatted or not.
	Document string
	// Name is the person's name, or the company's trade name.
	Name string
	// LegalName is the company's registered name. Required for a company.
	LegalName string
	// LegalRepresentative is who signs for the company. Required for a company.
	LegalRepresentative string
	// Email is where the investor is reached.
	Email string
}

CreateRequest is the input contract for registering an investor.

The fields are explicit and there is no mass assignment, so a request body cannot write a column nobody meant to expose. There is no TenantID here and there must never be one: the tenant comes from the Grant, which comes from the session.

func (CreateRequest) Validate

func (r CreateRequest) Validate() validation.Errors

Validate reports the errors per field.

type DashboardPageData

type DashboardPageData struct {
	Screen
	Investor                                      string
	Document                                      string
	Available, Held, ReceivedYear, WithdrawnTotal string
	Contracts                                     []ContractRow
	Invoices                                      []InvoiceRow
	Accounts                                      []AccountOption
	Year, Month                                   int
	// ReportsURL is the base of the reports; PixURL, the address a payout
	// account is declared at, is the same as PayoutAccountsURL and kept for a
	// published view that still reads it.
	ReportsURL, PixURL, PayoutAccountsURL string
	// ReportMonths and ReportYears are the reports offered: none before the
	// investor's first contract started.
	ReportMonths, ReportYears []ReportLink
}

DashboardPageData is the investor's own panel.

type Day

type Day string

Day is a calendar day, stored as YYYY-MM-DD.

A day and not a timestamp, because a contract starts on the 20th in the customer's calendar, not at an instant in some timezone, and a timestamp column turns that into a different day on every server that reads it in another zone. The empty Day is "no day", which is how an open end is kept.

func DayOf

func DayOf(t time.Time, loc *time.Location) Day

DayOf is the calendar day of an instant, in the location given.

func ParseDay

func ParseDay(s string) (Day, error)

ParseDay reads a day, refusing anything that is not a real date.

func (Day) AddDays

func (d Day) AddDays(n int) Day

AddDays moves the day by n days.

func (Day) Before

func (d Day) Before(other Day) bool

Before reports whether d is earlier than other. An unset day is never before anything.

func (Day) DaysUntil

func (d Day) DaysUntil(other Day) int

DaysUntil is the number of days from d to other, negative when other is earlier.

func (Day) IsZero

func (d Day) IsZero() bool

IsZero reports whether the day is unset.

func (Day) Time

func (d Day) Time() time.Time

Time is the day at midnight UTC, the one instant used for arithmetic.

type EntriesQuery

type EntriesQuery struct {
	Search  string
	Kind    EntryKind
	Sort    string
	Dir     string
	Page    int
	PerPage int
}

EntriesQuery narrows the admin's books. Page counts from one.

type Entry

type Entry struct {
	model.Model

	ID       string `db:"id"`
	TenantID string `db:"tenant_id"`

	// ProductID is the application's product the money belongs to.
	ProductID string `db:"product_id"`

	// Kind is what the entry is.
	Kind EntryKind `db:"kind"`

	// OccurredAt is when it happened, and OccurredOn the calendar day of that
	// instant in the application's timezone -- the day the periods count by.
	OccurredAt time.Time `db:"occurred_at"`
	OccurredOn Day       `db:"occurred_on"`

	// Gross and Fee are centavos. Net is Gross - Fee, stored so a statement
	// sums one column.
	Gross int64 `db:"gross"`
	Fee   int64 `db:"fee"`
	Net   int64 `db:"net"`

	// FeeDetail says what the fee was: "gateway", "invoice", "withdrawal".
	FeeDetail string `db:"fee_detail"`

	Description string `db:"description"`

	// Source is where the entry came from: the application's code, or the
	// admin by hand.
	Source EntrySource `db:"source"`

	// ExternalRef is the caller's identifier of the event, unique per tenant:
	// sending the same event twice records it once.
	ExternalRef string `db:"external_ref"`

	// ReversesID is the entry a reversal undoes. Empty on every other kind.
	ReversesID string `db:"reverses_id"`

	CreatedBy string    `db:"created_by"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

Entry is one movement of the application's money that the investors' statements are made of: a sale, a renewal, a refund, a fee, an expense, a tax, an adjustment, or the reversal of one of them.

Money is in centavos, signed: Gross is what the entry adds to the revenue (negative for a refund), Fee is what was taken from it on the way (the gateway, the invoice issuer, a tax). The net of the entry is Gross - Fee.

An entry is never edited. A wrong one is undone by a reversal, a new entry that names it and carries the opposite amounts, so the statement of a closed period never changes after it was closed.

func (*Entry) Fresh

func (row *Entry) Fresh(ctx context.Context, g auth.Grant, with ...string) (*Entry, error)

Fresh reads the row again, as a new Entry; it shadows the untyped one the embedded model promotes.

func (*Entry) Replicate

func (row *Entry) Replicate(except ...string) (*Entry, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

func (Entry) Reverse

func (e Entry) Reverse() (Entry, error)

Reverse builds the reversal of an entry: the opposite amounts, the same product, pointing at it. The caller stamps the identifiers and the time.

type EntryCollection

type EntryCollection []*Entry

EntryCollection is rows of Entry, as a query returns them.

func EntryCollectionOf

func EntryCollectionOf(rows model.Rows) EntryCollection

EntryCollectionOf converts rows of the table of Entry. A nil input is a nil collection.

func (EntryCollection) Contains

func (c EntryCollection) Contains(key any) bool

func (EntryCollection) Except

func (c EntryCollection) Except(keys ...any) EntryCollection

func (EntryCollection) Find

func (c EntryCollection) Find(key any) *Entry

func (EntryCollection) FindOrFail

func (c EntryCollection) FindOrFail(key any) (*Entry, error)

func (EntryCollection) Fresh

func (c EntryCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (EntryCollection, error)

func (EntryCollection) Load

func (c EntryCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (EntryCollection) LoadCount

func (c EntryCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (EntryCollection) LoadMissing

func (c EntryCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (EntryCollection) ModelKeys

func (c EntryCollection) ModelKeys() []any

func (EntryCollection) Only

func (c EntryCollection) Only(keys ...any) EntryCollection

func (EntryCollection) Pluck

func (c EntryCollection) Pluck(column string) []any

func (EntryCollection) Rows

func (c EntryCollection) Rows() model.Rows

Rows converts the collection back to the core's rows.

func (EntryCollection) ToArray

func (c EntryCollection) ToArray() []map[string]any

func (EntryCollection) Unique

func (c EntryCollection) Unique() EntryCollection

type EntryKind

type EntryKind string

EntryKind is what an entry is.

const (
	// KindSale is a first purchase.
	KindSale EntryKind = "sale"
	// KindRenewal is a recurring payment of something already sold.
	KindRenewal EntryKind = "renewal"
	// KindRefund is money given back to a buyer: negative revenue.
	KindRefund EntryKind = "refund"
	// KindFee is a charge taken on the way that is not tied to one sale.
	KindFee EntryKind = "fee"
	// KindExpense is money spent that is not one of the declared costs.
	KindExpense EntryKind = "expense"
	// KindTax is a tax paid.
	KindTax EntryKind = "tax"
	// KindAdjustment corrects the revenue by hand, either way.
	KindAdjustment EntryKind = "adjustment"
	// KindReversal undoes another entry.
	KindReversal EntryKind = "reversal"
)

type EntryQuery

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

EntryQuery is a query on the table of Entry.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Entry rows or a value; there is no way to run one without a Grant.

func Entries

func Entries(db model.DB) *EntryQuery

Entries starts a query on the table of Entry, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*EntryQuery) AddSelect

func (q *EntryQuery) AddSelect(columns ...any) *EntryQuery

func (*EntryQuery) Avg

func (q *EntryQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*EntryQuery) Base

func (q *EntryQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of ledger.go -- and for the factory, which builds rows through it.

func (*EntryQuery) Chunk

func (q *EntryQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(EntryCollection, int) (bool, error)) error

func (*EntryQuery) Clone

func (q *EntryQuery) Clone() *EntryQuery

Clone returns an independent copy of the query.

func (*EntryQuery) Count

func (q *EntryQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*EntryQuery) Create

func (q *EntryQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Entry, error)

func (*EntryQuery) Cursor

func (q *EntryQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Entry, error]

func (*EntryQuery) CursorPaginate

func (q *EntryQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (EntryCollection, *pagination.CursorPage, error)

func (*EntryQuery) Decrement

func (q *EntryQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*EntryQuery) Delete

func (q *EntryQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*EntryQuery) DoesntExist

func (q *EntryQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*EntryQuery) DoesntHave

func (q *EntryQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) Each

func (q *EntryQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*Entry, int) (bool, error)) error

func (*EntryQuery) Exists

func (q *EntryQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*EntryQuery) Find

func (q *EntryQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Entry, error)

func (*EntryQuery) FindMany

func (q *EntryQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (EntryCollection, error)

func (*EntryQuery) FindOrFail

func (q *EntryQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Entry, error)

func (*EntryQuery) FindOrNew

func (q *EntryQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Entry, error)

func (*EntryQuery) First

func (q *EntryQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Entry, error)

First returns the first row, or nil and no error when there is none.

func (*EntryQuery) FirstOrCreate

func (q *EntryQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Entry, error)

func (*EntryQuery) FirstOrFail

func (q *EntryQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Entry, error)

func (*EntryQuery) FirstOrNew

func (q *EntryQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Entry, error)

func (*EntryQuery) FirstWhere

func (q *EntryQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Entry, error)

func (*EntryQuery) ForPage

func (q *EntryQuery) ForPage(page, perPage int) *EntryQuery

func (*EntryQuery) ForceCreate

func (q *EntryQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Entry, error)

func (*EntryQuery) Get

func (q *EntryQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (EntryCollection, error)

Get runs the query and returns the rows.

func (*EntryQuery) GroupBy

func (q *EntryQuery) GroupBy(groups ...any) *EntryQuery

func (*EntryQuery) Has

func (q *EntryQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) Increment

func (q *EntryQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*EntryQuery) Insert

func (q *EntryQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*EntryQuery) InsertOrIgnore

func (q *EntryQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*EntryQuery) Join

func (q *EntryQuery) Join(table any, first any, args ...any) *EntryQuery

func (*EntryQuery) Latest

func (q *EntryQuery) Latest(column ...string) *EntryQuery

func (*EntryQuery) Limit

func (q *EntryQuery) Limit(value int) *EntryQuery

func (*EntryQuery) Max

func (q *EntryQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*EntryQuery) Min

func (q *EntryQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*EntryQuery) New

func (q *EntryQuery) New() (*Entry, error)

New returns an empty Entry on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*EntryQuery) Offset

func (q *EntryQuery) Offset(value int) *EntryQuery

func (*EntryQuery) Oldest

func (q *EntryQuery) Oldest(column ...string) *EntryQuery

func (*EntryQuery) OrDoesntHave

func (q *EntryQuery) OrDoesntHave(relation string) *EntryQuery

func (*EntryQuery) OrHas

func (q *EntryQuery) OrHas(relation, operator string, count int) *EntryQuery

func (*EntryQuery) OrWhere

func (q *EntryQuery) OrWhere(column any, args ...any) *EntryQuery

OrWhere adds an or-where clause; a func(*EntryQuery) in place of the column adds a group.

func (*EntryQuery) OrWhereDoesntHave

func (q *EntryQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) OrWhereHas

func (q *EntryQuery) OrWhereHas(relation string, callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) OrWhereNot

func (q *EntryQuery) OrWhereNot(column any, args ...any) *EntryQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*EntryQuery) OrWhereRelation

func (q *EntryQuery) OrWhereRelation(relation string, column any, args ...any) *EntryQuery

func (*EntryQuery) OrderBy

func (q *EntryQuery) OrderBy(column any, direction ...string) *EntryQuery

func (*EntryQuery) OrderByDesc

func (q *EntryQuery) OrderByDesc(column any) *EntryQuery

func (*EntryQuery) Paginate

func (q *EntryQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (EntryCollection, *pagination.LengthAwarePage, error)

func (*EntryQuery) Pluck

func (q *EntryQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*EntryQuery) Select

func (q *EntryQuery) Select(columns ...any) *EntryQuery

func (*EntryQuery) SelectRaw

func (q *EntryQuery) SelectRaw(expression string, bindings ...any) *EntryQuery

func (*EntryQuery) SimplePaginate

func (q *EntryQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (EntryCollection, *pagination.Page, error)

func (*EntryQuery) Sole

func (q *EntryQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Entry, error)

func (*EntryQuery) SoleValue

func (q *EntryQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*EntryQuery) Sum

func (q *EntryQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*EntryQuery) Touch

func (q *EntryQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*EntryQuery) Update

func (q *EntryQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*EntryQuery) UpdateOrCreate

func (q *EntryQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Entry, error)

func (*EntryQuery) Upsert

func (q *EntryQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*EntryQuery) Value

func (q *EntryQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*EntryQuery) ValueOrFail

func (q *EntryQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*EntryQuery) Where

func (q *EntryQuery) Where(column any, args ...any) *EntryQuery

Where adds a where clause; a func(*EntryQuery) in place of the column adds a group.

func (*EntryQuery) WhereBelongsTo

func (q *EntryQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *EntryQuery

func (*EntryQuery) WhereBetween

func (q *EntryQuery) WhereBetween(column any, from, to any) *EntryQuery

func (*EntryQuery) WhereColumn

func (q *EntryQuery) WhereColumn(first any, args ...any) *EntryQuery

func (*EntryQuery) WhereDoesntHave

func (q *EntryQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) WhereExists

func (q *EntryQuery) WhereExists(callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) WhereHas

func (q *EntryQuery) WhereHas(relation string, callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) WhereHasCount

func (q *EntryQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *EntryQuery

func (*EntryQuery) WhereIn

func (q *EntryQuery) WhereIn(column any, values []any) *EntryQuery

func (*EntryQuery) WhereKey

func (q *EntryQuery) WhereKey(id any) *EntryQuery

func (*EntryQuery) WhereNot

func (q *EntryQuery) WhereNot(column any, args ...any) *EntryQuery

WhereNot adds a negated where clause, or a negated group.

func (*EntryQuery) WhereNotExists

func (q *EntryQuery) WhereNotExists(callback func(*query.Builder)) *EntryQuery

func (*EntryQuery) WhereNotIn

func (q *EntryQuery) WhereNotIn(column any, values []any) *EntryQuery

func (*EntryQuery) WhereNotNull

func (q *EntryQuery) WhereNotNull(columns ...any) *EntryQuery

func (*EntryQuery) WhereNull

func (q *EntryQuery) WhereNull(columns ...any) *EntryQuery

func (*EntryQuery) WhereRelation

func (q *EntryQuery) WhereRelation(relation string, column any, args ...any) *EntryQuery

func (*EntryQuery) With

func (q *EntryQuery) With(relations ...string) *EntryQuery

func (*EntryQuery) WithAvg

func (q *EntryQuery) WithAvg(relation, column string) *EntryQuery

func (*EntryQuery) WithCount

func (q *EntryQuery) WithCount(relations ...string) *EntryQuery

func (*EntryQuery) WithExists

func (q *EntryQuery) WithExists(relation string) *EntryQuery

func (*EntryQuery) WithMax

func (q *EntryQuery) WithMax(relation, column string) *EntryQuery

func (*EntryQuery) WithMin

func (q *EntryQuery) WithMin(relation, column string) *EntryQuery

func (*EntryQuery) WithSum

func (q *EntryQuery) WithSum(relation, column string) *EntryQuery

func (*EntryQuery) Without

func (q *EntryQuery) Without(relations ...string) *EntryQuery

func (*EntryQuery) WithoutGlobalScope

func (q *EntryQuery) WithoutGlobalScope(identifier string) *EntryQuery

func (*EntryQuery) WithoutGlobalScopes

func (q *EntryQuery) WithoutGlobalScopes(identifiers ...string) *EntryQuery

type EntryRequest

type EntryRequest struct {
	// ExternalRef identifies the event in the caller's system. Sending the same
	// one twice records it once and answers the entry already recorded.
	ExternalRef string
	Kind        EntryKind
	ProductID   string
	OccurredAt  time.Time
	// Gross is centavos of revenue: positive for a sale, a renewal or an
	// adjustment up, negative for a refund or an adjustment down. Zero for a
	// fee, an expense or a tax.
	Gross int64
	// Fee is centavos taken on the way: the gateway's cut of a sale, or the
	// whole amount of a fee, an expense or a tax.
	Fee         int64
	FeeDetail   string
	Description string
}

EntryRequest is one event the application reports: a sale, a renewal, a refund, a fee, an expense or a tax. It is what the application's own events endpoint -- which it owns, with its own token per tenant -- turns its body into before calling RecordEntry.

func (EntryRequest) Validate

func (r EntryRequest) Validate() validation.Errors

Validate reports the errors per field.

type EntryRow

type EntryRow struct {
	ID, Day, Product, Kind, Description, Gross, Fee, Net, Source, Ref, ReverseURL string
	Reversible                                                                    bool
	GrossSort, DaySort                                                            string
}

EntryRow is one entry in the admin's books.

type EntrySource

type EntrySource string

EntrySource is where an entry came from.

const (
	// SourceAPI is the application's code, through RecordEntry.
	SourceAPI EntrySource = "api"
	// SourceManual is the admin, by hand.
	SourceManual EntrySource = "manual"
)

type Figures

type Figures struct {
	Gross        int64
	Fees         int64
	Costs        int64
	Net          int64
	CostRatioPPM int64
	ShareBps     int64
	Amount       int64
}

Figures are the numbers one closing of one contract comes to.

func ComputeFigures

func ComputeFigures(gross, fees, costs, shareBps int64) Figures

ComputeFigures turns the contract's gross, fees and allocated costs into the net and the investor's amount. A net of zero or less gives no amount.

type Flag

type Flag bool

Flag is a yes-or-no a column holds as an integer, read back from whatever an engine answers with -- the same arrangement arandu-wallet keeps, because the engines disagree about booleans and one place has to flatten them.

func (*Flag) Scan

func (f *Flag) Scan(value any) error

Scan reads the flag back. Anything it cannot read is refused rather than read as false.

func (Flag) Value

func (f Flag) Value() (driver.Value, error)

Value writes the flag as the integer the column holds.

type FormState

type FormState struct{ hview.Page }

FormState is what a form field reads from the page it is drawn on: what was typed before a refusal, and the message for each field.

func (FormState) ErrorSummary added in v0.2.0

func (f FormState) ErrorSummary() []string

ErrorSummary is one line per rejected field.

func (FormState) FieldError

func (f FormState) FieldError(name string) string

FieldError is the first message for one field, empty when it was accepted.

func (FormState) FieldErrors added in v0.2.0

func (f FormState) FieldErrors(name string) []string

FieldErrors is every message for one field.

func (FormState) HasErrors added in v0.2.0

func (f FormState) HasErrors() bool

HasErrors says whether the attempt that landed here was rejected.

func (FormState) LogValue added in v0.2.0

func (f FormState) LogValue() slog.Value

LogValue is the form state as a log line carries it, the token redacted.

func (FormState) MarshalJSON added in v0.2.0

func (f FormState) MarshalJSON() ([]byte, error)

MarshalJSON writes the form state with the CSRF token redacted.

type Investor

type Investor struct {
	model.Model

	// ID is the identifier. It is generated by the application rather than by
	// the database, because a DEFAULT that produces a uuid is spelled
	// differently in every engine.
	ID string `db:"id"`

	// TenantID is the customer the row belongs to. It is written from the
	// Grant and read back so the policy can compare it against the subject's
	// tenant.
	TenantID string `db:"tenant_id"`

	// UserID is the login user who is this investor. The application owns what
	// a user is; this package only compares the identifier with the subject's.
	UserID string `db:"user_id"`

	// Kind says whether the investor is a person or a company, which decides
	// which document is valid and which names are required.
	Kind PersonKind `db:"person_kind"`

	// Document is the CPF of a person or the CNPJ of a company, digits only
	// (and letters, for the alphanumeric CNPJ), never formatted.
	Document string `db:"document"`

	// Name is the person's name, or the company's trade name.
	Name string `db:"name"`

	// LegalName is the company's registered name. Empty for a person.
	LegalName string `db:"legal_name"`

	// LegalRepresentative is who signs for the company. Empty for a person.
	LegalRepresentative string `db:"legal_representative"`

	// Email is where the investor is reached about invoices and payments.
	Email string `db:"email"`

	// Status is whether the investor is active. A suspended investor keeps the
	// history and earns nothing new.
	Status InvestorStatus `db:"status"`

	// CreatedAt is when the row was written, in UTC.
	CreatedAt time.Time `db:"created_at"`

	// UpdatedAt is when the row last changed, in UTC.
	UpdatedAt time.Time `db:"updated_at"`
}

Investor is one angel investor of the application: a person (CPF) or a company (CNPJ) the finance team registered, tied to the login user who reads the statement.

It embeds the model, so a row returned by a query carries the connection and can be saved again. Build a new row with Investors(db).New(): a struct literal has no connection and its write methods return model.ErrUnwired.

Investors, InvestorQuery and InvestorCollection are generated beside this file, in InvestorQuery.go, by aru model:build.

func (Investor) DisplayName

func (i Investor) DisplayName() string

DisplayName is the name the screens print: the registered name of a company when there is one, the person's name otherwise.

func (*Investor) Fresh

func (row *Investor) Fresh(ctx context.Context, g auth.Grant, with ...string) (*Investor, error)

Fresh reads the row again, as a new Investor; it shadows the untyped one the embedded model promotes.

func (Investor) IsActive

func (i Investor) IsActive() bool

IsActive reports whether the investor takes part in new closings.

func (*Investor) Reactivate

func (i *Investor) Reactivate(now time.Time) error

Reactivate brings a suspended investor back into new closings.

func (*Investor) Replicate

func (row *Investor) Replicate(except ...string) (*Investor, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

func (*Investor) Suspend

func (i *Investor) Suspend(now time.Time) error

Suspend leaves the investor out of new closings, keeping the history.

type InvestorCollection

type InvestorCollection []*Investor

InvestorCollection is rows of Investor, as a query returns them.

func InvestorCollectionOf

func InvestorCollectionOf(rows model.Rows) InvestorCollection

InvestorCollectionOf converts rows of the table of Investor. A nil input is a nil collection.

func (InvestorCollection) Contains

func (c InvestorCollection) Contains(key any) bool

func (InvestorCollection) Except

func (c InvestorCollection) Except(keys ...any) InvestorCollection

func (InvestorCollection) Find

func (c InvestorCollection) Find(key any) *Investor

func (InvestorCollection) FindOrFail

func (c InvestorCollection) FindOrFail(key any) (*Investor, error)

func (InvestorCollection) Fresh

func (InvestorCollection) Load

func (c InvestorCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (InvestorCollection) LoadCount

func (c InvestorCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (InvestorCollection) LoadMissing

func (c InvestorCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (InvestorCollection) ModelKeys

func (c InvestorCollection) ModelKeys() []any

func (InvestorCollection) Only

func (c InvestorCollection) Only(keys ...any) InvestorCollection

func (InvestorCollection) Pluck

func (c InvestorCollection) Pluck(column string) []any

func (InvestorCollection) Rows

func (c InvestorCollection) Rows() model.Rows

Rows converts the collection back to the core's rows.

func (InvestorCollection) ToArray

func (c InvestorCollection) ToArray() []map[string]any

func (InvestorCollection) Unique

type InvestorPolicy

type InvestorPolicy struct{}

InvestorPolicy is the only authority over who does what with an Investor and everything that belongs to one: contracts, statement, invoices.

It denies unless a rule below says otherwise, and the rules are written around two subjects: the investor, who may read what is theirs, and the admin, who may act across the tenant. Everything else -- a guest, a subject from another tenant, a signed-in person reaching for somebody else's statement -- falls through to the refusal at the end.

func (InvestorPolicy) Can

Can decides whether the subject may perform the action on the record.

It is the only place that decides. The service reaches the Model only after Authorize turns this method's nil result into a Grant.

The record is the empty Investor where the question is "may this subject do this kind of thing at all", and the loaded row where it is "may they do it to this investor". Both are asked, in that order, and the second is what a rule about ownership answers.

func (InvestorPolicy) Writes added in v0.4.0

func (InvestorPolicy) Writes(a security.Action) bool

Writes reports whether a Grant issued for the action may change anything.

Reading the statement, the costs and the projection (DashboardView) and reading or downloading a contract (ContractView) change nothing, so the Grants issued for them only read: the database refuses an insert, update or delete made with one, whatever the code holding it does next.

ReportsView writes. It is also the action under which an investor asks for their own money -- declaring a payout account and withdrawing an invoice -- and both record the request and an activity entry with that Grant.

Everything not named as a read writes, the management actions with it, so an action added later behaves as every action did before this method existed until somebody decides it only reads.

type InvestorQuery

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

InvestorQuery is a query on the table of Investor.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Investor rows or a value; there is no way to run one without a Grant.

func Investors

func Investors(db model.DB) *InvestorQuery

Investors starts a query on the table of Investor, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*InvestorQuery) AddSelect

func (q *InvestorQuery) AddSelect(columns ...any) *InvestorQuery

func (*InvestorQuery) Avg

func (q *InvestorQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvestorQuery) Base

func (q *InvestorQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of model.go -- and for the factory, which builds rows through it.

func (*InvestorQuery) Chunk

func (q *InvestorQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(InvestorCollection, int) (bool, error)) error

func (*InvestorQuery) Clone

func (q *InvestorQuery) Clone() *InvestorQuery

Clone returns an independent copy of the query.

func (*InvestorQuery) Count

func (q *InvestorQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*InvestorQuery) Create

func (q *InvestorQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Investor, error)

func (*InvestorQuery) Cursor

func (q *InvestorQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Investor, error]

func (*InvestorQuery) CursorPaginate

func (q *InvestorQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (InvestorCollection, *pagination.CursorPage, error)

func (*InvestorQuery) Decrement

func (q *InvestorQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*InvestorQuery) Delete

func (q *InvestorQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*InvestorQuery) DoesntExist

func (q *InvestorQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*InvestorQuery) DoesntHave

func (q *InvestorQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) Each

func (q *InvestorQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*Investor, int) (bool, error)) error

func (*InvestorQuery) Exists

func (q *InvestorQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*InvestorQuery) Find

func (q *InvestorQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Investor, error)

func (*InvestorQuery) FindMany

func (q *InvestorQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (InvestorCollection, error)

func (*InvestorQuery) FindOrFail

func (q *InvestorQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Investor, error)

func (*InvestorQuery) FindOrNew

func (q *InvestorQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Investor, error)

func (*InvestorQuery) First

func (q *InvestorQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Investor, error)

First returns the first row, or nil and no error when there is none.

func (*InvestorQuery) FirstOrCreate

func (q *InvestorQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Investor, error)

func (*InvestorQuery) FirstOrFail

func (q *InvestorQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Investor, error)

func (*InvestorQuery) FirstOrNew

func (q *InvestorQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Investor, error)

func (*InvestorQuery) FirstWhere

func (q *InvestorQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Investor, error)

func (*InvestorQuery) ForPage

func (q *InvestorQuery) ForPage(page, perPage int) *InvestorQuery

func (*InvestorQuery) ForceCreate

func (q *InvestorQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Investor, error)

func (*InvestorQuery) Get

func (q *InvestorQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (InvestorCollection, error)

Get runs the query and returns the rows.

func (*InvestorQuery) GroupBy

func (q *InvestorQuery) GroupBy(groups ...any) *InvestorQuery

func (*InvestorQuery) Has

func (q *InvestorQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) Increment

func (q *InvestorQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*InvestorQuery) Insert

func (q *InvestorQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*InvestorQuery) InsertOrIgnore

func (q *InvestorQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*InvestorQuery) Join

func (q *InvestorQuery) Join(table any, first any, args ...any) *InvestorQuery

func (*InvestorQuery) Latest

func (q *InvestorQuery) Latest(column ...string) *InvestorQuery

func (*InvestorQuery) Limit

func (q *InvestorQuery) Limit(value int) *InvestorQuery

func (*InvestorQuery) Max

func (q *InvestorQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvestorQuery) Min

func (q *InvestorQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvestorQuery) New

func (q *InvestorQuery) New() (*Investor, error)

New returns an empty Investor on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*InvestorQuery) Offset

func (q *InvestorQuery) Offset(value int) *InvestorQuery

func (*InvestorQuery) Oldest

func (q *InvestorQuery) Oldest(column ...string) *InvestorQuery

func (*InvestorQuery) OrDoesntHave

func (q *InvestorQuery) OrDoesntHave(relation string) *InvestorQuery

func (*InvestorQuery) OrHas

func (q *InvestorQuery) OrHas(relation, operator string, count int) *InvestorQuery

func (*InvestorQuery) OrWhere

func (q *InvestorQuery) OrWhere(column any, args ...any) *InvestorQuery

OrWhere adds an or-where clause; a func(*InvestorQuery) in place of the column adds a group.

func (*InvestorQuery) OrWhereDoesntHave

func (q *InvestorQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) OrWhereHas

func (q *InvestorQuery) OrWhereHas(relation string, callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) OrWhereNot

func (q *InvestorQuery) OrWhereNot(column any, args ...any) *InvestorQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*InvestorQuery) OrWhereRelation

func (q *InvestorQuery) OrWhereRelation(relation string, column any, args ...any) *InvestorQuery

func (*InvestorQuery) OrderBy

func (q *InvestorQuery) OrderBy(column any, direction ...string) *InvestorQuery

func (*InvestorQuery) OrderByDesc

func (q *InvestorQuery) OrderByDesc(column any) *InvestorQuery

func (*InvestorQuery) Paginate

func (q *InvestorQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (InvestorCollection, *pagination.LengthAwarePage, error)

func (*InvestorQuery) Pluck

func (q *InvestorQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*InvestorQuery) Select

func (q *InvestorQuery) Select(columns ...any) *InvestorQuery

func (*InvestorQuery) SelectRaw

func (q *InvestorQuery) SelectRaw(expression string, bindings ...any) *InvestorQuery

func (*InvestorQuery) SimplePaginate

func (q *InvestorQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (InvestorCollection, *pagination.Page, error)

func (*InvestorQuery) Sole

func (q *InvestorQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Investor, error)

func (*InvestorQuery) SoleValue

func (q *InvestorQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvestorQuery) Sum

func (q *InvestorQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvestorQuery) Touch

func (q *InvestorQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*InvestorQuery) Update

func (q *InvestorQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*InvestorQuery) UpdateOrCreate

func (q *InvestorQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Investor, error)

func (*InvestorQuery) Upsert

func (q *InvestorQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*InvestorQuery) Value

func (q *InvestorQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvestorQuery) ValueOrFail

func (q *InvestorQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvestorQuery) Where

func (q *InvestorQuery) Where(column any, args ...any) *InvestorQuery

Where adds a where clause; a func(*InvestorQuery) in place of the column adds a group.

func (*InvestorQuery) WhereBelongsTo

func (q *InvestorQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *InvestorQuery

func (*InvestorQuery) WhereBetween

func (q *InvestorQuery) WhereBetween(column any, from, to any) *InvestorQuery

func (*InvestorQuery) WhereColumn

func (q *InvestorQuery) WhereColumn(first any, args ...any) *InvestorQuery

func (*InvestorQuery) WhereDoesntHave

func (q *InvestorQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) WhereExists

func (q *InvestorQuery) WhereExists(callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) WhereHas

func (q *InvestorQuery) WhereHas(relation string, callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) WhereHasCount

func (q *InvestorQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *InvestorQuery

func (*InvestorQuery) WhereIn

func (q *InvestorQuery) WhereIn(column any, values []any) *InvestorQuery

func (*InvestorQuery) WhereKey

func (q *InvestorQuery) WhereKey(id any) *InvestorQuery

func (*InvestorQuery) WhereNot

func (q *InvestorQuery) WhereNot(column any, args ...any) *InvestorQuery

WhereNot adds a negated where clause, or a negated group.

func (*InvestorQuery) WhereNotExists

func (q *InvestorQuery) WhereNotExists(callback func(*query.Builder)) *InvestorQuery

func (*InvestorQuery) WhereNotIn

func (q *InvestorQuery) WhereNotIn(column any, values []any) *InvestorQuery

func (*InvestorQuery) WhereNotNull

func (q *InvestorQuery) WhereNotNull(columns ...any) *InvestorQuery

func (*InvestorQuery) WhereNull

func (q *InvestorQuery) WhereNull(columns ...any) *InvestorQuery

func (*InvestorQuery) WhereRelation

func (q *InvestorQuery) WhereRelation(relation string, column any, args ...any) *InvestorQuery

func (*InvestorQuery) With

func (q *InvestorQuery) With(relations ...string) *InvestorQuery

func (*InvestorQuery) WithAvg

func (q *InvestorQuery) WithAvg(relation, column string) *InvestorQuery

func (*InvestorQuery) WithCount

func (q *InvestorQuery) WithCount(relations ...string) *InvestorQuery

func (*InvestorQuery) WithExists

func (q *InvestorQuery) WithExists(relation string) *InvestorQuery

func (*InvestorQuery) WithMax

func (q *InvestorQuery) WithMax(relation, column string) *InvestorQuery

func (*InvestorQuery) WithMin

func (q *InvestorQuery) WithMin(relation, column string) *InvestorQuery

func (*InvestorQuery) WithSum

func (q *InvestorQuery) WithSum(relation, column string) *InvestorQuery

func (*InvestorQuery) Without

func (q *InvestorQuery) Without(relations ...string) *InvestorQuery

func (*InvestorQuery) WithoutGlobalScope

func (q *InvestorQuery) WithoutGlobalScope(identifier string) *InvestorQuery

func (*InvestorQuery) WithoutGlobalScopes

func (q *InvestorQuery) WithoutGlobalScopes(identifiers ...string) *InvestorQuery

type InvestorRow

type InvestorRow struct {
	ID, Name, Document, Kind, Email, Status, User, URL string
	Active                                             bool
}

InvestorRow is one investor in the admin's registry.

type InvestorService

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

InvestorService orchestrates the use cases of this package: it validates the request, asks the policy for a Grant, applies the rules the entities hold for themselves, and persists with that Grant.

It receives its collaborators through the constructor. There is no container and no resolution by reflection: what this service is made of is written at the one place that builds it, and reading that place is how somebody learns what the package touches.

Everything a handler is allowed to do goes through here. The service is the only owner of the database handle, so the request layer cannot reach a Model before the policy has answered.

func NewInvestorService

func NewInvestorService(db *data.DB) *InvestorService

NewInvestorService wires the service over the application's database handle.

func (*InvestorService) AddBankAccount added in v0.2.0

AddBankAccount declares a bank account the investor who is asking is paid into, in the name and the document of their registration, as AddPixAccount does for a PIX key.

func (*InvestorService) AddPixAccount

func (s *InvestorService) AddPixAccount(ctx context.Context, actor security.Subject, keyType, key string) (*wallet.PayoutAccount, error)

AddPixAccount declares a PIX key the investor who is asking is paid into, in the name and the document of their registration: an investor is paid into an account of their own, never a third party's.

func (*InvestorService) AdminCosts

func (s *InvestorService) AdminCosts(ctx context.Context, actor security.Subject) ([]CostView, error)

AdminCosts lists the declared costs for the admin who declares them.

func (*InvestorService) AmendContract

func (s *InvestorService) AmendContract(ctx context.Context, actor security.Subject, contractID string, in ContractRequest, file io.Reader) (*Contract, error)

AmendContract registers an amendment: a new version of the contract named, with its own terms and file. The version in force becomes superseded in the same transaction, so there is never a moment with two versions in force or with none.

func (*InvestorService) AnnualReport

func (s *InvestorService) AnnualReport(ctx context.Context, actor security.Subject, investorID string, year int, w io.Writer) error

AnnualReport writes the year's income report of one investor as .xlsx: the payer, the beneficiary, and the amounts credited month by month, laid out the way the Receita Federal's informe de rendimentos is. Nothing is withheld by this package, and the report says so.

func (*InvestorService) Close

func (s *InvestorService) Close(ctx context.Context, actor security.Subject, contractID string, asOf Day) (*Invoice, error)

Close closes the period of one contract that ended on the last billing day on or before asOf, and answers the invoice it produced.

The period starts where the last invoice of the contract ended, or on the day the contract started. The entries counted are those of the contract's products not counted before -- which is how an entry dated in a closed period is counted in the next closing instead of reopening the old one. The costs are those of the period's window, shared out over the revenue.

Closing the same period twice answers the invoice the first closing made.

func (*InvestorService) CloseDue

func (s *InvestorService) CloseDue(ctx context.Context, actor security.Subject, asOf Day) ([]*Invoice, map[string]error, error)

CloseDue closes every contract whose billing day is asOf's day: the admin's "close the contracts that are due today". A contract that fails is reported beside the others, and does not stop them.

func (*InvestorService) ContractFile

func (s *InvestorService) ContractFile(ctx context.Context, actor security.Subject, contractID string) (*Contract, filesystem.File, error)

ContractFile opens the signed file of one contract version. The admin may open any; an investor only their own. The caller closes the body.

func (*InvestorService) Costs

func (s *InvestorService) Costs(ctx context.Context, actor security.Subject) ([]CostView, error)

Costs lists the declared costs, for the admin and for the investors: what the money is spent on is part of what an investor is shown.

func (*InvestorService) Create

Create registers an investor: validate, authorize, then act with the Grant the authorization produced.

The candidate is authorized before it is stored, and the candidate is what the policy sees -- so a rule about what may be created is a rule about the record being created, and not about the person alone.

func (*InvestorService) CreateContract

func (s *InvestorService) CreateContract(ctx context.Context, actor security.Subject, investorID string, in ContractRequest, file io.Reader) (*Contract, error)

CreateContract registers the original version of a contract for an investor, with the signed file.

func (*InvestorService) CreateCost

func (s *InvestorService) CreateCost(ctx context.Context, actor security.Subject, in CostRequest) (*CostItem, error)

CreateCost declares one cost.

func (*InvestorService) EndCost

func (s *InvestorService) EndCost(ctx context.Context, actor security.Subject, costID, lastDay string) (*CostItem, error)

EndCost stops a cost from the day after the one given. The months it ran stay counted; nothing about a closed period changes.

func (*InvestorService) EntriesPage

func (s *InvestorService) EntriesPage(ctx context.Context, actor security.Subject, q EntriesQuery) ([]*Entry, int, error)

EntriesPage is a page of the admin's books and how many rows the whole listing has.

func (*InvestorService) Find

func (s *InvestorService) Find(ctx context.Context, actor security.Subject, id string) (*Investor, error)

Find returns one investor for the admin, and asks the policy twice.

The first call is on the empty candidate, because there is no way to read the record without a Grant and no way to hold a Grant without a decision. What it decides is whether this subject may manage investors at all -- an investor reads their own row through Mine, never by naming an identifier.

The second call is on the record that came back, and it is the one a rule about the record itself depends on.

func (*InvestorService) InvestorContracts

func (s *InvestorService) InvestorContracts(ctx context.Context, actor security.Subject, investorID string) ([]ContractResource, error)

InvestorContracts lists every version of every contract of one investor, newest first, with the products of each. The admin may ask about anybody; an investor only about themselves.

func (*InvestorService) InvoiceReceipt

func (s *InvestorService) InvoiceReceipt(ctx context.Context, actor security.Subject, invoiceID string) (*wallet.WithdrawalRequest, filesystem.File, error)

InvoiceReceipt opens the receipt of an invoice's paid withdrawal, for the investor and the admin. The caller closes the body.

func (*InvestorService) InvoiceViews

func (s *InvestorService) InvoiceViews(ctx context.Context, actor security.Subject, investorID string) ([]InvoiceView, error)

InvoiceViews lists one investor's invoices with the state of each one's withdrawal. An invoice whose request was paid reads as withdrawn.

func (*InvestorService) Invoices

func (s *InvestorService) Invoices(ctx context.Context, actor security.Subject, investorID string) ([]*Invoice, error)

Invoices lists one investor's invoices, newest period first. The admin may ask about anybody; an investor about themselves.

func (*InvestorService) List

func (s *InvestorService) List(ctx context.Context, actor security.Subject, q data.Query) ([]*Investor, error)

List returns a page of investors, for the admin.

It authorizes once, on the empty candidate, and the tenant filter in the statement is what bounds the rows. Listing every investor is an admin's question: the probe for InvestorsManage refuses an investor, who reads their own row through Mine instead.

func (*InvestorService) Mine

func (s *InvestorService) Mine(ctx context.Context, actor security.Subject) (*Investor, error)

Mine returns the investor whose login user is the subject, which is how the investor's own panel finds what to show. ErrNotFound when the subject is not an investor of this tenant.

func (*InvestorService) MonthlyReport

func (s *InvestorService) MonthlyReport(ctx context.Context, actor security.Subject, investorID string, year, month int, w io.Writer) error

MonthlyReport writes, as .xlsx, the invoices of one investor whose period closed in the month, and the entries each one counted with its share of the costs.

func (*InvestorService) PayInvestorWithdrawal

func (s *InvestorService) PayInvestorWithdrawal(ctx context.Context, actor security.Subject, in wallet.PaymentInput, receipt io.Reader) (*wallet.WithdrawalRequest, error)

PayInvestorWithdrawal records that the operator paid an investor's withdrawal, with the receipt.

func (*InvestorService) PayoutAccounts

func (s *InvestorService) PayoutAccounts(ctx context.Context, actor security.Subject, investorID string) ([]*wallet.PayoutAccount, error)

PayoutAccounts are the accounts the investor can be paid into, from arandu-wallet, the usable ones first.

func (*InvestorService) ProjectionOf

func (s *InvestorService) ProjectionOf(ctx context.Context, actor security.Subject, contractID string) (*Projection, error)

ProjectionOf answers the open period of a contract.

func (*InvestorService) RecordEntry

func (s *InvestorService) RecordEntry(ctx context.Context, actor security.Subject, in EntryRequest) (*Entry, error)

RecordEntry records one event, once.

It is idempotent by ExternalRef within the tenant: a second call with the same reference answers the entry the first one recorded, whatever the rest of the body says, because the caller retrying is the case this exists for. The unique index is what decides between two concurrent first calls.

func (*InvestorService) RecordManualEntry

func (s *InvestorService) RecordManualEntry(ctx context.Context, actor security.Subject, in EntryRequest) (*Entry, error)

RecordManualEntry is RecordEntry for the admin's own hand: the same rules, marked as manual in the statement so the investor sees which lines a person typed.

func (*InvestorService) RejectInvestorWithdrawal

func (s *InvestorService) RejectInvestorWithdrawal(ctx context.Context, actor security.Subject, requestID, reason string) (*wallet.WithdrawalRequest, error)

RejectInvestorWithdrawal refuses an investor's withdrawal with the reason they will read. The invoice can be asked for again.

func (*InvestorService) ReverseEntry

func (s *InvestorService) ReverseEntry(ctx context.Context, actor security.Subject, entryID, reason string) (*Entry, error)

ReverseEntry undoes an entry with a new one carrying the opposite amounts, dated now: an entry of a period already closed is corrected in the period that is open, never by reopening the old one. Reversing the same entry twice answers the first reversal.

func (*InvestorService) SetActive

func (s *InvestorService) SetActive(ctx context.Context, actor security.Subject, id string, active bool) (*Investor, error)

SetActive suspends or reactivates an investor. A suspended investor keeps the whole history and is left out of the closings that follow.

func (*InvestorService) StartPaying

func (s *InvestorService) StartPaying(ctx context.Context, actor security.Subject, requestID string) (*wallet.WithdrawalRequest, error)

StartPaying is the operator taking an investor's withdrawal to pay it.

func (*InvestorService) StatementOf

func (s *InvestorService) StatementOf(ctx context.Context, actor security.Subject, contractID string, f StatementFilter) (*Statement, error)

StatementOf answers a contract's statement: each entry of its products with its share of the costs. A line of a closed period carries the cost ratio of the invoice that counted it; a line of the open period carries the projection's, and is marked as an estimate.

func (*InvestorService) Update

func (s *InvestorService) Update(ctx context.Context, actor security.Subject, id string, in UpdateRequest) (*Investor, error)

Update changes the names and the e-mail of an investor.

func (*InvestorService) WithdrawInvoice

func (s *InvestorService) WithdrawInvoice(ctx context.Context, actor security.Subject, invoiceID, accountID string) (*InvoiceView, error)

WithdrawInvoice asks arandu-wallet to pay one invoice, whole, to one of the investor's payout accounts. The investor asks for their own; the admin may ask on an investor's behalf.

func (*InvestorService) Withdrawals

Withdrawals is the operator's queue of investors' withdrawals: the requests arandu-wallet holds whose invoice is one of this tenant's.

type InvestorStatus

type InvestorStatus string

InvestorStatus is whether an investor takes part in new closings.

const (
	// InvestorActive takes part in every closing of its contracts.
	InvestorActive InvestorStatus = "active"
	// InvestorSuspended keeps its history and is left out of new closings.
	InvestorSuspended InvestorStatus = "suspended"
)

type InvestorWithdrawal

type InvestorWithdrawal struct {
	Request  *wallet.WithdrawalRequest
	Invoice  *Invoice
	Investor *Investor
}

InvestorWithdrawal is one investor's withdrawal request, with the invoice and the investor it pays.

type Invoice

type Invoice struct {
	model.Model

	ID       string `db:"id"`
	TenantID string `db:"tenant_id"`

	InvestorID string `db:"investor_id"`
	// ContractID is the version in force when the period closed; RootID the
	// contract every version shares, which is what the periods follow.
	ContractID string `db:"contract_id"`
	RootID     string `db:"root_id"`

	// The period is [PeriodStart, PeriodEnd): the end day belongs to the next.
	PeriodStart Day `db:"period_start"`
	PeriodEnd   Day `db:"period_end"`

	// The figures, in centavos.
	Gross int64 `db:"gross"`
	Fees  int64 `db:"fees"`
	Costs int64 `db:"costs"`
	Net   int64 `db:"net"`

	// CostRatioPPM is the costs as a share of the gross, in parts per million:
	// what every line of the statement carries as its part of the costs.
	CostRatioPPM int64 `db:"cost_ratio_ppm"`

	ShareBps int64 `db:"share_bps"`
	Amount   int64 `db:"amount"`

	Status InvoiceStatus `db:"status"`

	// WalletOperationID is the deposit that put the amount in the investor's
	// wallet. Empty when there was nothing to deposit.
	WalletOperationID string `db:"wallet_operation_id"`

	// WithdrawalRequestID is the latest arandu-wallet withdrawal request made
	// for this invoice, and WithdrawalAttempts how many were made: a rejected
	// or cancelled one leaves the invoice to be asked for again.
	WithdrawalRequestID string `db:"withdrawal_request_id"`
	WithdrawalAttempts  int    `db:"withdrawal_attempts"`

	ClosedBy  string    `db:"closed_by"`
	ClosedAt  time.Time `db:"closed_at"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

Invoice is what one closing of one contract produced: the period, the figures it was computed from, and the investor's amount. It is the unit the investor withdraws, and it is never summed into the next period.

func (*Invoice) Fresh

func (row *Invoice) Fresh(ctx context.Context, g auth.Grant, with ...string) (*Invoice, error)

Fresh reads the row again, as a new Invoice; it shadows the untyped one the embedded model promotes.

func (*Invoice) Replicate

func (row *Invoice) Replicate(except ...string) (*Invoice, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

type InvoiceCollection

type InvoiceCollection []*Invoice

InvoiceCollection is rows of Invoice, as a query returns them.

func InvoiceCollectionOf

func InvoiceCollectionOf(rows model.Rows) InvoiceCollection

InvoiceCollectionOf converts rows of the table of Invoice. A nil input is a nil collection.

func (InvoiceCollection) Contains

func (c InvoiceCollection) Contains(key any) bool

func (InvoiceCollection) Except

func (c InvoiceCollection) Except(keys ...any) InvoiceCollection

func (InvoiceCollection) Find

func (c InvoiceCollection) Find(key any) *Invoice

func (InvoiceCollection) FindOrFail

func (c InvoiceCollection) FindOrFail(key any) (*Invoice, error)

func (InvoiceCollection) Fresh

func (InvoiceCollection) Load

func (c InvoiceCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (InvoiceCollection) LoadCount

func (c InvoiceCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (InvoiceCollection) LoadMissing

func (c InvoiceCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (InvoiceCollection) ModelKeys

func (c InvoiceCollection) ModelKeys() []any

func (InvoiceCollection) Only

func (c InvoiceCollection) Only(keys ...any) InvoiceCollection

func (InvoiceCollection) Pluck

func (c InvoiceCollection) Pluck(column string) []any

func (InvoiceCollection) Rows

func (c InvoiceCollection) Rows() model.Rows

Rows converts the collection back to the core's rows.

func (InvoiceCollection) ToArray

func (c InvoiceCollection) ToArray() []map[string]any

func (InvoiceCollection) Unique

type InvoiceEntry

type InvoiceEntry struct {
	model.Model

	ID        string    `db:"id"`
	TenantID  string    `db:"tenant_id"`
	InvoiceID string    `db:"invoice_id"`
	RootID    string    `db:"root_id"`
	EntryID   string    `db:"entry_id"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

InvoiceEntry records that an entry was counted in an invoice of a contract. It is what lets an entry that arrived late -- dated in a period already closed -- be counted in the next closing instead of reopening the old one, and never twice.

func (*InvoiceEntry) Fresh

func (row *InvoiceEntry) Fresh(ctx context.Context, g auth.Grant, with ...string) (*InvoiceEntry, error)

Fresh reads the row again, as a new InvoiceEntry; it shadows the untyped one the embedded model promotes.

func (*InvoiceEntry) Replicate

func (row *InvoiceEntry) Replicate(except ...string) (*InvoiceEntry, error)

Replicate returns an unsaved copy of the row without its key; it shadows the untyped one the embedded model promotes.

type InvoiceEntryCollection

type InvoiceEntryCollection []*InvoiceEntry

InvoiceEntryCollection is rows of InvoiceEntry, as a query returns them.

func InvoiceEntryCollectionOf

func InvoiceEntryCollectionOf(rows model.Rows) InvoiceEntryCollection

InvoiceEntryCollectionOf converts rows of the table of InvoiceEntry. A nil input is a nil collection.

func (InvoiceEntryCollection) Contains

func (c InvoiceEntryCollection) Contains(key any) bool

func (InvoiceEntryCollection) Except

func (InvoiceEntryCollection) Find

func (InvoiceEntryCollection) FindOrFail

func (c InvoiceEntryCollection) FindOrFail(key any) (*InvoiceEntry, error)

func (InvoiceEntryCollection) Fresh

func (InvoiceEntryCollection) Load

func (c InvoiceEntryCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error

func (InvoiceEntryCollection) LoadCount

func (c InvoiceEntryCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error

func (InvoiceEntryCollection) LoadMissing

func (c InvoiceEntryCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error

func (InvoiceEntryCollection) ModelKeys

func (c InvoiceEntryCollection) ModelKeys() []any

func (InvoiceEntryCollection) Only

func (InvoiceEntryCollection) Pluck

func (c InvoiceEntryCollection) Pluck(column string) []any

func (InvoiceEntryCollection) Rows

Rows converts the collection back to the core's rows.

func (InvoiceEntryCollection) ToArray

func (c InvoiceEntryCollection) ToArray() []map[string]any

func (InvoiceEntryCollection) Unique

type InvoiceEntryQuery

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

InvoiceEntryQuery is a query on the table of InvoiceEntry.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return InvoiceEntry rows or a value; there is no way to run one without a Grant.

func InvoiceEntries

func InvoiceEntries(db model.DB) *InvoiceEntryQuery

InvoiceEntries starts a query on the table of InvoiceEntry, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*InvoiceEntryQuery) AddSelect

func (q *InvoiceEntryQuery) AddSelect(columns ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Avg

func (q *InvoiceEntryQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceEntryQuery) Base

func (q *InvoiceEntryQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of ledger.go -- and for the factory, which builds rows through it.

func (*InvoiceEntryQuery) Chunk

func (q *InvoiceEntryQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(InvoiceEntryCollection, int) (bool, error)) error

func (*InvoiceEntryQuery) Clone

Clone returns an independent copy of the query.

func (*InvoiceEntryQuery) Count

func (q *InvoiceEntryQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*InvoiceEntryQuery) Create

func (q *InvoiceEntryQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) Cursor

func (*InvoiceEntryQuery) CursorPaginate

func (q *InvoiceEntryQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (InvoiceEntryCollection, *pagination.CursorPage, error)

func (*InvoiceEntryQuery) Decrement

func (q *InvoiceEntryQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*InvoiceEntryQuery) Delete

func (q *InvoiceEntryQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*InvoiceEntryQuery) DoesntExist

func (q *InvoiceEntryQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*InvoiceEntryQuery) DoesntHave

func (q *InvoiceEntryQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Each

func (q *InvoiceEntryQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*InvoiceEntry, int) (bool, error)) error

func (*InvoiceEntryQuery) Exists

func (q *InvoiceEntryQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*InvoiceEntryQuery) Find

func (q *InvoiceEntryQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) FindMany

func (q *InvoiceEntryQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (InvoiceEntryCollection, error)

func (*InvoiceEntryQuery) FindOrFail

func (q *InvoiceEntryQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) FindOrNew

func (q *InvoiceEntryQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) First

func (q *InvoiceEntryQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*InvoiceEntry, error)

First returns the first row, or nil and no error when there is none.

func (*InvoiceEntryQuery) FirstOrCreate

func (q *InvoiceEntryQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) FirstOrFail

func (q *InvoiceEntryQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) FirstOrNew

func (q *InvoiceEntryQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) FirstWhere

func (q *InvoiceEntryQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) ForPage

func (q *InvoiceEntryQuery) ForPage(page, perPage int) *InvoiceEntryQuery

func (*InvoiceEntryQuery) ForceCreate

func (q *InvoiceEntryQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) Get

Get runs the query and returns the rows.

func (*InvoiceEntryQuery) GroupBy

func (q *InvoiceEntryQuery) GroupBy(groups ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Has

func (q *InvoiceEntryQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Increment

func (q *InvoiceEntryQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*InvoiceEntryQuery) Insert

func (q *InvoiceEntryQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*InvoiceEntryQuery) InsertOrIgnore

func (q *InvoiceEntryQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*InvoiceEntryQuery) Join

func (q *InvoiceEntryQuery) Join(table any, first any, args ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Latest

func (q *InvoiceEntryQuery) Latest(column ...string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Limit

func (q *InvoiceEntryQuery) Limit(value int) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Max

func (q *InvoiceEntryQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceEntryQuery) Min

func (q *InvoiceEntryQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceEntryQuery) New

func (q *InvoiceEntryQuery) New() (*InvoiceEntry, error)

New returns an empty InvoiceEntry on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*InvoiceEntryQuery) Offset

func (q *InvoiceEntryQuery) Offset(value int) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Oldest

func (q *InvoiceEntryQuery) Oldest(column ...string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrDoesntHave

func (q *InvoiceEntryQuery) OrDoesntHave(relation string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrHas

func (q *InvoiceEntryQuery) OrHas(relation, operator string, count int) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrWhere

func (q *InvoiceEntryQuery) OrWhere(column any, args ...any) *InvoiceEntryQuery

OrWhere adds an or-where clause; a func(*InvoiceEntryQuery) in place of the column adds a group.

func (*InvoiceEntryQuery) OrWhereDoesntHave

func (q *InvoiceEntryQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrWhereHas

func (q *InvoiceEntryQuery) OrWhereHas(relation string, callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrWhereNot

func (q *InvoiceEntryQuery) OrWhereNot(column any, args ...any) *InvoiceEntryQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*InvoiceEntryQuery) OrWhereRelation

func (q *InvoiceEntryQuery) OrWhereRelation(relation string, column any, args ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrderBy

func (q *InvoiceEntryQuery) OrderBy(column any, direction ...string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) OrderByDesc

func (q *InvoiceEntryQuery) OrderByDesc(column any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Paginate

func (q *InvoiceEntryQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (InvoiceEntryCollection, *pagination.LengthAwarePage, error)

func (*InvoiceEntryQuery) Pluck

func (q *InvoiceEntryQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*InvoiceEntryQuery) Select

func (q *InvoiceEntryQuery) Select(columns ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) SelectRaw

func (q *InvoiceEntryQuery) SelectRaw(expression string, bindings ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) SimplePaginate

func (q *InvoiceEntryQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (InvoiceEntryCollection, *pagination.Page, error)

func (*InvoiceEntryQuery) Sole

func (q *InvoiceEntryQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) SoleValue

func (q *InvoiceEntryQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvoiceEntryQuery) Sum

func (q *InvoiceEntryQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceEntryQuery) Touch

func (q *InvoiceEntryQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*InvoiceEntryQuery) Update

func (q *InvoiceEntryQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*InvoiceEntryQuery) UpdateOrCreate

func (q *InvoiceEntryQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*InvoiceEntry, error)

func (*InvoiceEntryQuery) Upsert

func (q *InvoiceEntryQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*InvoiceEntryQuery) Value

func (q *InvoiceEntryQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvoiceEntryQuery) ValueOrFail

func (q *InvoiceEntryQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvoiceEntryQuery) Where

func (q *InvoiceEntryQuery) Where(column any, args ...any) *InvoiceEntryQuery

Where adds a where clause; a func(*InvoiceEntryQuery) in place of the column adds a group.

func (*InvoiceEntryQuery) WhereBelongsTo

func (q *InvoiceEntryQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereBetween

func (q *InvoiceEntryQuery) WhereBetween(column any, from, to any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereColumn

func (q *InvoiceEntryQuery) WhereColumn(first any, args ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereDoesntHave

func (q *InvoiceEntryQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereExists

func (q *InvoiceEntryQuery) WhereExists(callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereHas

func (q *InvoiceEntryQuery) WhereHas(relation string, callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereHasCount

func (q *InvoiceEntryQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereIn

func (q *InvoiceEntryQuery) WhereIn(column any, values []any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereKey

func (q *InvoiceEntryQuery) WhereKey(id any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereNot

func (q *InvoiceEntryQuery) WhereNot(column any, args ...any) *InvoiceEntryQuery

WhereNot adds a negated where clause, or a negated group.

func (*InvoiceEntryQuery) WhereNotExists

func (q *InvoiceEntryQuery) WhereNotExists(callback func(*query.Builder)) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereNotIn

func (q *InvoiceEntryQuery) WhereNotIn(column any, values []any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereNotNull

func (q *InvoiceEntryQuery) WhereNotNull(columns ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereNull

func (q *InvoiceEntryQuery) WhereNull(columns ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WhereRelation

func (q *InvoiceEntryQuery) WhereRelation(relation string, column any, args ...any) *InvoiceEntryQuery

func (*InvoiceEntryQuery) With

func (q *InvoiceEntryQuery) With(relations ...string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithAvg

func (q *InvoiceEntryQuery) WithAvg(relation, column string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithCount

func (q *InvoiceEntryQuery) WithCount(relations ...string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithExists

func (q *InvoiceEntryQuery) WithExists(relation string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithMax

func (q *InvoiceEntryQuery) WithMax(relation, column string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithMin

func (q *InvoiceEntryQuery) WithMin(relation, column string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithSum

func (q *InvoiceEntryQuery) WithSum(relation, column string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) Without

func (q *InvoiceEntryQuery) Without(relations ...string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithoutGlobalScope

func (q *InvoiceEntryQuery) WithoutGlobalScope(identifier string) *InvoiceEntryQuery

func (*InvoiceEntryQuery) WithoutGlobalScopes

func (q *InvoiceEntryQuery) WithoutGlobalScopes(identifiers ...string) *InvoiceEntryQuery

type InvoiceQuery

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

InvoiceQuery is a query on the table of Invoice.

The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Invoice rows or a value; there is no way to run one without a Grant.

func Invoices

func Invoices(db model.DB) *InvoiceQuery

Invoices starts a query on the table of Invoice, through db.

Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.

func (*InvoiceQuery) AddSelect

func (q *InvoiceQuery) AddSelect(columns ...any) *InvoiceQuery

func (*InvoiceQuery) Avg

func (q *InvoiceQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceQuery) Base

func (q *InvoiceQuery) Base() *model.Builder

Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of ledger.go -- and for the factory, which builds rows through it.

func (*InvoiceQuery) Chunk

func (q *InvoiceQuery) Chunk(ctx context.Context, g auth.Grant, count int, callback func(InvoiceCollection, int) (bool, error)) error

func (*InvoiceQuery) Clone

func (q *InvoiceQuery) Clone() *InvoiceQuery

Clone returns an independent copy of the query.

func (*InvoiceQuery) Count

func (q *InvoiceQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)

func (*InvoiceQuery) Create

func (q *InvoiceQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Invoice, error)

func (*InvoiceQuery) Cursor

func (q *InvoiceQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Invoice, error]

func (*InvoiceQuery) CursorPaginate

func (q *InvoiceQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (InvoiceCollection, *pagination.CursorPage, error)

func (*InvoiceQuery) Decrement

func (q *InvoiceQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*InvoiceQuery) Delete

func (q *InvoiceQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)

func (*InvoiceQuery) DoesntExist

func (q *InvoiceQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)

func (*InvoiceQuery) DoesntHave

func (q *InvoiceQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) Each

func (q *InvoiceQuery) Each(ctx context.Context, g auth.Grant, count int, callback func(*Invoice, int) (bool, error)) error

func (*InvoiceQuery) Exists

func (q *InvoiceQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)

func (*InvoiceQuery) Find

func (q *InvoiceQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Invoice, error)

func (*InvoiceQuery) FindMany

func (q *InvoiceQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (InvoiceCollection, error)

func (*InvoiceQuery) FindOrFail

func (q *InvoiceQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Invoice, error)

func (*InvoiceQuery) FindOrNew

func (q *InvoiceQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Invoice, error)

func (*InvoiceQuery) First

func (q *InvoiceQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Invoice, error)

First returns the first row, or nil and no error when there is none.

func (*InvoiceQuery) FirstOrCreate

func (q *InvoiceQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Invoice, error)

func (*InvoiceQuery) FirstOrFail

func (q *InvoiceQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Invoice, error)

func (*InvoiceQuery) FirstOrNew

func (q *InvoiceQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Invoice, error)

func (*InvoiceQuery) FirstWhere

func (q *InvoiceQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Invoice, error)

func (*InvoiceQuery) ForPage

func (q *InvoiceQuery) ForPage(page, perPage int) *InvoiceQuery

func (*InvoiceQuery) ForceCreate

func (q *InvoiceQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Invoice, error)

func (*InvoiceQuery) Get

func (q *InvoiceQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (InvoiceCollection, error)

Get runs the query and returns the rows.

func (*InvoiceQuery) GroupBy

func (q *InvoiceQuery) GroupBy(groups ...any) *InvoiceQuery

func (*InvoiceQuery) Has

func (q *InvoiceQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) Increment

func (q *InvoiceQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, extra map[string]any) (int64, error)

func (*InvoiceQuery) Insert

func (q *InvoiceQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*InvoiceQuery) InsertOrIgnore

func (q *InvoiceQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)

func (*InvoiceQuery) Join

func (q *InvoiceQuery) Join(table any, first any, args ...any) *InvoiceQuery

func (*InvoiceQuery) Latest

func (q *InvoiceQuery) Latest(column ...string) *InvoiceQuery

func (*InvoiceQuery) Limit

func (q *InvoiceQuery) Limit(value int) *InvoiceQuery

func (*InvoiceQuery) Max

func (q *InvoiceQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceQuery) Min

func (q *InvoiceQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceQuery) New

func (q *InvoiceQuery) New() (*Invoice, error)

New returns an empty Invoice on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.

func (*InvoiceQuery) Offset

func (q *InvoiceQuery) Offset(value int) *InvoiceQuery

func (*InvoiceQuery) Oldest

func (q *InvoiceQuery) Oldest(column ...string) *InvoiceQuery

func (*InvoiceQuery) OrDoesntHave

func (q *InvoiceQuery) OrDoesntHave(relation string) *InvoiceQuery

func (*InvoiceQuery) OrHas

func (q *InvoiceQuery) OrHas(relation, operator string, count int) *InvoiceQuery

func (*InvoiceQuery) OrWhere

func (q *InvoiceQuery) OrWhere(column any, args ...any) *InvoiceQuery

OrWhere adds an or-where clause; a func(*InvoiceQuery) in place of the column adds a group.

func (*InvoiceQuery) OrWhereDoesntHave

func (q *InvoiceQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) OrWhereHas

func (q *InvoiceQuery) OrWhereHas(relation string, callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) OrWhereNot

func (q *InvoiceQuery) OrWhereNot(column any, args ...any) *InvoiceQuery

OrWhereNot adds an or-joined negated where clause, or a negated group.

func (*InvoiceQuery) OrWhereRelation

func (q *InvoiceQuery) OrWhereRelation(relation string, column any, args ...any) *InvoiceQuery

func (*InvoiceQuery) OrderBy

func (q *InvoiceQuery) OrderBy(column any, direction ...string) *InvoiceQuery

func (*InvoiceQuery) OrderByDesc

func (q *InvoiceQuery) OrderByDesc(column any) *InvoiceQuery

func (*InvoiceQuery) Paginate

func (q *InvoiceQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (InvoiceCollection, *pagination.LengthAwarePage, error)

func (*InvoiceQuery) Pluck

func (q *InvoiceQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)

func (*InvoiceQuery) Select

func (q *InvoiceQuery) Select(columns ...any) *InvoiceQuery

func (*InvoiceQuery) SelectRaw

func (q *InvoiceQuery) SelectRaw(expression string, bindings ...any) *InvoiceQuery

func (*InvoiceQuery) SimplePaginate

func (q *InvoiceQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (InvoiceCollection, *pagination.Page, error)

func (*InvoiceQuery) Sole

func (q *InvoiceQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Invoice, error)

func (*InvoiceQuery) SoleValue

func (q *InvoiceQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvoiceQuery) Sum

func (q *InvoiceQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)

func (*InvoiceQuery) Touch

func (q *InvoiceQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)

func (*InvoiceQuery) Update

func (q *InvoiceQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)

func (*InvoiceQuery) UpdateOrCreate

func (q *InvoiceQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Invoice, error)

func (*InvoiceQuery) Upsert

func (q *InvoiceQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, update []string) (int64, error)

func (*InvoiceQuery) Value

func (q *InvoiceQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvoiceQuery) ValueOrFail

func (q *InvoiceQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)

func (*InvoiceQuery) Where

func (q *InvoiceQuery) Where(column any, args ...any) *InvoiceQuery

Where adds a where clause; a func(*InvoiceQuery) in place of the column adds a group.

func (*InvoiceQuery) WhereBelongsTo

func (q *InvoiceQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *InvoiceQuery

func (*InvoiceQuery) WhereBetween

func (q *InvoiceQuery) WhereBetween(column any, from, to any) *InvoiceQuery

func (*InvoiceQuery) WhereColumn

func (q *InvoiceQuery) WhereColumn(first any, args ...any) *InvoiceQuery

func (*InvoiceQuery) WhereDoesntHave

func (q *InvoiceQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) WhereExists

func (q *InvoiceQuery) WhereExists(callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) WhereHas

func (q *InvoiceQuery) WhereHas(relation string, callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) WhereHasCount

func (q *InvoiceQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *InvoiceQuery

func (*InvoiceQuery) WhereIn

func (q *InvoiceQuery) WhereIn(column any, values []any) *InvoiceQuery

func (*InvoiceQuery) WhereKey

func (q *InvoiceQuery) WhereKey(id any) *InvoiceQuery

func (*InvoiceQuery) WhereNot

func (q *InvoiceQuery) WhereNot(column any, args ...any) *InvoiceQuery

WhereNot adds a negated where clause, or a negated group.

func (*InvoiceQuery) WhereNotExists

func (q *InvoiceQuery) WhereNotExists(callback func(*query.Builder)) *InvoiceQuery

func (*InvoiceQuery) WhereNotIn

func (q *InvoiceQuery) WhereNotIn(column any, values []any) *InvoiceQuery

func (*InvoiceQuery) WhereNotNull

func (q *InvoiceQuery) WhereNotNull(columns ...any) *InvoiceQuery

func (*InvoiceQuery) WhereNull

func (q *InvoiceQuery) WhereNull(columns ...any) *InvoiceQuery

func (*InvoiceQuery) WhereRelation

func (q *InvoiceQuery) WhereRelation(relation string, column any, args ...any) *InvoiceQuery

func (*InvoiceQuery) With

func (q *InvoiceQuery) With(relations ...string) *InvoiceQuery

func (*InvoiceQuery) WithAvg

func (q *InvoiceQuery) WithAvg(relation, column string) *InvoiceQuery

func (*InvoiceQuery) WithCount

func (q *InvoiceQuery) WithCount(relations ...string) *InvoiceQuery

func (*InvoiceQuery) WithExists

func (q *InvoiceQuery) WithExists(relation string) *InvoiceQuery

func (*InvoiceQuery) WithMax

func (q *InvoiceQuery) WithMax(relation, column string) *InvoiceQuery

func (*InvoiceQuery) WithMin

func (q *InvoiceQuery) WithMin(relation, column string) *InvoiceQuery

func (*InvoiceQuery) WithSum

func (q *InvoiceQuery) WithSum(relation, column string) *InvoiceQuery

func (*InvoiceQuery) Without

func (q *InvoiceQuery) Without(relations ...string) *InvoiceQuery

func (*InvoiceQuery) WithoutGlobalScope

func (q *InvoiceQuery) WithoutGlobalScope(identifier string) *InvoiceQuery

func (*InvoiceQuery) WithoutGlobalScopes

func (q *InvoiceQuery) WithoutGlobalScopes(identifiers ...string) *InvoiceQuery

type InvoiceRow

type InvoiceRow struct {
	ID, Period, Gross, Fees, Costs, Net, Share, Amount string
	Status, StatusKey, Withdrawal, WithdrawalKey       string
	Withdrawable                                       bool
	WithdrawURL, ReceiptURL, RejectedReason            string
}

InvoiceRow is one invoice as a screen shows it.

type InvoiceStatus

type InvoiceStatus string

InvoiceStatus is where an invoice stands.

const (
	// InvoiceAvailable can be withdrawn.
	InvoiceAvailable InvoiceStatus = "available"
	// InvoiceOverdue can still be withdrawn; a later period has closed since.
	InvoiceOverdue InvoiceStatus = "overdue"
	// InvoiceWithdrawn was withdrawn.
	InvoiceWithdrawn InvoiceStatus = "withdrawn"
	// InvoiceNothingDue closed a period whose net was zero or negative: no
	// amount, no withdrawal, and no loss carried into the next period.
	InvoiceNothingDue InvoiceStatus = "nothing_due"
)

type InvoiceView

type InvoiceView struct {
	Invoice    Invoice
	Withdrawal *wallet.WithdrawalRequest
}

InvoiceView is an invoice with the state of its withdrawal, as arandu-wallet knows it.

func (InvoiceView) Pending

func (v InvoiceView) Pending() bool

Pending reports whether a request for it is waiting for an operator.

func (InvoiceView) Withdrawable

func (v InvoiceView) Withdrawable() bool

Withdrawable reports whether the investor may ask for it now.

func (InvoiceView) Withdrawn

func (v InvoiceView) Withdrawn() bool

Withdrawn reports whether the invoice was paid out.

type Labels

type Labels struct {
	Locale string
	// contains filtered or unexported fields
}

Labels are the sentences of this package's screens in one locale.

func (Labels) Errors added in v0.3.0

func (l Labels) Errors(errs validation.Errors) validation.Errors

Errors are the messages of a rejected input in the labels' locale, field by field. The value given is not changed.

func (Labels) Field added in v0.3.0

func (l Labels) Field(name string) string

Field is what a person reads in place of an input's name, in a summary of the rejected fields: "pix_key" reads "Chave PIX". A field with no line reads the way hesape's page would have drawn it.

func (Labels) Kind

func (l Labels) Kind(k EntryKind) string

Kind is the label of an entry's kind.

func (Labels) Message added in v0.3.0

func (l Labels) Message(msg string) string

Message is one validation message in the labels' locale.

The messages are written in English where they are produced -- by this package from its own English lines, by the framework's validation helpers ("is required") and by arandu-wallet -- because validation.Errors carries sentences and not keys, and an API client reads them as they always were. Here each one is read back against the English lines of the "validation" group, placeholders and all, and drawn again from the same key in the locale asked for. A message no line matches comes back as it was.

func (Labels) Month added in v0.3.0

func (l Labels) Month(month int) string

Month is the name of a month, 1 to 12, as the reports print it.

func (Labels) Status

func (l Labels) Status(s InvoiceStatus) string

Status is the label of an invoice's status.

func (Labels) Summary added in v0.3.0

func (l Labels) Summary(errs validation.Errors) []string

Summary is one line per rejected message, the field named before it, for the banner above a form: "Chave PIX: Preencha este campo.". Nil when nothing was rejected, so a layout that ranges over it draws no banner.

func (Labels) T

func (l Labels) T(key string) string

T reads a key of this package: "screen.dashboard_title".

type Module

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

Module is what the application registers.

It implements foundation.Module, which is Name and Routes and nothing else -- that pair is the whole public contract between a package and the framework.

It also implements foundation.Migratable, because it owns a table, and foundation.Publishable, because it hands view sources to the project. The other optional interfaces are declared beside Module in the framework and are opted into the same way, by implementing them: Bootable to prepare state at boot, Background to run a loop of its own, Schedulable to declare work for the scheduler, Health to report on the storage it depends on, Closable to give resources back at shutdown.

func New

func New(cfg Config, db *data.DB, sessions *security.SessionStore) (*Module, error)

New returns the module, or the reason it cannot be built.

The collaborators are parameters and not fields somebody fills in afterwards: a module that could be registered half-wired is a module whose first request is the thing that reports the missing half.

It returns an error rather than panicking or carrying on, because everything it refuses is a wiring mistake, and a wiring mistake found at boot costs one restart. The same mistake found later is a request that reached a nil handle.

func (*Module) AdminRoutes added in v0.2.0

func (m *Module) AdminRoutes(r *fhttp.Router)

AdminRoutes registers the admin's routes alone, under AdminPrefix, for an application that mounts them inside its operator console with that console's guards on r.

func (*Module) Boot

func (m *Module) Boot(context.Context) error

Boot refuses to serve when a view this package renders is not in the binary.

A compiled view registers itself from init(), so by the time anything boots the question has one answer already: either the application published the files, compiled them and imported the package they became, or it did not. Asking here turns "did anybody run the install command" into one refusal at start-up that names the views and the command, instead of a 500 on the first request that reached one of them -- which is where it used to be answered, once per page, to whoever happened to open it.

It also holds the destination. Every file the archive offers has to land under the module directory named after this module: an archive that reached resources/views/home.kyse.go would land on a page the application wrote, and what publishes the files writes what the archive says.

func (*Module) InvestorRoutes added in v0.2.0

func (m *Module) InvestorRoutes(r *fhttp.Router)

InvestorRoutes registers the investor's own routes alone, under Prefix, for an application that mounts them inside its own side -- a customer's panel -- with that side's guards on r.

func (*Module) Labels

func (m *Module) Labels(locale string) Labels

Labels answers the sentences in a locale: the one given, else Config.Locale, else FallbackLocale.

func (*Module) Migrations

func (m *Module) Migrations() []foundation.Migration

Migrations declares the schema this module owns.

They are returned in the order their names sort in, which is the order they apply in: the name carries the order, and nothing else decides it.

func (*Module) Name

func (m *Module) Name() string

Name is the module identifier: a lowercase slug, stable, no spaces.

It is what `aru route:list` groups by and what the route names are prefixed with, so changing it changes addresses that other code has already written down.

func (*Module) Publishes

func (m *Module) Publishes() []foundation.Publication

Publishes declares the files this package offers, each at the path it takes relative to the root of the project.

One tree, under one tag. A publication may carry a page, a component, a configuration file, a migration, a catalogue of sentences or an asset, and this package offers the first of those and nothing else. Each absence is a decision rather than an omission:

  • configuration is the Config struct New is handed, checked by the compiler and validated before the module exists. A file copied into the project beside it would be a second place to say the same thing, and only one of the two could be the one the code reads.
  • a stylesheet, a script or any other asset is registered with the view layer and served from an address derived from its own bytes. Copying one into the project would put a second copy of those bytes under a second address, and a page can only reference one of them.
  • translations are overridden by writing the lines the application wants into its own override tree, which the catalogue loader already reads. A copy of every line this package ships is a copy that goes stale, and it goes stale without saying so.
  • migrations are declared and collected, never copied. A copy in the project's own migration directory is found by the runner as well, so one schema change applies twice under two names.

What is left is the markup, and it is here for the reason the others are not: it is the one thing the project is expected to edit. A package cannot know what a screen should say in a product it has never seen.

func (*Module) Routes

func (m *Module) Routes(r *fhttp.Router)

Routes registers every route of the module: the investor's and the admin's.

They are named, so a URL is built from a name rather than written out a second time somewhere else -- two spellings of one address disagree, and the failure when they do is a link to a 404.

Every route needs somebody signed in, so the guard is mounted once, on the router they are registered on, rather than route by route: r is replaced by the guarded group before the first registration, and no unguarded router is left in scope for the next route to be added to. RequireAuth sends a request with no session to the sign-in screen, and puts the subject of one that has a session on its context, where a handler reads it with ctx.User; Config.Middleware runs after it, and Config.AdminMiddleware after that on the admin's routes.

func (*Module) Service

func (m *Module) Service() *InvestorService

Service is the use cases, for an application that calls them from its own code: the events endpoint it owns, a job, a command. Every method asks the policy, so handing it out opens nothing.

func (*Module) URLs added in v0.2.0

func (m *Module) URLs() URLs

URLs answers the addresses the module is mounted at, for an application that links to them from its own pages.

type Paths added in v0.2.0

type Paths struct {
	Me, Contracts, Invoices, Reports, PayoutAccounts string
	File, Statement, Projection, Costs               string
	Withdrawal, Receipt                              string
	Admin, Investors, Suspension, Amendments         string
	Closings, Due, Entries, Reversal, End            string
	Withdrawals, Processing, Payment, Rejection      string
}

Paths are the segments the routes of this package are built from. Each one starts with "/" and holds no wildcard; Me may be "/", which mounts the investor's own panel at Prefix itself.

GET  Prefix + Me                                 the investor's panel
GET  Prefix + Me + Contracts                     their contracts
GET  Prefix + Me + Invoices                      their invoices
GET  Prefix + Me + Reports + /{year}[/{month}]   their reports
POST Prefix + Me + PayoutAccounts                a payout account
GET  Prefix + Contracts + /{id} + File|Statement|Projection
GET  Prefix + Costs
POST Prefix + Invoices + /{id} + Withdrawal      ask for an invoice
GET  Prefix + Invoices + /{id} + Receipt         the receipt of its payment

and under AdminPrefix: Investors (with Suspension, Contracts, Invoices and Reports below one), Contracts + /{id} + Amendments|Closings, Closings + Due, Entries (with Reversal), Costs (with End), and Withdrawals (with Processing, Payment and Rejection).

type Payer

type Payer struct {
	Name     string
	Document string // CNPJ, digits or formatted
}

Payer is who pays the investors, as it is printed on the income report: the company that owns the application. The application passes it in Config.Payer; an empty one prints a dash, never an invented name.

type PersonKind

type PersonKind string

PersonKind is whether an investor is a natural person or a company.

const (
	// Person is a natural person, identified by a CPF.
	Person PersonKind = "person"
	// Company is a legal entity, identified by a CNPJ.
	Company PersonKind = "company"
)

type ProjectedCost

type ProjectedCost struct {
	Item     CostItem
	Products []string
	Amount   int64
}

ProjectedCost is one declared cost and how much of it falls in the open period, before it is shared out.

type ProjectedCostRow

type ProjectedCostRow struct{ Name, Category, Recurrence, Scope, Amount string }

ProjectedCostRow is one declared cost in the open period.

type Projection

type Projection struct {
	Contract              Contract
	PeriodStart           Day
	PeriodEnd             Day
	Costs                 []ProjectedCost
	Gross, Fees           int64
	ProjectedCosts        int64
	EstimatedNet          int64
	EstimatedAmount       int64
	EstimatedCostRatioPPM int64
}

Projection is the open period of a contract: what it is expected to cost, what came in so far, and where that leaves the investor if nothing else happens before it closes.

type ProjectionPageData

type ProjectionPageData struct {
	Screen
	Contract                           ContractRow
	PeriodStart, PeriodEnd             string
	Costs                              []ProjectedCostRow
	Gross, Fees, ProjectedCosts, Ratio string
	EstimatedNet, EstimatedAmount      string
}

ProjectionPageData is one contract's open period.

type Recurrence

type Recurrence string

Recurrence is how often a cost's amount is due.

const (
	// Monthly is the amount every billing month.
	Monthly Recurrence = "monthly"
	// Yearly is the amount every year, a twelfth of it every billing month.
	Yearly Recurrence = "yearly"
	// Once is the amount on StartsOn, and never again.
	Once Recurrence = "once"
)
type ReportLink struct{ Label, URL string }

ReportLink is one report a screen offers: its label and its address.

type Resource

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

Resource is the list of fields one Investor is allowed to answer with.

A declared list rather than the entity itself. An encoder handed the entity answers with whatever fields it happens to have, including the ones somebody adds later without ever opening the handler -- and TenantID is exactly such a field: it names another customer's identifier and belongs in no response.

func NewResource

func NewResource(record Investor) Resource

NewResource snapshots one record for the response.

func (Resource) ToArray

func (r Resource) ToArray() map[string]any

ToArray returns the fields that may leave, by name.

func (Resource) With

func (r Resource) With() map[string]any

With returns what goes beside the fields at the top level of the response. Nothing does here, and a resource that has nothing to add says so by answering nil.

type Scope

type Scope struct {
	All      bool
	Products map[string]bool
}

Scope is a set of products, or the whole application.

type ScopedCost

type ScopedCost struct {
	Amount int64
	Scope  Scope
}

ScopedCost is a cost's amount in a window and the products that bear it.

type Screen

type Screen struct {
	hview.Page
	Labels Labels
	// Prefix is where the investor's routes are mounted. URLs has every
	// address; Prefix is kept for a published view that still reads it.
	Prefix string
	// URLs are the addresses of the package's routes.
	URLs URLs
	// contains filtered or unexported fields
}

Screen is what every page of this package carries: the page hesape's view.New builds, the application's chrome, the sentences, and where the package is mounted.

It embeds hesape's view.Page, so every page of this package is a hesape/view.Layout -- what the layouts of an application on Arandu framework v0.62 and newer assert -- and it answers HasErrors and ErrorSummary as well, so it is also the framework/view.Layout an older layout asks for.

func (Screen) AdminNav

func (s Screen) AdminNav(current string) template.HTML

AdminNav is the bar on top of every admin screen: the four lists the admin works in, the current one marked.

func (Screen) All added in v0.3.0

func (s Screen) All() []string

All is one line per rejected message, for the banner above a form, in the screen's language: the field is named by its label in the catalogue ("Chave PIX: Preencha este campo."), where hesape's page would name it by its input ("Pix key").

func (Screen) BankAccountTypeOptions added in v0.2.0

func (s Screen) BankAccountTypeOptions() []components.SelectOption

BankAccountTypeOptions are the kinds of bank account.

func (Screen) CellForm

func (s Screen) CellForm(action, label, variant string, inputs ...CellInput) template.HTML

CellForm is a small form posted from a table cell: the CSRF token of the page, the fields given, and one button. Every value is escaped; nothing the caller passes is written as markup.

func (Screen) Chrome added in v0.2.0

func (s Screen) Chrome() any

Chrome is what Config.Chrome answered for this screen: the application's sidebar, navigation and account menu, in whatever type its layout draws from. A layout asserts that type on it; nil when Config.Chrome is nil.

func (Screen) ErrorSummary added in v0.2.0

func (s Screen) ErrorSummary() []string

ErrorSummary is one line per rejected field: framework/view.Layout's name for All.

func (Screen) FieldErrors added in v0.2.0

func (s Screen) FieldErrors(name string) []string

FieldErrors is every message for one field.

func (Screen) Form

func (s Screen) Form() FormState

Form is the form state of the page.

func (Screen) HasErrors added in v0.2.0

func (s Screen) HasErrors() bool

HasErrors says whether the attempt that landed here was rejected: framework/view.Layout's name for hesape's Any.

func (Screen) KindOptions

func (s Screen) KindOptions() []components.SelectOption

KindOptions are the kinds of entry a filter offers.

func (Screen) LogValue added in v0.2.0

func (s Screen) LogValue() slog.Value

LogValue is the page as a log line carries it, the token redacted.

func (Screen) ManualKindOptions

func (s Screen) ManualKindOptions() []components.SelectOption

ManualKindOptions are the kinds of entry the admin types by hand: a reversal is made from the entry it undoes, never typed.

func (Screen) MarshalJSON added in v0.2.0

func (s Screen) MarshalJSON() ([]byte, error)

MarshalJSON writes the page with the CSRF token redacted, as framework/view.Page does: a page dumped for debugging never publishes the token. It answers for every page data that embeds Screen.

func (Screen) PayForm added in v0.2.0

func (s Screen) PayForm(action string) template.HTML

PayForm is the operator's form, drawn inside a table cell, that marks a withdrawal paid: the end-to-end identifier of the PIX or transfer, and the receipt, a PDF, JPEG or PNG.

func (Screen) PersonOptions

func (s Screen) PersonOptions() []components.SelectOption

PersonOptions are the kinds of person an investor can be.

func (Screen) PixKeyOptions

func (s Screen) PixKeyOptions() []components.SelectOption

PixKeyOptions are the kinds of PIX key.

func (Screen) RecurrenceOptions

func (s Screen) RecurrenceOptions() []components.SelectOption

RecurrenceOptions are how often a cost is due.

func (Screen) SearchLabel added in v0.3.0

func (s Screen) SearchLabel(table string) string

SearchLabel is the name a screen reader gives a table's search box: "Buscar em Extrato".

func (Screen) TableLines

func (s Screen) TableLines() components.DataTableLines

TableLines are the sentences a data table on these screens says.

func (Screen) WithdrawForm added in v0.2.0

func (s Screen) WithdrawForm(action string, accounts []AccountOption) template.HTML

WithdrawForm is the form, drawn inside a table cell, that asks for one invoice to be paid into one of the accounts given.

func (Screen) WithdrawalStatusOptions

func (s Screen) WithdrawalStatusOptions() []components.SelectOption

WithdrawalStatusOptions are where a withdrawal request can stand.

type Statement

type Statement struct {
	Contract Contract
	Lines    []StatementLine
	// Totals of the lines shown.
	Gross, Fees, Costs, Net int64
	// Open marks the lines whose cost share is an estimate: they belong to the
	// period that has not closed yet, whose costs are the projection's.
	Open map[string]bool
}

Statement is one contract's entries as the investor reads them.

type StatementFilter

type StatementFilter struct {
	From, To  Day // [From, To], by the day the entry happened
	Kind      EntryKind
	ProductID string
}

StatementFilter narrows a statement. Every field is optional.

type StatementLine

type StatementLine struct {
	Entry Entry
	Cost  int64
	Net   int64
}

StatementLine is one entry as the investor's statement shows it: its own gross and fee, its share of the period's costs, and what is left.

func SpreadCosts

func SpreadCosts(entries []Entry, costs int64) []StatementLine

SpreadCosts gives each entry its share of the costs, in proportion to its gross, and makes the shares add up to exactly the total: the centavos the rounding leaves go, one each, to the lines with the largest remainders. Entries with no positive gross carry no cost.

type StatementPageData

type StatementPageData struct {
	Screen
	Contract                ContractRow
	Rows                    []StatementRow
	Gross, Fees, Costs, Net string
	From, To, Kind, Product string
	URL                     string
	HasEstimates            bool
}

StatementPageData is one contract's statement.

type StatementRow

type StatementRow struct {
	ID, Day, Product, Kind, Description                 string
	Gross, Fee, FeeDetail, Cost, Net                    string
	Estimate                                            bool
	GrossSort, FeeSort, CostSort, NetSort, DaySortValue string
}

StatementRow is one line of a statement.

type URLs added in v0.2.0

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

URLs are the addresses of this package's routes, built from Config.Prefix, Config.AdminPrefix and Config.Paths. The route table is built from the same methods with the wildcard in place of the identifier, so an address a screen links to and the pattern that answers it are one spelling.

func NewURLs added in v0.2.0

func NewURLs(prefix, adminPrefix string, paths Paths) URLs

NewURLs builds the addresses for a prefix, an admin prefix and the paths, as New would from a Config holding them. Empty segments take DefaultPaths, and an empty admin prefix is the prefix followed by Paths.Admin.

func (URLs) AdminCosts added in v0.2.0

func (u URLs) AdminCosts() string

AdminCosts are the declared costs, for the admin who declares them.

func (URLs) AdminPrefix added in v0.2.0

func (u URLs) AdminPrefix() string

AdminPrefix is where the admin's routes are mounted.

func (URLs) Amend added in v0.2.0

func (u URLs) Amend(contractID string) string

Amend registers an amendment of a contract.

func (URLs) Close added in v0.2.0

func (u URLs) Close(contractID string) string

Close closes a contract's period.

func (URLs) CloseDue added in v0.2.0

func (u URLs) CloseDue() string

CloseDue closes every contract due on a day.

func (URLs) ContractFile added in v0.2.0

func (u URLs) ContractFile(id string) string

ContractFile downloads a contract's signed copy.

func (URLs) Costs added in v0.2.0

func (u URLs) Costs() string

Costs are the declared costs, as the investor reads them.

func (URLs) EndCost added in v0.2.0

func (u URLs) EndCost(id string) string

EndCost ends a declared cost.

func (URLs) Entries added in v0.2.0

func (u URLs) Entries() string

Entries are the admin's books.

func (URLs) Investor added in v0.2.0

func (u URLs) Investor(id string) string

Investor is the admin's page of one investor.

func (URLs) InvestorContracts added in v0.2.0

func (u URLs) InvestorContracts(id string) string

InvestorContracts lists (GET) and registers (POST) an investor's contracts.

func (URLs) InvestorInvoices added in v0.2.0

func (u URLs) InvestorInvoices(id string) string

InvestorInvoices lists an investor's invoices for the admin.

func (URLs) InvestorReports added in v0.2.0

func (u URLs) InvestorReports(id string) string

InvestorReports is the base of an investor's reports for the admin.

func (URLs) Investors added in v0.2.0

func (u URLs) Investors() string

Investors is the admin's registry.

func (URLs) Me added in v0.2.0

func (u URLs) Me() string

Me is the investor's own panel.

func (URLs) MyContracts added in v0.2.0

func (u URLs) MyContracts() string

MyContracts lists the investor's own contracts.

func (URLs) MyInvoices added in v0.2.0

func (u URLs) MyInvoices() string

MyInvoices lists the investor's own invoices.

func (URLs) MyReports added in v0.2.0

func (u URLs) MyReports() string

MyReports is the base of the investor's reports: /{year} and /{year}/{month} below it.

func (URLs) Pay added in v0.2.0

func (u URLs) Pay(id string) string

Pay records a withdrawal paid, with its receipt.

func (URLs) PayoutAccounts added in v0.2.0

func (u URLs) PayoutAccounts() string

PayoutAccounts is where the investor declares an account to be paid into.

func (URLs) Prefix added in v0.2.0

func (u URLs) Prefix() string

Prefix is where the investor's routes are mounted.

func (URLs) Process added in v0.2.0

func (u URLs) Process(id string) string

Process takes a withdrawal to be paid.

func (URLs) Projection added in v0.2.0

func (u URLs) Projection(id string) string

Projection is a contract's open period.

func (URLs) Receipt added in v0.2.0

func (u URLs) Receipt(invoiceID string) string

Receipt downloads the receipt of an invoice's paid withdrawal.

func (URLs) Reject added in v0.2.0

func (u URLs) Reject(id string) string

Reject refuses a withdrawal with a reason.

func (URLs) Reverse added in v0.2.0

func (u URLs) Reverse(id string) string

Reverse reverses one entry.

func (URLs) Statement added in v0.2.0

func (u URLs) Statement(id string) string

Statement is a contract's statement.

func (URLs) Suspension added in v0.2.0

func (u URLs) Suspension(id string) string

Suspension suspends (POST) or reactivates (DELETE) an investor.

func (URLs) Withdraw added in v0.2.0

func (u URLs) Withdraw(invoiceID string) string

Withdraw asks for one invoice, whole.

func (URLs) Withdrawals added in v0.2.0

func (u URLs) Withdrawals() string

Withdrawals is the queue of investors' withdrawals.

type UpdateRequest

type UpdateRequest struct {
	Name                string
	LegalName           string
	LegalRepresentative string
	Email               string
}

UpdateRequest is what may change in an investor after it is registered. The kind and the document are not here: a person does not become a company, and a different document is a different investor.

type WithdrawalRow

type WithdrawalRow struct {
	ID, Investor, Amount, Account, Status, StatusKey, RequestedAt, Reason string
	Open, Processing, Paid                                                bool
	ProcessURL, PayURL, RejectURL, ReceiptURL                             string
}

WithdrawalRow is one investor's withdrawal request in the operator's queue.

Jump to

Keyboard shortcuts

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