package ledger import ( "time" "go.mongodb.org/mongo-driver/bson/primitive" ) // OwnershipRole captures legal roles (not permissions). type OwnershipRole string const ( RoleLegalOwner OwnershipRole = "legal_owner" RoleBeneficialOwner OwnershipRole = "beneficial_owner" RoleCustodian OwnershipRole = "custodian" RoleSignatory OwnershipRole = "signatory" ) type Ownership struct { OwnerPartyRef primitive.ObjectID `bson:"ownerPartyRef" json:"ownerPartyRef"` Role OwnershipRole `bson:"role" json:"role"` SharePct *float64 `bson:"sharePct,omitempty" json:"sharePct,omitempty"` // 0..100; nil = unspecified From time.Time `bson:"effectiveFrom" json:"effectiveFrom"` To *time.Time `bson:"effectiveTo,omitempty" json:"effectiveTo,omitempty"` // active if t < To; nil = open } func (o *Ownership) Validate() error { var verr *ValidationError if o.OwnerPartyRef.IsZero() { veAdd(&verr, "ownerPartyRef", "required", "owner party reference required") } switch o.Role { case RoleLegalOwner, RoleBeneficialOwner, RoleCustodian, RoleSignatory: default: veAdd(&verr, "role", "invalid", "unknown ownership role") } if o.SharePct != nil { if *o.SharePct < 0 || *o.SharePct > 100 { veAdd(&verr, "sharePct", "out_of_range", "must be between 0 and 100") } } if o.To != nil && o.To.Before(o.From) { veAdd(&verr, "effectiveTo", "before_from", "must be >= effectiveFrom") } return verr } func (o *Ownership) ActiveAt(t time.Time) bool { if t.Before(o.From) { return false } if o.To != nil && !t.Before(*o.To) { // active iff t < To return false } return true }