[Employer Sync 4.1] Implement select_employers_in_scope
TL;DR: Implement the locked selection predicate, fix the WHERE NOT IN three-valued-logic bug that drops company_id IS NULL rows, and move OBSOLETE_REMOTE_COMPANIES_IDS to JodGig::Configuration so the company sync and this sync read the same list.
Context
The sync needs to pull the right set of jodgig employer users — and only that set — on each run. The exact predicate is locked in issue 1.1.
Problem
PR #1634's scope has a real bug. Its filter ends with:
.where.not(company_id: JodGig::Companies::SyncService::OBSOLETE_REMOTE_COMPANIES_IDS)
That generates WHERE company_id NOT IN (...). Under SQL three-valued logic, NULL NOT IN (...) is NULL, not TRUE, so every row where company_id IS NULL is dropped. Super-HQ users legitimately have company_id = NULL — they link to companies through the user_company pivot. ~32 valid super-HQ users disappear from the scope, silently.
PR #1634 also reads the obsolete-company list from JodGig::Companies::SyncService — two syncs should not depend on each other's constants.
Direction
Implement select_employers_in_scope on EmployersSyncService per the predicate in 1.1:
user_types = [
JodGig::User.user_types[:SUPER_HQ_EXTERNAL],
JodGig::User.user_types[:HQ],
JodGig::User.user_types[:AREA],
JodGig::User.user_types[:LOCATION]
]
JodGig::User
.where(user_type: user_types, is_deleted: false, status: 1)
.where(
'company_id IS NULL OR company_id NOT IN (?)',
JodGig::Configuration::OBSOLETE_REMOTE_COMPANIES_IDS
)
.where(/* incremental watermark via JodGig::TimezoneService */)
Move OBSOLETE_REMOTE_COMPANIES_IDS from JodGig::Companies::SyncService to JodGig::Configuration. Both the company sync and the employer sync read it from there.
Add a post-selection filter for the company state — drop any employer whose resolved Org::Company is archived / disabled. For SUPER_HQ_EXTERNAL, drop any user whose every user_company pivot row points to an obsolete or missing company. This is the "skip-on-create" half of the data-cleaning decision; the "state-transition" half lives in 4.3.
The watermark uses JodGig::TimezoneService.format_to_naive_sgt_string(datetime: last_sync_log.started_at). Do not use + 8.hours. Coordinate with branch 1642.
Acceptance
-
OBSOLETE_REMOTE_COMPANIES_IDSlives onJodGig::Configuration; the company sync reads it from there. - Tests cover: null
company_id(kept for super-HQ, dropped for others), obsoletecompany_id(dropped), employer at astatus = 0company (dropped), enabled super-HQ with valid pivot (kept), enabled super-HQ with only obsolete pivot rows (dropped). - On the QA snapshot, the scope size matches the audit target (~1,682, within drift).
- No
+ 8.hoursliteral anywhere in the file.
Depends on
- 3.1 (the skeleton this method plugs into)