Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/recruiting/requisition_dto.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 |
| Branch | feature/aioe-upgrade |
| Path or archive member | internal/modules/recruiting/requisition_dto.go |
| Original SHA-256 | 966538376bf5756fd43294bb3962eca6d6add6557458336de710e2e3bb01ab48 |
| Git blob SHA | 13e01ceba285b341d9f0b786c6b1048016c88f29 |
| Reading-copy SHA-256 | 966538376bf5756fd43294bb3962eca6d6add6557458336de710e2e3bb01ab48 |
Recovered source transcript
Download complete source text ↓172 lines · 7.8 KB
package recruiting
import (
"time"
"github.com/shopspring/decimal"
)
// Requisition is a job order: a role a client has asked this organization to fill.
//
// Money is carried as decimal and rendered as a JSON string, never a float. A bill rate is multiplied by
// hours and by a wrap rate downstream, and binary floating point cannot represent 0.1 exactly, so a rate
// that survived a round trip through a JSON number would not necessarily be the rate that was agreed.
//
// The three clocks are reported separately because they answer different questions. AgeDays is the wall
// clock a client sees. WorkingDays removes time the order spent on hold, which is the number that says
// how fast this organization actually works. HeldDays is the difference, shown so neither number has to
// be taken on trust.
type Requisition struct {
ID string `json:"id"`
ClientID string `json:"client_id,omitempty"`
ClientName string `json:"client_name,omitempty"`
// The hiring manager is constrained by the database to be a contact AT this client, so a submittal
// cannot be addressed to someone at a different company.
HiringManagerID string `json:"hiring_manager_id,omitempty"`
HiringManagerName string `json:"hiring_manager_name,omitempty"`
// Ownership is the lock, the same rule clients use. An unowned order is claimable by anyone with
// write capability; an owned one is edited by its holder or an admin.
OwnerUserID string `json:"owner_user_id,omitempty"`
OwnerName string `json:"owner_name,omitempty"`
// RequirementID bridges to the federal capture side when a job order came from a solicitation.
RequirementID string `json:"requirement_id,omitempty"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
LaborCategory string `json:"labor_category,omitempty"`
Openings int `json:"openings"`
Priority string `json:"priority"`
EmploymentType string `json:"employment_type"`
Status string `json:"status"`
// Clearance is a self reported indicator throughout this product, never a verified status.
RequiredLevel string `json:"required_level"`
RequiredPoly string `json:"required_poly"`
WorkLocation string `json:"work_location,omitempty"`
RemoteAllowed bool `json:"remote_allowed"`
BillRateMin *decimal.Decimal `json:"bill_rate_min,omitempty"`
BillRateMax *decimal.Decimal `json:"bill_rate_max,omitempty"`
PayRateMin *decimal.Decimal `json:"pay_rate_min,omitempty"`
PayRateMax *decimal.Decimal `json:"pay_rate_max,omitempty"`
SalaryMin *decimal.Decimal `json:"salary_min,omitempty"`
SalaryMax *decimal.Decimal `json:"salary_max,omitempty"`
OpenedAt string `json:"opened_at"`
TargetFillDate string `json:"target_fill_date,omitempty"`
ClosedAt string `json:"closed_at,omitempty"`
OnHoldSince string `json:"on_hold_since,omitempty"`
AgeDays float64 `json:"age_days"`
WorkingDays float64 `json:"working_days"`
HeldDays float64 `json:"held_days"`
// DaysToTarget is negative when the target fill date has passed. Nil when no target was set, which
// is different from zero and must not be rendered as "due today".
DaysToTarget *int `json:"days_to_target,omitempty"`
CreatedAt string `json:"created_at"`
// UpdatedAt doubles as the optimistic concurrency token.
UpdatedAt string `json:"updated_at"`
}
// RequisitionList is an envelope so the caller learns the total without a second query.
type RequisitionList struct {
Requisitions []Requisition `json:"requisitions"`
Limit int `json:"limit"`
Offset int `json:"offset"`
Total int `json:"total"`
}
// RequisitionEvent is one status change. Append only, and the source of every duration Phase 17 reports.
type RequisitionEvent struct {
ID string `json:"id"`
FromStatus string `json:"from_status,omitempty"`
ToStatus string `json:"to_status"`
DaysInFrom float64 `json:"days_in_from"`
Note string `json:"note,omitempty"`
ActorUserID string `json:"actor_user_id,omitempty"`
ActorUserName string `json:"actor_user_name,omitempty"`
OccurredAt string `json:"occurred_at"`
}
// RequisitionDetail is an order with its history, which is how the detail screen reads it.
type RequisitionDetail struct {
Requisition
Events []RequisitionEvent `json:"events"`
}
// CreateRequisitionInput. Only a title is required. A job order is usually opened from a phone call
// with the rate and the manager still unknown, and demanding them up front makes people type
// placeholders that are worse than a blank.
type CreateRequisitionInput struct {
ClientID string `json:"client_id"`
HiringManagerID string `json:"hiring_manager_id"`
RequirementID string `json:"requirement_id"`
Title string `json:"title"`
Description string `json:"description"`
LaborCategory string `json:"labor_category"`
Openings int `json:"openings"`
Priority string `json:"priority"`
EmploymentType string `json:"employment_type"`
Status string `json:"status"`
RequiredLevel string `json:"required_level"`
RequiredPoly string `json:"required_poly"`
WorkLocation string `json:"work_location"`
RemoteAllowed bool `json:"remote_allowed"`
BillRateMin string `json:"bill_rate_min"`
BillRateMax string `json:"bill_rate_max"`
PayRateMin string `json:"pay_rate_min"`
PayRateMax string `json:"pay_rate_max"`
SalaryMin string `json:"salary_min"`
SalaryMax string `json:"salary_max"`
TargetFillDate string `json:"target_fill_date"`
}
// UpdateRequisitionInput carries the editable fields plus the concurrency token. Pointers so an omitted
// field means leave it alone, which is different from an empty string meaning clear it.
//
// Status is deliberately absent. A status change moves clocks and writes an event, so it goes through
// ChangeStatus, where the transition graph decides whether it is legal. Allowing it here would let a
// PATCH write any status directly and bypass the entire lifecycle.
type UpdateRequisitionInput struct {
ExpectedUpdatedAt string `json:"expected_updated_at"`
ClientID *string `json:"client_id,omitempty"`
HiringManagerID *string `json:"hiring_manager_id,omitempty"`
Title *string `json:"title,omitempty"`
Description *string `json:"description,omitempty"`
LaborCategory *string `json:"labor_category,omitempty"`
Openings *int `json:"openings,omitempty"`
Priority *string `json:"priority,omitempty"`
EmploymentType *string `json:"employment_type,omitempty"`
RequiredLevel *string `json:"required_level,omitempty"`
RequiredPoly *string `json:"required_poly,omitempty"`
WorkLocation *string `json:"work_location,omitempty"`
RemoteAllowed *bool `json:"remote_allowed,omitempty"`
BillRateMin *string `json:"bill_rate_min,omitempty"`
BillRateMax *string `json:"bill_rate_max,omitempty"`
PayRateMin *string `json:"pay_rate_min,omitempty"`
PayRateMax *string `json:"pay_rate_max,omitempty"`
SalaryMin *string `json:"salary_min,omitempty"`
SalaryMax *string `json:"salary_max,omitempty"`
TargetFillDate *string `json:"target_fill_date,omitempty"`
}
// ChangeStatusInput. The note is what makes the event trail readable a year later: "client froze the
// program" and "candidate accepted elsewhere" are the same transition and different stories.
type ChangeStatusInput struct {
ExpectedUpdatedAt string `json:"expected_updated_at"`
Status string `json:"status"`
Note string `json:"note"`
}
const dateLayout = "2006-01-02"
// dateStr renders a Postgres date. Only the date part, because a target fill date has no time of day and
// showing one would imply a precision the field does not have.
func dateStr(t *time.Time) string {
if t == nil {
return ""
}
return t.UTC().Format(dateLayout)
}