Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/recruiting/dto.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/recruiting/dto.go |
| Original SHA-256 | bbf3b14d08ee34dc52775be42099278afb83e5d5b021b2a37fdb37d7e68e8174 |
| Git blob SHA | bec4c6b548fc0195f7c50e52cd41058f06cb83a3 |
| Reading-copy SHA-256 | bbf3b14d08ee34dc52775be42099278afb83e5d5b021b2a37fdb37d7e68e8174 |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / internal/modules/recruiting/dto.go | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / internal/modules/recruiting/dto.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓119 lines · 5.2 KB
// Package recruiting is the recruiting operations module: the clients an organization recruits for, the
// people at those clients, and later the job orders placed against them. It is the write side that
// recruitMATCH reports on.
//
// Two decisions shape every write in this package.
//
// Concurrency is optimistic, not last write wins. Every update carries the updated_at the caller read,
// and the UPDATE matches on it. Two recruiters editing the same client is uncommon but silently losing
// one of their edits is unacceptable, and a timestamptz round trips through RFC3339Nano exactly, so the
// token needs no schema change and no version column.
//
// Constraint violations are translated, never leaked. A duplicate client name is a 409 that names the
// problem, not a 500 with a Postgres string in it. The database is the authority on uniqueness because
// only the database can check it without a race, so the service inserts and interprets the failure
// rather than pre checking and hoping nothing changes in between.
package recruiting
import "time"
// Client is a company this organization recruits for.
type Client struct {
ID string `json:"id"`
Name string `json:"name"`
UEI string `json:"uei,omitempty"`
Industry string `json:"industry,omitempty"`
Website string `json:"website,omitempty"`
Status string `json:"status"`
Notes string `json:"notes,omitempty"`
ContactCount int `json:"contact_count"`
// Ownership is the lock. A client with an owner is edited by that owner; an unowned client is
// claimable by anyone with write capability. OwnerName is carried so the UI can say who holds an
// account without a second lookup, because the answer to a collision is a conversation.
OwnerUserID string `json:"owner_user_id,omitempty"`
OwnerName string `json:"owner_name,omitempty"`
OwnerSince string `json:"owner_since,omitempty"`
CreatedAt string `json:"created_at"`
// UpdatedAt is both a display value and the optimistic concurrency token. A caller sends it back on
// an update and the write is refused if the row moved underneath them.
UpdatedAt string `json:"updated_at"`
}
// Contact is a person at a client.
type Contact struct {
ID string `json:"id"`
ClientID string `json:"client_id"`
FullName string `json:"full_name"`
Title string `json:"title,omitempty"`
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
IsHiringManager bool `json:"is_hiring_manager"`
IsPrimary bool `json:"is_primary"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// ClientDetail is a client with its people, which is how the detail screen reads it.
type ClientDetail struct {
Client
Contacts []Contact `json:"contacts"`
}
// ClientList is an envelope rather than a bare array so the caller learns whether more pages exist
// without issuing a second count query.
type ClientList struct {
Clients []Client `json:"clients"`
Limit int `json:"limit"`
Offset int `json:"offset"`
Total int `json:"total"`
}
// CreateClientInput is the create body. Only Name is required; a client is often entered from a phone
// call with nothing else known yet, and forcing more would push people to type placeholders.
type CreateClientInput struct {
Name string `json:"name"`
UEI string `json:"uei"`
Industry string `json:"industry"`
Website string `json:"website"`
Status string `json:"status"`
Notes string `json:"notes"`
}
// UpdateClientInput carries every editable field plus the concurrency token. Fields are pointers so an
// omitted field means leave it alone, which is different from an empty string meaning clear it.
type UpdateClientInput struct {
ExpectedUpdatedAt string `json:"expected_updated_at"`
Name *string `json:"name,omitempty"`
UEI *string `json:"uei,omitempty"`
Industry *string `json:"industry,omitempty"`
Website *string `json:"website,omitempty"`
Status *string `json:"status,omitempty"`
Notes *string `json:"notes,omitempty"`
}
type CreateContactInput struct {
FullName string `json:"full_name"`
Title string `json:"title"`
Email string `json:"email"`
Phone string `json:"phone"`
IsHiringManager bool `json:"is_hiring_manager"`
IsPrimary bool `json:"is_primary"`
}
type UpdateContactInput struct {
ExpectedUpdatedAt string `json:"expected_updated_at"`
FullName *string `json:"full_name,omitempty"`
Title *string `json:"title,omitempty"`
Email *string `json:"email,omitempty"`
Phone *string `json:"phone,omitempty"`
IsHiringManager *bool `json:"is_hiring_manager,omitempty"`
IsPrimary *bool `json:"is_primary,omitempty"`
Status *string `json:"status,omitempty"`
}
// ts renders a database timestamp for the wire. RFC3339Nano is used rather than RFC3339 because it
// preserves the microsecond precision Postgres stores, which is what makes updated_at usable as a
// concurrency token: a truncated value would never match on the way back.
func ts(t time.Time) string { return t.UTC().Format(time.RFC3339Nano) }