ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / internal/modules/recruiting/activity_service.go

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / internal/modules/recruiting/activity_service.go
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberinternal/modules/recruiting/activity_service.go
Original SHA-256286b5369172eaddee579ba134e1e340ca91ec33f628e8f23a34fcb1d5a477e9d
Git blob SHAb7ede1ed29673dc9498696e71473500eb3cbc2cb
Reading-copy SHA-256286b5369172eaddee579ba134e1e340ca91ec33f628e8f23a34fcb1d5a477e9d

Original source ↗

Every recorded occurrence

These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.

Original recordBranch or archiveRevision / identifierOriginal location
Janady13/missionmatch / internal/modules/recruiting/activity_service.gofeature/opportunity-to-outcome720d47fae476b0d38477ae4401697d372b1ea2bcOpen original
Janady13/missionmatch / internal/modules/recruiting/activity_service.gofeature/aioe-upgrade2178e7298d0e5d9af83afa12402fd587f0ba6ed8Open original

Recovered source transcript

package recruiting import ( "context" "errors" "strings" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" "github.com/shopspring/decimal" "github.com/missionworkforce/missionmatch/internal/platform/tenant" ) // The recruiter activity log: what a recruiter actually did, as opposed to what moved as a result. // // One rule shapes this whole file. auto_captured is never accepted from a caller. The database trigger // discards whatever was supplied and sets it from a transaction local flag that only the capture paths // in this package raise, and LogActivityInput has no such field, so the API cannot express the claim. // A flag the subject can set about themselves would make every productivity comparison meaningless, and // that column exists for no other purpose. var activityKinds = map[string]bool{ "call": true, "email": true, "inmail": true, "text": true, "meeting": true, "note": true, "submission": true, "screen": true, } var activityDirections = map[string]bool{"outbound": true, "inbound": true, "internal": true} var activityOutcomes = map[string]bool{ "logged": true, "connected": true, "no_answer": true, "left_message": true, "replied": true, "bounced": true, "declined": true, } // connectingOutcomes are the outcomes that represent a human actually reached. The distinction matters // because a hundred dials and two conversations is a different day from a hundred conversations, and a // raw activity count reports them identically. var connectingOutcomes = map[string]bool{"connected": true, "replied": true} const activitySelect = `ra.id::text, ra.actor_user_id::text, NULLIF(ra.actor_name, ''), ra.kind, ra.direction, ra.outcome, ra.candidate_id::text, c.full_name, ra.contact_id::text, ra.requisition_id::text, r.title, ra.application_id::text, ra.body, ra.auto_captured, ra.occurred_at, ra.created_at` const activityFrom = `FROM recruiter_activities ra LEFT JOIN candidates c ON c.organization_id = ra.organization_id AND c.id = ra.candidate_id LEFT JOIN requisitions r ON r.organization_id = ra.organization_id AND r.id = ra.requisition_id` func scanActivity(row scannable) (Activity, error) { var a Activity var actorID, actorName, candID, candName, contactID, reqID, reqTitle, appID *string var occurred, created time.Time if err := row.Scan(&a.ID, &actorID, &actorName, &a.Kind, &a.Direction, &a.Outcome, &candID, &candName, &contactID, &reqID, &reqTitle, &appID, &a.Body, &a.AutoCaptured, &occurred, &created); err != nil { return Activity{}, err } a.ActorUserID, a.ActorName = str(actorID), str(actorName) a.CandidateID, a.CandidateName = str(candID), str(candName) a.ContactID, a.RequisitionID, a.RequisitionTitle = str(contactID), str(reqID), str(reqTitle) a.ApplicationID = str(appID) a.OccurredAt, a.CreatedAt = ts(occurred), ts(created) return a, nil } // LogActivity records an outreach or a note. // // occurred_at is accepted so yesterday's calls can be entered this morning, which is how recruiters // actually work. The database refuses a future date, so backdating is possible and forward dating is // not, which is the asymmetry that keeps today's number honest. func (s *Service) LogActivity(ctx context.Context, in LogActivityInput) (Activity, error) { if s.db == nil { return Activity{}, ErrNoDatabase } if !activityKinds[in.Kind] { return Activity{}, &ValidationError{Field: "kind", Message: "is not a permitted activity type"} } if in.Direction == "" { in.Direction = "outbound" } if !activityDirections[in.Direction] { return Activity{}, &ValidationError{Field: "direction", Message: "is not a permitted direction"} } if in.Outcome == "" { in.Outcome = "logged" } if !activityOutcomes[in.Outcome] { return Activity{}, &ValidationError{Field: "outcome", Message: "is not a permitted outcome"} } body, err := clean("body", in.Body, maxReqDesc) if err != nil { return Activity{}, err } candID, err := optUUID("candidate_id", in.CandidateID) if err != nil { return Activity{}, err } contactID, err := optUUID("contact_id", in.ContactID) if err != nil { return Activity{}, err } reqID, err := optUUID("requisition_id", in.RequisitionID) if err != nil { return Activity{}, err } appID, err := optUUID("application_id", in.ApplicationID) if err != nil { return Activity{}, err } // An activity about nothing is noise, and the database says so too. Asking here names the problem. if candID == nil && contactID == nil && reqID == nil && appID == nil { return Activity{}, &ValidationError{Field: "candidate_id", Message: "say who or what this was about"} } occurred, err := optTime("occurred_at", in.OccurredAt) if err != nil { return Activity{}, err } actor := actorPtr(ctx) if actor == nil { return Activity{}, tenant.ErrNoTenant } var id string err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { return insertActivity(ctx, tx, activityRow{ actor: actor, kind: in.Kind, direction: in.Direction, outcome: in.Outcome, candidateID: candID, contactID: contactID, requisitionID: reqID, applicationID: appID, body: body, occurredAt: occurred, }, &id) }) if err != nil { return Activity{}, err } return s.activityRow(ctx, id) } // activityRow is the insert shape, shared by the human path and the capture paths. type activityRow struct { actor *uuid.UUID kind string direction string outcome string candidateID *uuid.UUID contactID *uuid.UUID requisitionID *uuid.UUID applicationID *uuid.UUID body string occurredAt *time.Time } // insertActivity writes the row. actor_name is resolved at write time so the history stays legible after // the person is deleted and actor_user_id is nulled. func insertActivity(ctx context.Context, tx pgx.Tx, r activityRow, outID *string) error { var id string err := tx.QueryRow(ctx, ` INSERT INTO recruiter_activities (organization_id, actor_user_id, actor_name, kind, direction, outcome, candidate_id, contact_id, requisition_id, application_id, body, occurred_at) VALUES (NULLIF(current_setting('app.current_org_id', true), '')::uuid, $1, COALESCE((SELECT full_name FROM users WHERE id = $1), ''), $2, $3, $4, $5, $6, $7, $8, $9, COALESCE($10, now())) RETURNING id::text`, r.actor, r.kind, r.direction, r.outcome, r.candidateID, r.contactID, r.requisitionID, r.applicationID, r.body, r.occurredAt).Scan(&id) if err != nil { return translateActivityErr(err) } if outID != nil { *outID = id } return nil } // CaptureActivity records something the platform did rather than something a human typed. // // The flag is raised transaction locally, the insert happens, and the flag is cleared, so nothing else // in the same transaction is accidentally marked as captured. This is the ONLY path that can produce a // captured row, and it is not reachable from HTTP. func captureActivity(ctx context.Context, tx pgx.Tx, r activityRow) error { if _, err := tx.Exec(ctx, `SELECT set_config('app.rm_system_activity', '1', true)`); err != nil { return err } insertErr := insertActivity(ctx, tx, r, nil) if _, err := tx.Exec(ctx, `SELECT set_config('app.rm_system_activity', '', true)`); err != nil { return err } return insertErr } // CorrectActivityNote fixes a typo. Nothing else about a logged activity can change, enforced by the // database, because everything else is an input to a metric. func (s *Service) CorrectActivityNote(ctx context.Context, id string, body string) (Activity, error) { if s.db == nil { return Activity{}, ErrNoDatabase } clean, err := clean("body", body, maxReqDesc) if err != nil { return Activity{}, err } err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { tag, e := tx.Exec(ctx, `UPDATE recruiter_activities SET body = $2 WHERE id = $1::bigint`, id, clean) if e != nil { return translateActivityErr(e) } if tag.RowsAffected() == 0 { return ErrNotFound } return nil }) if err != nil { return Activity{}, err } return s.activityRow(ctx, id) } func (s *Service) activityRow(ctx context.Context, id string) (Activity, error) { var out Activity err := s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { a, e := scanActivity(tx.QueryRow(ctx, `SELECT `+activitySelect+` `+activityFrom+` WHERE ra.id = $1::bigint`, id)) if e != nil { if errors.Is(e, pgx.ErrNoRows) { return ErrNotFound } return translatePG(e) } out = a return nil }) return out, err } // ListActivities returns the feed, newest first, filtered server side. func (s *Service) ListActivities(ctx context.Context, f ActivityFilter, limit, offset int) (ActivityList, error) { if s.db == nil { return ActivityList{}, ErrNoDatabase } if limit <= 0 || limit > 200 { limit = 50 } if offset < 0 { offset = 0 } where := []string{"true"} var args []any add := func(clause string, v any) { args = append(args, v) where = append(where, strings.ReplaceAll(clause, "?", "$"+itoa(len(args)))) } switch f.Actor { case "": case "me": actor := actorPtr(ctx) if actor == nil { return ActivityList{}, tenant.ErrNoTenant } add("ra.actor_user_id = ?", *actor) default: id, err := uuid.Parse(f.Actor) if err != nil { return ActivityList{}, &ValidationError{Field: "actor", Message: "must be me or a user id"} } add("ra.actor_user_id = ?", id) } for field, raw := range map[string]string{ "candidate_id": f.CandidateID, "requisition_id": f.RequisitionID, "application_id": f.ApplicationID, } { if raw == "" { continue } id, err := uuid.Parse(raw) if err != nil { return ActivityList{}, &ValidationError{Field: field, Message: "must be an id"} } add("ra."+field+" = ?", id) } if f.Kind != "" { if !activityKinds[f.Kind] { return ActivityList{}, &ValidationError{Field: "kind", Message: "is not a permitted activity type"} } add("ra.kind = ?", f.Kind) } // Captured rows are excluded by default. A recruiter looking at their own log means what they did, // and mixing in every screen the platform ran on their behalf would drown it. if !f.IncludeCaptured { where = append(where, "NOT ra.auto_captured") } since, err := optTime("since", f.Since) if err != nil { return ActivityList{}, err } if since != nil { add("ra.occurred_at >= ?", *since) } cond := strings.Join(where, " AND ") out := ActivityList{Activities: []Activity{}, Limit: limit, Offset: offset} err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { if e := tx.QueryRow(ctx, `SELECT count(*) `+activityFrom+` WHERE `+cond, args...).Scan(&out.Total); e != nil { return translatePG(e) } rows, e := tx.Query(ctx, `SELECT `+activitySelect+` `+activityFrom+` WHERE `+cond+` ORDER BY ra.occurred_at DESC, ra.id DESC LIMIT $`+itoa(len(args)+1)+` OFFSET $`+itoa(len(args)+2), append(args, limit, offset)...) if e != nil { return translatePG(e) } defer rows.Close() for rows.Next() { a, e := scanActivity(rows) if e != nil { return translatePG(e) } out.Activities = append(out.Activities, a) } return rows.Err() }) if err != nil { return ActivityList{}, err } return out, nil } // ActivitySummary reports effort over a window, per recruiter. // // Two numbers per person, deliberately. Total is everything logged; Connects is the subset where a human // was actually reached. A hundred dials with two conversations and a hundred conversations are different // days, and a raw activity count reports them identically, which is how activity metrics come to be // gamed and then distrusted. // // Captured rows are counted separately and never pooled with logged effort. func (s *Service) ActivitySummary(ctx context.Context, sinceRaw string) (ActivitySummaryView, error) { if s.db == nil { return ActivitySummaryView{}, ErrNoDatabase } since, err := optTime("since", sinceRaw) if err != nil { return ActivitySummaryView{}, err } if since == nil { t := time.Now().UTC().AddDate(0, 0, -7) since = &t } out := ActivitySummaryView{Since: ts(*since), Recruiters: []RecruiterEffort{}, ByKind: []KindCount{}} err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { rows, e := tx.Query(ctx, ` SELECT COALESCE(ra.actor_user_id::text, ''), COALESCE(NULLIF(ra.actor_name, ''), 'Removed user'), count(*) FILTER (WHERE NOT ra.auto_captured), count(*) FILTER (WHERE NOT ra.auto_captured AND ra.outcome IN ('connected','replied')), count(*) FILTER (WHERE ra.auto_captured) FROM recruiter_activities ra WHERE ra.occurred_at >= $1 GROUP BY ra.actor_user_id, ra.actor_name ORDER BY 3 DESC, 2 ASC`, *since) if e != nil { return translatePG(e) } defer rows.Close() for rows.Next() { var r RecruiterEffort if e := rows.Scan(&r.UserID, &r.Name, &r.Logged, &r.Connects, &r.Captured); e != nil { return translatePG(e) } out.TotalLogged += r.Logged out.TotalConnects += r.Connects out.TotalCaptured += r.Captured out.Recruiters = append(out.Recruiters, r) } if e := rows.Err(); e != nil { return e } kinds, e := tx.Query(ctx, ` SELECT ra.kind, count(*) FROM recruiter_activities ra WHERE ra.occurred_at >= $1 AND NOT ra.auto_captured GROUP BY ra.kind ORDER BY 2 DESC, 1 ASC`, *since) if e != nil { return translatePG(e) } defer kinds.Close() for kinds.Next() { var k KindCount if e := kinds.Scan(&k.Kind, &k.Count); e != nil { return translatePG(e) } out.ByKind = append(out.ByKind, k) } return kinds.Err() }) if err != nil { return ActivitySummaryView{}, err } // Connect rate is computed here rather than in SQL so the division is exact decimal and guarded, and // so a zero denominator yields an absent rate rather than a claimed zero percent. for i := range out.Recruiters { out.Recruiters[i].ConnectRate = rateOf(out.Recruiters[i].Connects, out.Recruiters[i].Logged) } out.ConnectRate = rateOf(out.TotalConnects, out.TotalLogged) return out, nil } // rateOf is a share to two places, exact, and empty when the denominator is zero. A connect rate of // "0.00" on nobody dialling claims a real failure; an absent rate says there is nothing to report. func rateOf(part, total int) string { if total <= 0 { return "" } return decimal.NewFromInt(int64(part)). Mul(decimal.NewFromInt(100)). Div(decimal.NewFromInt(int64(total))). StringFixed(2) } func translateActivityErr(err error) error { var pg *pgconn.PgError if !errors.As(err, &pg) { return translatePG(err) } switch { case pg.Code == "22007" && strings.Contains(pg.Message, "in the future"): return &ValidationError{Field: "occurred_at", Message: "an activity cannot be logged in the future"} case pg.Code == "22007" && strings.Contains(pg.Message, "mistyped"): return &ValidationError{Field: "occurred_at", Message: "that date looks mistyped"} case pg.Code == "42501" && strings.Contains(pg.Message, "only its note"): return &ValidationError{Field: "body", Message: "a logged activity is a record: only its note may be corrected"} case pg.Code == "42501": return &ValidationError{Field: "id", Message: "activity history cannot be deleted"} case pg.Code == "23514" && strings.Contains(pg.ConstraintName, "subject_chk"): return &ValidationError{Field: "candidate_id", Message: "say who or what this was about"} } return translatePG(err) }

Search equations, builds, manuscript text, and recovered sources.